From d6e393ea58b69248e226bc661c4a6f6785732b75 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 22 Feb 2016 22:17:30 +0100 Subject: [PATCH] Inital commit --- CHANGELOG | 51 + COPYING | 632 ++ Makefile.in | 112 + README | 72 + README.develop | 68 + README.doxygen | 31 + README.md | 37 + apps/Makefile.in | 68 + apps/backend/Makefile.in | 137 + apps/backend/backend_client.c | 1066 ++++ apps/backend/backend_client.h | 64 + apps/backend/backend_commit.c | 684 ++ apps/backend/backend_commit.h | 34 + apps/backend/backend_handle.h | 43 + apps/backend/backend_lock.c | 95 + apps/backend/backend_lock.h | 37 + apps/backend/backend_main.c | 617 ++ apps/backend/backend_plugin.c | 751 +++ apps/backend/backend_plugin.h | 72 + apps/backend/backend_socket.c | 262 + apps/backend/backend_socket.h | 33 + apps/backend/clicon_backend.h | 92 + apps/backend/clicon_backend_handle.c | 353 ++ apps/backend/clicon_backend_handle.h | 71 + apps/backend/clicon_backend_transaction.c | 206 + apps/backend/clicon_backend_transaction.h | 60 + apps/backend/clicon_transaction_api.o | Bin 0 -> 7432 bytes apps/cli/Makefile.in | 134 + apps/cli/cli_common.c | 1930 ++++++ apps/cli/cli_common.h | 33 + apps/cli/cli_generate.c | 689 +++ apps/cli/cli_generate.h | 32 + apps/cli/cli_handle.c | 295 + apps/cli/cli_handle.h | 58 + apps/cli/cli_main.c | 407 ++ apps/cli/cli_plugin.c | 1153 ++++ apps/cli/cli_plugin.h | 90 + apps/cli/clicon_cli.h | 59 + apps/cli/clicon_cli_api.h | 113 + apps/dbctrl/Makefile.in | 99 + apps/dbctrl/dbctrl_main.c | 241 + apps/netconf/Makefile.in | 122 + apps/netconf/clicon_netconf.h | 73 + apps/netconf/netconf_filter.c | 633 ++ apps/netconf/netconf_filter.h | 36 + apps/netconf/netconf_hello.c | 118 + apps/netconf/netconf_hello.h | 34 + apps/netconf/netconf_lib.c | 261 + apps/netconf/netconf_lib.h | 75 + apps/netconf/netconf_main.c | 425 ++ apps/netconf/netconf_plugin.c | 277 + apps/netconf/netconf_plugin.h | 57 + apps/netconf/netconf_rpc.c | 1258 ++++ apps/netconf/netconf_rpc.h | 48 + autom4te.cache/output.0 | 5482 +++++++++++++++++ autom4te.cache/requests | 77 + autom4te.cache/traces.0 | 452 ++ clicon.conf.cpp.cpp | 124 + clicon.mk.cpp | 44 + config.guess | 1550 +++++ config.sub | 1786 ++++++ configure | 5482 +++++++++++++++++ configure.ac | 173 + doc/Doxyfile | 2303 +++++++ doc/Doxyfile.graphs | 2303 +++++++ doc/Makefile.in | 69 + etc/Makefile.in | 49 + etc/README | 14 + etc/cliconrc.in | 13 + example/Makefile.in | 114 + example/README | 27 + example/ietf-inet-types@2013-07-15.yang | 457 ++ example/ietf-interfaces@2014-05-08.yang | 698 +++ example/ietf-ip@2014-06-16.yang | 701 +++ .../ietf-ipv4-unicast-routing@2014-10-26.yang | 232 + .../ietf-ipv6-unicast-routing@2014-10-26.yang | 636 ++ example/ietf-routing@2014-10-26.yang | 1112 ++++ example/ietf-yang-types@2013-07-15.yang | 481 ++ example/routing.conf.local | 27 + example/routing_backend.c | 78 + example/routing_cli.c | 57 + example/routing_cli.cli | 45 + example/routing_netconf.c | 62 + include/Makefile.in | 49 + include/clicon_config.h.in | 122 + include/clicon_custom.h | 33 + install-sh | 250 + lib/Makefile.in | 73 + lib/clicon/Makefile.in | 44 + lib/clicon/clicon.h.in | 78 + lib/clicon/clicon_chunk.h | 166 + lib/clicon/clicon_err.h | 80 + lib/clicon/clicon_event.h | 46 + lib/clicon/clicon_file.h | 36 + lib/clicon/clicon_handle.h | 61 + lib/clicon/clicon_hash.h | 70 + lib/clicon/clicon_log.h | 57 + lib/clicon/clicon_options.h | 114 + lib/clicon/clicon_plugin.h | 67 + lib/clicon/clicon_proc.h | 33 + lib/clicon/clicon_proto.h | 183 + lib/clicon/clicon_proto_client.h | 57 + lib/clicon/clicon_proto_encode.h | 189 + lib/clicon/clicon_qdb.h | 58 + lib/clicon/clicon_queue.h | 89 + lib/clicon/clicon_sha1.h | 30 + lib/clicon/clicon_sig.h | 42 + lib/clicon/clicon_string.h | 56 + lib/clicon/clicon_xml.h | 108 + lib/clicon/clicon_xml_db.h | 42 + lib/clicon/clicon_xml_map.h | 53 + lib/clicon/clicon_xsl.h | 33 + lib/clicon/clicon_yang.h | 206 + lib/clicon/clicon_yang_type.h | 68 + lib/src/Makefile.in | 173 + lib/src/clicon_chunk.c | 778 +++ lib/src/clicon_err.c | 227 + lib/src/clicon_event.c | 309 + lib/src/clicon_file.c | 348 ++ lib/src/clicon_handle.c | 155 + lib/src/clicon_hash.c | 343 ++ lib/src/clicon_log.c | 332 + lib/src/clicon_options.c | 684 ++ lib/src/clicon_plugin.c | 73 + lib/src/clicon_proc.c | 354 ++ lib/src/clicon_proto.c | 515 ++ lib/src/clicon_proto_client.c | 524 ++ lib/src/clicon_proto_encode.c | 1038 ++++ lib/src/clicon_qdb.c | 462 ++ lib/src/clicon_sha1.c | 448 ++ lib/src/clicon_sig.c | 185 + lib/src/clicon_string.c | 346 ++ lib/src/clicon_xml.c | 1039 ++++ lib/src/clicon_xml_db.c | 1229 ++++ lib/src/clicon_xml_map.c | 845 +++ lib/src/clicon_xml_parse.h | 50 + lib/src/clicon_xml_parse.l | 138 + lib/src/clicon_xml_parse.y | 344 ++ lib/src/clicon_xpath | Bin 0 -> 25708 bytes lib/src/clicon_xsl.c | 831 +++ lib/src/clicon_yang.c | 2034 ++++++ lib/src/clicon_yang_parse.h | 85 + lib/src/clicon_yang_parse.l | 260 + lib/src/clicon_yang_parse.y | 1319 ++++ lib/src/clicon_yang_type.c | 910 +++ 145 files changed, 58117 insertions(+) create mode 100644 CHANGELOG create mode 100644 COPYING create mode 100644 Makefile.in create mode 100644 README create mode 100644 README.develop create mode 100644 README.doxygen create mode 100644 README.md create mode 100644 apps/Makefile.in create mode 100644 apps/backend/Makefile.in create mode 100644 apps/backend/backend_client.c create mode 100644 apps/backend/backend_client.h create mode 100644 apps/backend/backend_commit.c create mode 100644 apps/backend/backend_commit.h create mode 100644 apps/backend/backend_handle.h create mode 100644 apps/backend/backend_lock.c create mode 100644 apps/backend/backend_lock.h create mode 100644 apps/backend/backend_main.c create mode 100644 apps/backend/backend_plugin.c create mode 100644 apps/backend/backend_plugin.h create mode 100644 apps/backend/backend_socket.c create mode 100644 apps/backend/backend_socket.h create mode 100644 apps/backend/clicon_backend.h create mode 100644 apps/backend/clicon_backend_handle.c create mode 100644 apps/backend/clicon_backend_handle.h create mode 100644 apps/backend/clicon_backend_transaction.c create mode 100644 apps/backend/clicon_backend_transaction.h create mode 100644 apps/backend/clicon_transaction_api.o create mode 100644 apps/cli/Makefile.in create mode 100644 apps/cli/cli_common.c create mode 100644 apps/cli/cli_common.h create mode 100644 apps/cli/cli_generate.c create mode 100644 apps/cli/cli_generate.h create mode 100644 apps/cli/cli_handle.c create mode 100644 apps/cli/cli_handle.h create mode 100644 apps/cli/cli_main.c create mode 100644 apps/cli/cli_plugin.c create mode 100644 apps/cli/cli_plugin.h create mode 100644 apps/cli/clicon_cli.h create mode 100644 apps/cli/clicon_cli_api.h create mode 100644 apps/dbctrl/Makefile.in create mode 100644 apps/dbctrl/dbctrl_main.c create mode 100644 apps/netconf/Makefile.in create mode 100644 apps/netconf/clicon_netconf.h create mode 100644 apps/netconf/netconf_filter.c create mode 100644 apps/netconf/netconf_filter.h create mode 100644 apps/netconf/netconf_hello.c create mode 100644 apps/netconf/netconf_hello.h create mode 100644 apps/netconf/netconf_lib.c create mode 100644 apps/netconf/netconf_lib.h create mode 100644 apps/netconf/netconf_main.c create mode 100644 apps/netconf/netconf_plugin.c create mode 100644 apps/netconf/netconf_plugin.h create mode 100644 apps/netconf/netconf_rpc.c create mode 100644 apps/netconf/netconf_rpc.h create mode 100644 autom4te.cache/output.0 create mode 100644 autom4te.cache/requests create mode 100644 autom4te.cache/traces.0 create mode 100644 clicon.conf.cpp.cpp create mode 100644 clicon.mk.cpp create mode 100644 config.guess create mode 100644 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100644 doc/Doxyfile create mode 100644 doc/Doxyfile.graphs create mode 100644 doc/Makefile.in create mode 100644 etc/Makefile.in create mode 100644 etc/README create mode 100644 etc/cliconrc.in create mode 100644 example/Makefile.in create mode 100644 example/README create mode 100644 example/ietf-inet-types@2013-07-15.yang create mode 100644 example/ietf-interfaces@2014-05-08.yang create mode 100644 example/ietf-ip@2014-06-16.yang create mode 100644 example/ietf-ipv4-unicast-routing@2014-10-26.yang create mode 100644 example/ietf-ipv6-unicast-routing@2014-10-26.yang create mode 100644 example/ietf-routing@2014-10-26.yang create mode 100644 example/ietf-yang-types@2013-07-15.yang create mode 100644 example/routing.conf.local create mode 100644 example/routing_backend.c create mode 100644 example/routing_cli.c create mode 100644 example/routing_cli.cli create mode 100644 example/routing_netconf.c create mode 100644 include/Makefile.in create mode 100644 include/clicon_config.h.in create mode 100644 include/clicon_custom.h create mode 100755 install-sh create mode 100644 lib/Makefile.in create mode 100644 lib/clicon/Makefile.in create mode 100644 lib/clicon/clicon.h.in create mode 100644 lib/clicon/clicon_chunk.h create mode 100644 lib/clicon/clicon_err.h create mode 100644 lib/clicon/clicon_event.h create mode 100644 lib/clicon/clicon_file.h create mode 100644 lib/clicon/clicon_handle.h create mode 100644 lib/clicon/clicon_hash.h create mode 100644 lib/clicon/clicon_log.h create mode 100644 lib/clicon/clicon_options.h create mode 100644 lib/clicon/clicon_plugin.h create mode 100644 lib/clicon/clicon_proc.h create mode 100644 lib/clicon/clicon_proto.h create mode 100644 lib/clicon/clicon_proto_client.h create mode 100644 lib/clicon/clicon_proto_encode.h create mode 100644 lib/clicon/clicon_qdb.h create mode 100644 lib/clicon/clicon_queue.h create mode 100644 lib/clicon/clicon_sha1.h create mode 100644 lib/clicon/clicon_sig.h create mode 100644 lib/clicon/clicon_string.h create mode 100644 lib/clicon/clicon_xml.h create mode 100644 lib/clicon/clicon_xml_db.h create mode 100644 lib/clicon/clicon_xml_map.h create mode 100644 lib/clicon/clicon_xsl.h create mode 100644 lib/clicon/clicon_yang.h create mode 100644 lib/clicon/clicon_yang_type.h create mode 100644 lib/src/Makefile.in create mode 100644 lib/src/clicon_chunk.c create mode 100644 lib/src/clicon_err.c create mode 100644 lib/src/clicon_event.c create mode 100644 lib/src/clicon_file.c create mode 100644 lib/src/clicon_handle.c create mode 100644 lib/src/clicon_hash.c create mode 100644 lib/src/clicon_log.c create mode 100644 lib/src/clicon_options.c create mode 100644 lib/src/clicon_plugin.c create mode 100644 lib/src/clicon_proc.c create mode 100644 lib/src/clicon_proto.c create mode 100644 lib/src/clicon_proto_client.c create mode 100644 lib/src/clicon_proto_encode.c create mode 100644 lib/src/clicon_qdb.c create mode 100644 lib/src/clicon_sha1.c create mode 100644 lib/src/clicon_sig.c create mode 100644 lib/src/clicon_string.c create mode 100644 lib/src/clicon_xml.c create mode 100644 lib/src/clicon_xml_db.c create mode 100644 lib/src/clicon_xml_map.c create mode 100644 lib/src/clicon_xml_parse.h create mode 100644 lib/src/clicon_xml_parse.l create mode 100644 lib/src/clicon_xml_parse.y create mode 100644 lib/src/clicon_xpath create mode 100644 lib/src/clicon_xsl.c create mode 100644 lib/src/clicon_yang.c create mode 100644 lib/src/clicon_yang_parse.h create mode 100644 lib/src/clicon_yang_parse.l create mode 100644 lib/src/clicon_yang_parse.y create mode 100644 lib/src/clicon_yang_type.c diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 000000000..e9121e264 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,51 @@ +# 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 +# . + +- New option: CLICON_DB_XML with new xml-based database. This makes more efficient + implementation of yang-based applications. +- Changed yang type lookup to be lexically instead of dynamically scoped (as + they should) by using a cache (yang_type_cache). +- Added support for yang 'max' range keyword +- Added option: CLICON_YANG_MODULE_REVISION +- Cleaned up xml translation functions in clicon_xml_map.c +- Extended client/backend protocol with dumping a database config: CLICON_MSG_DBITEMS +- Removed -a (appdir) config options. Use only -f . +- Added INET (IPv4) communication between client and backend. Not only UNIX. Experimental. +- Removed clicon_dbmatch.[ch]. Replaced with clicon_dbitems_match(). +- Replaced internal clicon_proto_ messaging API with clicon_rpc_. +- Extended tree-based access functions: clicon_dbget_parent/children/descendents/xpath. +- clicon_dbctrl: Renamed brief option from -P to -b and made it work with -m +- Reference documentation using doxygen: make doc, make graphs +- When entering CLI commands, they appear in the same order in xml and reload. +- yang parse error using '+' in strings +- New example: clicon_yang for stateless yang experiments (no backend) +- Event subscription API: add/delete/each +- Long-term mem-leak in chunk-code +- xml parser did not support "" only "" +- fixed error in event-loop if timers are used: events before now caused hanging + +R3.0.0 23 February 2015 +======================= +This is a new major CLICON release. +The changes from previous versions are too numerous to document. +Major recent additions are: +- Added python API +- YANG modeling support +- Updated commit callback API +- Asynchronous notifications +- db2txt diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..ae47ce6cb --- /dev/null +++ b/COPYING @@ -0,0 +1,632 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + +Note the following clarification from the GNU FAQ concerning plugins +(CLIXON uses cli, netconf and backend plugins that comply to this): + +If the program dynamically links plug-ins, and they make function +calls to each other and share data structures, we believe they form a +single program, which must be treated as an extension of both the main +program and the plug-ins. This means the plug-ins must be released +under the GPL or a GPL-compatible free software license, and that the +terms of the GPL must be followed when those plug-ins are distributed. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..c4c6ac72c --- /dev/null +++ b/Makefile.in @@ -0,0 +1,112 @@ +# +# 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 +# . +# + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +# abs_top_builddir is by default the absolute path of the builddir. +includedir = @includedir@ +datadir = @datarootdir@ +localstatedir = @localstatedir@ +sysconfdir = @sysconfdir@ + +VPATH = @srcdir@ +srcdir = @srcdir@ +libdir = @libdir@ +top_srcdir = @top_srcdir@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +#INSTALL = @INSTALL@ + +INCLUDES = -I. -I@srcdir@ @INCLUDES@ +SHELL = /bin/sh + +SUBDIRS = lib apps include doc etc + +.PHONY: doc all clean depend $(SUBDIRS) install loc TAGS .config.status + +all: $(SUBDIRS) clicon.conf.cpp clicon.mk + +$(SUBDIRS): + (cd $@ && $(MAKE) $(MFLAGS) all) + +depend: + for i in $(SUBDIRS) example; \ + do (cd $$i && $(MAKE) $(MFLAGS) depend); done + +# template clicon.conf file +clicon.conf.cpp: clicon.conf.cpp.cpp + $(CPP) -P -x assembler-with-cpp -Dprefix=$(prefix) -Dlocalstatedir=$(localstatedir) -Dsysconfdir=$(sysconfdir) -Ddatadir=$(datadir) -Dlibdir=$(libdir) $< > $@ + +clicon.mk: clicon.mk.cpp + $(CPP) -P -traditional-cpp -x assembler-with-cpp -Dprefix=$(prefix) -Dlocalstatedir=$(localstatedir) -Dsysconfdir=$(sysconfdir) -Ddatadir=$(datadir) -Dlibdir=$(libdir) $< > $@ + +install: clicon.conf.cpp clicon.mk + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) $@); done; \ + install -d -m 755 $(DESTDIR)$(datadir)/clicon + install -m 755 clicon.conf.cpp $(DESTDIR)$(datadir)/clicon + install -m 755 clicon.mk $(DESTDIR)$(datadir)/clicon + echo "Install for compilation by: make install-include" + +install-include: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) $@); done; \ + echo "To install example app: cd example; make; make install" + +uninstall: + for i in $(SUBDIRS) example; \ + do (cd $$i && $(MAKE) $(MFLAGS) $@); done; + rm -f $(datadir)/clicon/clicon.conf.cpp + rm -f $(datadir)/clicon/clicon.mk + +# Overrides SUBDIRS above +#doc: +# cd $@; $(MAKE) $(MFLAGS) $@ + +config.status: configure + $(SHELL) config.status --recheck + +configure: configure.ac + cd $(srcdir) && autoconf + +clean: + for i in $(SUBDIRS) example; \ + do (cd $$i && $(MAKE) $(MFLAGS) $@); done; + +distclean: + rm -f Makefile TAGS config.status config.log *~ .depend + rm -rf Makefile autom4te.cache + rm -rf clicon.conf.cpp clicon.mk + for i in $(SUBDIRS) example; \ + do (cd $$i && $(MAKE) $(MFLAGS) $@); done + +# Lines of code +loc: + find . -name '*.[chyl]' -type f | xargs wc -l | tail -1 2> /dev/null + +TAGS: + find $(srcdir) -name '*.[chyl]' -type f | grep -v \.tab\.[ch] | grep -v lex.*.c | grep -v .yy.c | etags - + + diff --git a/README b/README new file mode 100644 index 000000000..86a25e7b6 --- /dev/null +++ b/README @@ -0,0 +1,72 @@ +This README contains information for developers: +1. How to document the code +2. How to work in git (branching) +3. How the meta-configure stuff works + +1. How to document the code ++++++++++++++++++++++++++++ + +Create documentation: +cd doc +make doc +make graphs # callgraphs + +/*! This is a small comment on one line + * + * This is a detailed description + * spanning several lines. + * + * Example usage: + * @code + * fn(a, &b); + * @endcode + * + * @param[in] src This is a description of the first parameter + * @param[in,out] dest This is a description of the second parameter + * @retval TRUE This is a description of the return value + * @retval FALSE This is a description of another return value + * @see See also this function + */ + +2. How to work in git (branching) ++++++++++++++++++++++++++++++++++ +Baically follows: http://nvie.com/posts/a-successful-git-branching-model/ +only somewhat simplified: + +Do commits in develop branch. When done, merge with master. +($ git checkout -b develop master # create develop) + +$ git checkout develop +Switch to branch develop +$ git add .. +$ git commit .. +$ git push origin develop +Add/commit stuff here (and push) + +Ready for tagging +----------------- +(This is somewhat simplified - no release branch) +$ ./bump-version.sh 3.6.0 +Files modified successfully, version bumped to 3.6.0 +$ git checkout master +Switch to master +$ git merge --no-ff develop +Merge made by recursive. +(Summary of changes) +$ git tag -a 3.6.0 + +3. How the meta-configure stuff works ++++++++++++++++++++++++++++++++++++++ +configure.ac --. + | .------> autoconf* -----> configure + [aclocal.m4] --+---+ + | `-----> [autoheader*] --> [config.h.in] + [acsite.m4] ---' + + .-------------> [config.cache] + configure* ------------+-------------> config.log + | + [config.h.in] -. v .-> [config.h] -. + +--> config.status* -+ +--> make* + Makefile.in ---' `-> Makefile ---' + diff --git a/README.develop b/README.develop new file mode 100644 index 000000000..165936309 --- /dev/null +++ b/README.develop @@ -0,0 +1,68 @@ +This README contains information for developers: +1. How to document the code +2. How to work in git (branching) +3. How the meta-configure stuff works + +1. How to document the code ++++++++++++++++++++++++++++ + +/*! This is a small comment on one line + * + * This is a detailed description + * spanning several lines. + * + * Example usage: + * @code + * fn(a, &b); + * @endcode + * + * @param[in] src This is a description of the first parameter + * @param[in,out] dest This is a description of the second parameter + * @retval TRUE This is a description of the return value + * @retval FALSE This is a description of another return value + * @see See also this function + */ + + +2. How to work in git (branching) ++++++++++++++++++++++++++++++++++ +Baically follows: http://nvie.com/posts/a-successful-git-branching-model/ +only somewhat simplified: + +Do commits in develop branch. When done, merge with master. + + +$ git checkout develop +Switch to branch develop +$ git add .. +$ git commit .. +$ git push origin develop +Add/commit stuff here (and push) + +Ready for tagging +----------------- +(This is somewhat simplified - no release branch) +$ ./bump-version.sh 3.6.0 +Files modified successfully, version bumped to 3.6.0 +$ git checkout master +Switch to master +$ git merge --no-ff develop +Merge made by recursive. +(Summary of changes) +$ git tag -a 3.6.0 + +3. How the meta-configure stuff works ++++++++++++++++++++++++++++++++++++++ +configure.ac --. + | .------> autoconf* -----> configure + [aclocal.m4] --+---+ + | `-----> [autoheader*] --> [config.h.in] + [acsite.m4] ---' + + .-------------> [config.cache] + configure* ------------+-------------> config.log + | + [config.h.in] -. v .-> [config.h] -. + +--> config.status* -+ +--> make* + Makefile.in ---' `-> Makefile ---' + diff --git a/README.doxygen b/README.doxygen new file mode 100644 index 000000000..9ad563b48 --- /dev/null +++ b/README.doxygen @@ -0,0 +1,31 @@ +/*! This is a small comment on one line + * + * This is a detailed description + * spanning several lines. + * + * Example usage: + * @code + * fn(a, &b); + * @endcode + * + * @param[in] src This is a description of the first parameter + * @param[in,out] dest This is a description of the second parameter + * @retval TRUE This is a description of the return value + * @retval FALSE This is a description of another return value + * @see anotherfn() + * @note This is just an example + */ + +/*! This is a documentation of a typedef or struct + * + * This is a detailed description + * spanning several lines. + * + * Example usage: + * @code + * struct foo f; + * @endcode + */ +typedef foo{ + int a; /**< This is the a field*/ +}; diff --git a/README.md b/README.md new file mode 100644 index 000000000..472628ef9 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +CLIXON +====== + +CLIXON is an automatic configuration manager where you from a YANG +specification generate interactive CLI, NETCONF and embedded +databases with transaction support. + +CLIXON is a fork of CLICON where legacy key specification has been +replaced completely by YANG. This means that legacy CLICON +applications such as CLICON/ROST does not run on CLIXON. + +Presentations and tutorial is found on the [CLICON project +page](http://www.clicon.org) + +A typical installation is as follows: + + > configure # Configure clixon to platform + > make # Compile + > sudo make install # Install libs, binaries, and config-files + > sudo make install-include # Install include files (for compiling) + +One example applications is provided, the IETF IP YANG datamodel with generated CLI and configuration interface. It all origins from work at +[KTH](http://www.csc.kth.se/~olofh/10G_OSR) + +[CLIgen](http://www.cligen.se) is required for building CLIXON. If you need +to build and install CLIgen: + + git clone https://github.com/olofhagsand/cligen.git + cd cligen; configure; make; make install + +CLIXON is covered by GPLv3, and is also available with commercial license. + +See COPYING for license, CHANGELOG for recent changes. + + + + diff --git a/apps/Makefile.in b/apps/Makefile.in new file mode 100644 index 000000000..c33d0b202 --- /dev/null +++ b/apps/Makefile.in @@ -0,0 +1,68 @@ +# +# 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 +# . +# +# +VPATH = @srcdir@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +SHELL = /bin/sh + +SUBDIRS = cli backend dbctrl netconf + +.PHONY: all clean depend install $(SUBDIRS) + +all: $(SUBDIRS) + +depend: + for i in $(SUBDIRS); \ + do (cd $$i; $(MAKE) $(MFLAGS) $@); done + +$(SUBDIRS): + (cd $@; $(MAKE) $(MFLAGS) all) + +install-include: + for i in $(SUBDIRS); \ + do (cd $$i ; $(MAKE) $(MFLAGS) $@); done; + +install: + for i in $(SUBDIRS); \ + do (cd $$i; $(MAKE) $(MFLAGS) $@); done + +uninstall: + for i in $(SUBDIRS); \ + do (cd $$i; $(MAKE) $(MFLAGS) $@); done + +clean: + for i in $(SUBDIRS); \ + do (cd $$i; $(MAKE) $(MFLAGS) $@); done + +distclean: clean + rm -f Makefile *~ .depend + for i in $(SUBDIRS); \ + do (cd $$i; $(MAKE) $(MFLAGS) $@); done + +tags: + find $(srcdir) -name '*.[chyl]' -print | etags - diff --git a/apps/backend/Makefile.in b/apps/backend/Makefile.in new file mode 100644 index 000000000..aea109d13 --- /dev/null +++ b/apps/backend/Makefile.in @@ -0,0 +1,137 @@ +# +# 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 +# . +# +# +VPATH = @srcdir@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +sbindir = @sbindir@ +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_BACKEND_SYSDIR = $(libdir)/clicon/plugins/backend + +# 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/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@ + +# Not accessible from plugin +APPSRC = backend_main.c backend_socket.c backend_client.c \ + backend_lock.c backend_commit.c backend_plugin.c + +APPOBJ = $(APPSRC:.c=.o) +APPL = clicon_backend + +#SHLIB = clicon_backend +MYNAME = clicon_backend +MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX) +MYLIB = $(MYLIBLINK).$(CLICON_MAJOR).$(CLICON_MINOR) +MYLIBSO = $(MYLIBLINK).$(CLICON_MAJOR) + +# Accessible from plugin +LIBSRC = clicon_backend_transaction.c clicon_backend_handle.c +LIBOBJ = $(LIBSRC:.c=.o) + +all: $(MYLIB) $(APPL) test + +clean: + rm -f *.core $(APPL) $(APPOBJ) $(LIBOBJ) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) + +distclean: clean + rm -f Makefile *~ .depend + +# Put demon 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)$(sbindir) + install $(APPL) $(DESTDIR)$(sbindir) + +install-lib: $(MYLIB) + install -d $(DESTDIR)$(libdir) + install $(MYLIB) $(DESTDIR)$(libdir) + ln -sf $(MYLIB) $(DESTDIR)$(libdir)/$(MYLIBSO) # -l:libclicon_config.so.2 + ln -sf $(MYLIBSO) $(DESTDIR)$(libdir)/$(MYLIBLINK) # -l:libclicon_config.so + install -d $(DESTDIR)$(libdir)/clicon/plugins/backend + +uninstall: + rm -f $(sbindir)/$(APPL) + rm -f $(libdir)/$(MYLIB) + rm -f $(includedir)/clicon/* + +install-include: clicon_backend.h clicon_backend_api.h + install -d $(DESTDIR)$(includedir)/clicon + install -m 644 $^ $(DESTDIR)$(includedir)/clicon + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(INCLUDES) -D__PROGRAM__=\"$(APPL)\" -DCLICON_BACKEND_SYSDIR=\"$(CLICON_BACKEND_SYSDIR)\" $(CPPFLAGS) $(CFLAGS) -c $< + +# Just link test programs +test.c : + echo "main(){}" > $@ + +test: test.c $(LIBOBJ) + $(CC) $(INCLUDES) $(LDFLAGS) $< $(LIBOBJ) -L. -l:$(MYLIB) $(LIBS) -o $@ + +$(APPL) : $(APPOBJ) $(MYLIBLINK) $(LIBDEPS) + $(CC) $(LDFLAGS) $(APPOBJ) $(OBJS) -L. -l:$(MYLIB) $(LIBS) -o $@ + +$(MYLIB): $(LIBOBJ) + $(CC) $(LDFLAGS) -shared -Wl,-soname,$(MYLIBSO) -o $@ -lc $(LIBOBJ) -Wl,-soname=$(MYLIBSO) + +# link-name is needed for application linking, eg for clicon_cli and clicon_backend +$(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 + diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c new file mode 100644 index 000000000..4eada539f --- /dev/null +++ b/apps/backend/backend_client.c @@ -0,0 +1,1066 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "backend_commit.h" +#include "backend_lock.h" +#include "backend_plugin.h" +#include "backend_client.h" +#include "backend_handle.h" + +/*! Add client notification subscription. Ie send notify to this client when event occurs + * @param[in] ce Client entry struct + * @param[in] stream Notification stream name + * @param[in] format How to display event (see enum format_enum) + * @param[in] filter Filter, what to display, eg xpath for format=xml, fnmatch + * + * @see backend_notify - where subscription is made and notify call is made + */ +static struct client_subscription * +client_subscription_add(struct client_entry *ce, + char *stream, + enum format_enum format, + char *filter) +{ + struct client_subscription *su = NULL; + + if ((su = malloc(sizeof(*su))) == NULL){ + clicon_err(OE_PLUGIN, errno, "malloc"); + goto done; + } + memset(su, 0, sizeof(*su)); + su->su_stream = strdup(stream); + su->su_format = format; + su->su_filter = strdup(filter); + su->su_next = ce->ce_subscription; + ce->ce_subscription = su; + done: + return su; +} + +static struct client_entry * +ce_find_bypid(struct client_entry *ce_list, int pid) +{ + struct client_entry *ce; + + for (ce = ce_list; ce; ce = ce->ce_next) + if (ce->ce_pid == pid) + return ce; + return NULL; +} + +static int +client_subscription_delete(struct client_entry *ce, + struct client_subscription *su0) +{ + struct client_subscription *su; + struct client_subscription **su_prev; + + su_prev = &ce->ce_subscription; /* this points to stack and is not real backpointer */ + for (su = *su_prev; su; su = su->su_next){ + if (su == su0){ + *su_prev = su->su_next; + free(su->su_stream); + if (su->su_filter) + free(su->su_filter); + free(su); + break; + } + su_prev = &su->su_next; + } + return 0; +} + +static struct client_subscription * +client_subscription_find(struct client_entry *ce, char *stream) +{ + struct client_subscription *su = NULL; + + for (su = ce->ce_subscription; su; su = su->su_next) + if (strcmp(su->su_stream, stream) == 0) + break; + + return su; +} + +/*! Remove client entry state + * Close down everything wrt clients (eg sockets, subscriptions) + * Finally actually remove client struct in handle + * @see backend_client_delete + */ +int +backend_client_rm(clicon_handle h, + struct client_entry *ce) +{ + struct client_entry *c; + struct client_entry *c0; + struct client_entry **ce_prev; + struct client_subscription *su; + + c0 = backend_client_list(h); + ce_prev = &c0; /* this points to stack and is not real backpointer */ + for (c = *ce_prev; c; c = c->ce_next){ + if (c == ce){ + if (ce->ce_s){ + event_unreg_fd(ce->ce_s, from_client); + close(ce->ce_s); + ce->ce_s = 0; + } + while ((su = ce->ce_subscription) != NULL) + client_subscription_delete(ce, su); + break; + } + ce_prev = &c->ce_next; + } + return backend_client_delete(h, ce); /* actually purge it */ +} + + +/*! Internal message: Change entry set/delete in database xmldb variant + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_change(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + uint32_t len; + char *xk; + char *dbname; + enum operation_type op; + char *str = NULL; + char *candidate_db; + char *val=NULL; + yang_spec *yspec; + + if (clicon_msg_change_decode(msg, + &dbname, + &op, + &xk, + &val, + &len, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + /* candidate is locked by other client */ + if (strcmp(dbname, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, + "lock failed: locked by %d", db_islocked(h)); + goto done; + } + + /* Update database */ + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_XML, 0, "yang spec not found"); + goto done; + } + if (xmldb_put_xkey(dbname, xk, val, yspec, op) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + if (str) + free(str); + return retval; +} + + + +/*! Internal message: Change entries as XML + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_xmlput(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + char *dbname; + enum operation_type op; + cvec *cvv = NULL; + char *str = NULL; + char *xml = NULL; + yang_spec *ys; + char *candidate_db; + cxobj *xt; + + if ((ys = clicon_dbspec_yang(h)) == NULL) + goto done; + if (clicon_msg_xmlput_decode(msg, + &dbname, + &op, + &xml, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + /* candidate is locked by other client */ + if (strcmp(dbname, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, + "lock failed: locked by %d", db_islocked(h)); + goto done; + } + if (clicon_xml_parse_string(&xml, &xt) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if (xmldb_put(dbname, xt, ys, op) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + if (str) + free(str); + if (cvv) + cvec_free (cvv); + return retval; +} + +/* Nr of snapshots. Can be made into a dynamic option */ +#define SNAPSHOTS_NR 30 +/*! dump old running_db to snapshot file #0. move all other checkpoints + * one step up + */ +int +config_snapshot(clicon_handle h, + char *dbname, + char *dir) +{ + int retval = -1; + char filename0[MAXPATHLEN]; + char filename1[MAXPATHLEN]; + struct stat st; + int i; + FILE *f = NULL; + cxobj *xn; + yang_spec *yspec = clicon_dbspec_yang(h); + + if (stat(dir, &st) < 0){ + clicon_err(OE_CFG, errno, "%s: stat(%s): %s\n", + __FUNCTION__, dir, strerror(errno)); + return -1; + } + if (!S_ISDIR(st.st_mode)){ + clicon_err(OE_CFG, 0, "%s: %s: not directory\n", + __FUNCTION__, dir); + return -1; + } + for (i=SNAPSHOTS_NR-1; i>0; i--){ + snprintf(filename0, MAXPATHLEN, "%s/%d", + dir, + i-1); + snprintf(filename1, MAXPATHLEN, "%s/%d", + dir, + i); + if (stat(filename0, &st) == 0) + if (rename(filename0, filename1) < 0){ + clicon_err(OE_CFG, errno, "%s: rename(%s, %s): %s\n", + __FUNCTION__, filename0, filename1, strerror(errno)); + return -1; + } + } + /* Make the most current snapshot */ + snprintf(filename0, MAXPATHLEN, "%s/0", dir); + if ((f = fopen(filename0, "wb")) == NULL){ + clicon_err(OE_CFG, errno, "Creating file %s", filename0); + return -1; + } + if (xmldb_get(dbname, "/", yspec, &xn) < 0) + goto done; + if (clicon_xml2file(f, xn, 0, 1) < 0) + goto done; + retval = 0; + done: + if (f != NULL) + fclose(f); + if (xn) + xml_free(xn); + return retval; +} + + +/*! Internal message: Dump/print database to file + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_save(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + char *filename; + char *archive_dir; + char *db; + uint32_t snapshot; + FILE *f = NULL; + cxobj *xn = NULL; + yang_spec *yspec; + + if (clicon_msg_save_decode(msg, + &db, + &snapshot, + &filename, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if (snapshot){ + if ((archive_dir = clicon_archive_dir(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "snapshot set and clicon_archive_dir not defined"); + goto done; + } + if (config_snapshot(h, db, archive_dir) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + + goto done; + } + } + else{ + if ((f = fopen(filename, "wb")) == NULL){ + clicon_err(OE_CFG, errno, "Creating file %s", filename); + return -1; + } + yspec = clicon_dbspec_yang(h); + if (xmldb_get(db, "/", yspec, &xn) < 0) + goto done; + if (clicon_xml2file(f, xn, 0, 1) < 0) + goto done; + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + if (f != NULL) + fclose(f); + if (xn) + xml_free(xn); + return retval; +} + +/*! Internal message: Load file into database + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_load(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) + +{ + char *filename = NULL; + int retval = -1; + char *dbname = NULL; + int replace = 0; + char *candidate_db; + int fd = -1; + cxobj *xt = NULL; + cxobj *xn; + yang_spec *yspec; + + if (clicon_msg_load_decode(msg, + &replace, + &dbname, + &filename, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + /* candidate is locked by other client */ + if (strcmp(dbname, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h)); + goto done; + } + if (replace){ + if (unlink(dbname) < 0){ + send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename, strerror(errno)); + goto done; + } + if (db_init(dbname) < 0) + goto done; + } + + if ((fd = open(filename, O_RDONLY)) < 0){ + clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename); + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if (clicon_xml_parse_file(fd, &xt, "") < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + yspec = clicon_dbspec_yang(h); + if ((xn = xml_child_i(xt, 0)) != NULL){ + if (xmldb_put(dbname, xn, yspec, replace?OP_REPLACE:OP_MERGE) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + if (fd != -1) + close(fd); + if (xt) + xml_free(xt); + return retval; +} + +/*! Internal message: Initialize database + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_initdb(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + char *filename1; + int retval = -1; + char *candidate_db; + + if (clicon_msg_initdb_decode(msg, + &filename1, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + /* candidate is locked by other client */ + if (strcmp(filename1, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h)); + goto done; + } + + if (db_init(filename1) < 0) + goto done; + /* Change mode if shared candidate. XXXX full rights for all is no good */ + if (strcmp(filename1, candidate_db) == 0) + chmod(filename1, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Remove file + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_rm(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + char *filename1; + int retval = -1; + char *candidate_db; + + if (clicon_msg_rm_decode(msg, + &filename1, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + /* candidate is locked by other client */ + if (strcmp(filename1, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h)); + goto done; + } + + if (unlink(filename1) < 0){ + send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename1, strerror(errno)); + goto done; + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Copy file from file1 to file2 + * @param[in] h Clicon handle + * @param[in] s Socket where request arrived, and where replies are sent + * @param[in] pid Unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_copy(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + char *filename1; + char *filename2; + int retval = -1; + char *candidate_db; + + if (clicon_msg_copy_decode(msg, + &filename1, + &filename2, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + + /* candidate is locked by other client */ + if (strcmp(filename2, candidate_db) == 0 && + db_islocked(h) && + pid != db_islocked(h)){ + send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h)); + goto done; + } + + if (file_cp(filename1, filename2) < 0){ + send_msg_err(s, OE_UNIX, errno, "copy %s to %s", filename1, filename2); + goto done; + } + /* Change mode if shared candidate. XXXX full rights for all is no good */ + if (strcmp(filename2, candidate_db) == 0) + chmod(filename2, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Lock database + * @param[in] h Clicon handle + * @param[in] s Client socket where request arrived, and where replies are sent + * @param[in] pid Client unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_lock(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + char *db; + int retval = -1; + char *candidate_db; + + + if (clicon_msg_lock_decode(msg, + &db, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + if (strcmp(db, candidate_db)){ + send_msg_err(s, OE_DB, 0, "can not lock %s, only %s", + db, candidate_db); + goto done; + } + if (db_islocked(h)){ + if (pid == db_islocked(h)) + ; + else{ + send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h)); + goto done; + } + } + else + db_lock(h, pid); + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Unlock database + * @param[in] h Clicon handle + * @param[in] s Client socket where request arrived, and where replies are sent + * @param[in] pid Client unix process id + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_unlock(clicon_handle h, + int s, + int pid, + struct clicon_msg *msg, + const char *label) +{ + char *db; + int retval = -1; + char *candidate_db; + + if (clicon_msg_unlock_decode(msg, + &db, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + send_msg_err(s, 0, 0, "candidate db not set"); + goto done; + } + + if (strcmp(db, candidate_db)){ + send_msg_err(s, OE_DB, 0, "can not unlock %s, only %s", + db, clicon_candidate_db(h)); + goto done; + } + if (db_islocked(h)){ + if (pid == db_islocked(h)) + db_unlock(h); + else{ + send_msg_err(s, OE_DB, 0, "unlock failed: locked by %d", db_islocked(h)); + goto done; + } + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Kill session (Kill the process) + * @param[in] h Clicon handle + * @param[in] s Client socket where request arrived, and where replies are sent + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_kill(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + uint32_t pid; /* other pid */ + int retval = -1; + struct client_entry *ce; + + if (clicon_msg_kill_decode(msg, + &pid, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + /* may or may not be in active client list, probably not */ + if ((ce = ce_find_bypid(backend_client_list(h), pid)) != NULL) + backend_client_rm(h, ce); + if (kill (pid, 0) != 0 && errno == ESRCH) /* Nothing there */ + ; + else{ + killpg(pid, SIGTERM); + kill(pid, SIGTERM); +#if 0 /* Hate sleeps we assume it died, see also 0 in next if.. */ + sleep(1); +#endif + } + if (1 || (kill (pid, 0) != 0 && errno == ESRCH)){ /* Nothing there */ + /* clear from locks */ + if (db_islocked(h) == pid) + db_unlock(h); + } + else{ /* failed to kill client */ + send_msg_err(s, OE_DB, 0, "failed to kill %d", pid); + goto done; + } + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: Set debug level. This is global, not just for the session. + * @param[in] h Clicon handle + * @param[in] s Client socket where request arrived, and where replies are sent + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_debug(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + uint32_t level; + + if (clicon_msg_debug_decode(msg, + &level, + label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */ + + if (send_msg_ok(s) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Internal message: downcall backend plugin + * @param[in] h Clicon handle + * @param[in] s Client socket where request arrived, and where replies are sent + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_call(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + void *reply_data = NULL; + uint16_t reply_data_len = 0; + struct clicon_msg_call_req *req; + + if (clicon_msg_call_decode(msg, &req, label) < 0) { + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } +#ifdef notyet + if (!strlen(req->cr_plugin)) /* internal */ + internal_function(req, &reply_data_len, &reply_data); + else +#endif + if (plugin_downcall(h, req, &reply_data_len, &reply_data) < 0) { + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + + retval = send_msg_reply(s,CLICON_MSG_OK, (char *)reply_data, reply_data_len); + free(reply_data); + + done: + return retval; +} + +/*! Internal message: Create subscription for notifications + * @param[in] h Clicon handle + * @param[in] ce Client entry (from). + * @param[in] msg Message + * @param[in] label Memory chunk + * @retval 0 OK + * @retval -1 Error. Send error message back to client. + */ +static int +from_client_subscription(clicon_handle h, + struct client_entry *ce, + struct clicon_msg *msg, + const char *label) +{ + int status; + enum format_enum format; + char *stream; + char *filter; + int retval = -1; + struct client_subscription *su; + clicon_log_notify_t *old; + + if (clicon_msg_subscription_decode(msg, + &status, + &stream, + &format, + &filter, + label) < 0){ + send_msg_err(ce->ce_s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + + if (status){ + if ((su = client_subscription_add(ce, stream, format, filter)) == NULL){ + send_msg_err(ce->ce_s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto done; + } + } + else{ + if ((su = client_subscription_find(ce, stream)) != NULL) + client_subscription_delete(ce, su); + } + /* Avoid recursion when sending logs */ + old = clicon_log_register_callback(NULL, NULL); + if (send_msg_ok(ce->ce_s) < 0) + goto done; + clicon_log_register_callback(old, h); /* XXX: old h */ + retval = 0; + done: + return retval; +} + +/*! An internal clicon message has arrived from a client. Receive and dispatch. + * @param[in] s Socket where message arrived. read from this. + * @param[in] arg Client entry (from). + * @retval 0 OK + * @retval -1 Error Terminates backend and is never called). Instead errors are + * propagated back to client. + */ +int +from_client(int s, void* arg) +{ + struct client_entry *ce = (struct client_entry *)arg; + clicon_handle h = ce->ce_handle; + struct clicon_msg *msg; + enum clicon_msg_type type; + int eof; + + assert(s == ce->ce_s); + if (clicon_msg_rcv(ce->ce_s, &msg, &eof, __FUNCTION__) < 0) + goto done; + if (eof){ + backend_client_rm(h, ce); + goto done; + } + type = ntohs(msg->op_type); + switch (type){ + case CLICON_MSG_COMMIT: + if (from_client_commit(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_VALIDATE: + if (from_client_validate(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_CHANGE: + if (from_client_change(h, ce->ce_s, ce->ce_pid, msg, + (char *)__FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_XMLPUT: + if (from_client_xmlput(h, ce->ce_s, ce->ce_pid, msg, + (char *)__FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_SAVE: + if (from_client_save(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_LOAD: + if (from_client_load(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_RM: + if (from_client_rm(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_INITDB: + if (from_client_initdb(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_COPY: + if (from_client_copy(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_LOCK: + if (from_client_lock(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_UNLOCK: + if (from_client_unlock(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_KILL: + if (from_client_kill(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_DEBUG: + if (from_client_debug(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_CALL: + if (from_client_call(h, ce->ce_s, msg, __FUNCTION__) < 0) + goto done; + break; + case CLICON_MSG_SUBSCRIPTION: + if (from_client_subscription(h, ce, msg, __FUNCTION__) < 0) + goto done; + break; + default: + send_msg_err(s, OE_PROTO, 0, "Unexpected message: %d", type); + goto done; + } +// retval = 0; + done: + unchunk_group(__FUNCTION__); +// return retval; + return 0; // -1 here terminates +} + diff --git a/apps/backend/backend_client.h b/apps/backend/backend_client.h new file mode 100644 index 000000000..4a6ca2092 --- /dev/null +++ b/apps/backend/backend_client.h @@ -0,0 +1,64 @@ +/* + * + 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 + . + */ + +#ifndef _BACKEND_CLIENT_H_ +#define _BACKEND_CLIENT_H_ + +/* + * Types + */ +/* + * Client entry. + * Keep state about every connected client. + */ +struct client_entry{ + struct client_entry *ce_next; /* The clients linked list */ + struct sockaddr ce_addr; /* The clients (UNIX domain) address */ + int ce_s; /* stream socket to client */ + int ce_nr; /* Client number (for dbg/tracing) */ + int ce_stat_in; /* Nr of received msgs from client */ + int ce_stat_out;/* Nr of sent msgs to client */ + int ce_pid; /* Process id */ + int ce_uid; /* User id of calling process */ + clicon_handle ce_handle; /* clicon config handle (all clients have same?) */ + struct client_subscription *ce_subscription; /* notification subscriptions */ +}; + +/* Notification subscription info + * @see subscription in config_handle.c + */ +struct client_subscription{ + struct client_subscription *su_next; + int su_s; /* stream socket */ + enum format_enum su_format; /* format of notification stream */ + char *su_stream; + char *su_filter; +}; + +/* + * Prototypes + */ +int backend_client_rm(clicon_handle h, struct client_entry *ce); +int config_snapshot(clicon_handle h, char *dbname, char *dir); + +int from_client(int fd, void *arg); + +#endif /* _BACKEND_CLIENT_H_ */ diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c new file mode 100644 index 000000000..d8b0524dc --- /dev/null +++ b/apps/backend/backend_commit.c @@ -0,0 +1,684 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_backend_transaction.h" +#include "backend_plugin.h" +#include "backend_handle.h" +#include "backend_commit.h" +#include "backend_client.h" + +/*! Key values are checked for validity independent of user-defined callbacks + * + * Key values are checked as follows: + * 1. If no value and default value defined, add it. + * 2. If no value and mandatory flag set in spec, report error. + * 3. Validate value versus spec, and report error if no match. Currently only int ranges and + * string regexp checked. + * See also db_lv_set() where defaults are also filled in. The case here for defaults + * are if code comes via XML/NETCONF. + * @param yspec Yang spec + * @param td Transaction data + */ +static int +generic_validate(yang_spec *yspec, + transaction_data_t *td) +{ + int retval = -1; + cxobj *x1; + cxobj *x2; + int i; + yang_stmt *ys; + + /* changed entries */ + for (i=0; itd_clen; i++){ + x1 = td->td_scvec[i]; /* source changed */ + x2 = td->td_tcvec[i]; /* target changed */ + ys = xml_spec(x1); + if (xml_yang_validate(x2, ys) < 0) + goto done; + } + /* deleted entries */ + for (i=0; itd_dlen; i++){ + x1 = td->td_dvec[i]; + ys = xml_spec(x1); + if (yang_mandatory(ys)){ + clicon_err(OE_CFG, 0,"Removed mandatory variable: %s", + xml_name(x1)); + goto done; + } + } + /* added entries */ + for (i=0; itd_alen; i++){ + x2 = td->td_avec[i]; + if (xml_yang_validate(x2, xml_spec(x2)) < 0) + goto done; + if (xml_apply(x2, CX_ELMNT, + (xml_applyfn_t*)xml_yang_validate, NULL) < 0) + goto done; + } + retval = 0; + done: + return retval; +} + +/*! Do a diff between candidate and running, then start a commit transaction + * + * The code reverts changes if the commit fails. But if the revert + * fails, we just ignore the errors and proceed. Maybe we should + * do something more drastic? + * @param[in] h Clicon handle + * @param[in] running The current database. The original backend state + * @param[in] candidate: The candidate database. The wanted backend state +*/ +int +candidate_commit(clicon_handle h, + char *candidate, + char *running) +{ + int retval = -1; + // int i, j; + // int failed = 0; + struct stat sb; + void *firsterr = NULL; + yang_spec *yspec; + transaction_data_t *td = NULL; + + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_FATAL, 0, "No DB_SPEC"); + goto done; + } + /* Sanity checks that databases exists. */ + if (stat(running, &sb) < 0){ + clicon_err(OE_DB, errno, "%s", running); + goto done; + } + if (stat(candidate, &sb) < 0){ + clicon_err(OE_DB, errno, "%s", candidate); + goto done; + } + + /* 1. Start transaction */ + if ((td = transaction_new()) == NULL) + goto done; + + /* 2. Parse xml trees */ + if (xmldb_get(running, "/", yspec, &td->td_src) < 0) + goto done; + if (xmldb_get(candidate, "/", yspec, &td->td_target) < 0) + goto done; + + /* 3. Compute differences */ + if (xml_diff(yspec, + td->td_src, + td->td_target, + &td->td_dvec, /* removed: only in running */ + &td->td_dlen, + &td->td_avec, /* added: only in candidate */ + &td->td_alen, + &td->td_scvec, /* changed: original values */ + &td->td_tcvec, /* changed: wanted values */ + &td->td_clen) < 0) + goto done; + if (debug) + transaction_print(stderr, td); + + /* 4. Call plugin transaction start callbacks */ + if (plugin_transaction_begin(h, td) < 0) + goto done; + + /* 5. Make generic validation on all new or changed data. */ + if (generic_validate(yspec, td) < 0) + goto done; + + /* 6. Call plugin transaction validate callbacks */ + if (plugin_transaction_validate(h, td) < 0) + goto done; + + /* 7. Call plugin transaction complete callbacks */ + if (plugin_transaction_complete(h, td) < 0) + goto done; + + /* 7. Call plugin transaction commit callbacks */ + if (plugin_transaction_commit(h, td) < 0) + goto done; + + /* 8. Copy running back to candidate in case end functions triggered + updates in running */ + if (file_cp(running, candidate) < 0){ + /* ignore errors or signal major setback ? */ + clicon_err(OE_UNIX, errno, "file_cp(running, candidate)"); + clicon_log(LOG_NOTICE, "Error in rollback, trying to continue"); + goto done; + } + + /* 9. Call plugin transaction end callbacks */ + plugin_transaction_end(h, td); + +#ifdef OBSOLETE + /* Find the differences between the two databases and store it in df vector. */ + memset(&df, 0, sizeof(df)); + if (db_diff(running, candidate, + __FUNCTION__, + clicon_dbspec_key(h), + &df + ) < 0) + goto done; + + if (debug){ + struct dbdiff_ent *dfe; + for (i=0; idfe_op, + cvec_name_get(dfe->dfe_vec1?dfe->dfe_vec1:dfe->dfe_vec2)); + } + } + /* 1. Get commit processing to dbdiff vector: one entry per key that changed. + changes are registered as if they exist in the 1st(candidate) or + 2nd(running) dbs. + */ + if (dbdep_commitvec(h, &df, &nvec, &ddvec) < 0) + goto done; + + /* 2. Call transaction_begin hooks */ + if (plugin_transaction_begin(h) < 0) + goto done; + + /* call generic cv_validate() on all new or changed keys. */ + if (generic_validate(yspec, NULL) < 0) + goto done; + + /* user-defined validate callbacks registered in dbdep_validate */ + // if (validate_db(h, nvec, ddvec, running, candidate) < 0) + // goto done; + + /* Call plugin post-commit hooks */ + if (plugin_transaction_complete(h) < 0) + goto done; + + if (clicon_commit_order(h) == 0){ + for (i=0; i < nvec; i++){ /* revert in opposite order */ + dd = &ddvec[i]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + if (plugin_commit_callback(h, + op, /* oper */ + running, /* db1 */ + candidate, /* db2 */ + dd->dd_mkey1, /* key1 */ + dd->dd_mkey2, /* key2 */ + dd->dd_dbdiff->dfe_vec1, /* vec1 */ + dd->dd_dbdiff->dfe_vec2, /* vec2 */ + dp /* callback */ + ) < 0){ + firsterr = clicon_err_save(); /* save this error */ + failed++; + break; + } + } + if (!failed) + if (file_cp(candidate, running) < 0){ /* Commit here in case cp fails */ + clicon_err(OE_UNIX, errno, "file_cp"); + failed++; + } + /* Failed operation, start error handling: rollback in opposite order */ + if (failed){ + for (j=i-1; j>=0; j--){ /* revert in opposite order */ + dd = &ddvec[j]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + switch (op){ /* reverse operation */ + case CO_ADD: + op = CO_DELETE; + break; + case CO_DELETE: + op = CO_ADD; + break; + default: + break; + } + if (plugin_commit_callback(h, + op, /* oper */ + candidate, /* db1 */ + running, /* db2 */ + dd->dd_mkey2, /* key1 */ + dd->dd_mkey1, /* key2 */ + dd->dd_dbdiff->dfe_vec2, /* vec1 */ + dd->dd_dbdiff->dfe_vec1, /* vec2 */ + dp /* callback */ + ) < 0){ + /* ignore errors or signal major setback ? */ + clicon_log(LOG_NOTICE, "Error in rollback, trying to continue"); + continue; + } + } + goto done; + } /* error handling */ + } + else { /* commit_order == 1 or 2 */ + /* Now follows commit rules in order. + * 4. For all keys that are not in candidate but in running, delete key + * in reverse prio order + */ + for (i = nvec-1; i >= 0; i--){ + dd = &ddvec[i]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + /* original mode 2 where CHANGE=DEL/ADD */ + if (clicon_commit_order(h) == 2 && op == CO_CHANGE) + op = CO_DELETE; + if (op != CO_DELETE) + continue; + if (plugin_commit_callback(h, + op, /* oper */ + running, /* db1 */ + candidate, /* db2 */ + dd->dd_mkey1, /* key1 */ + dd->dd_mkey2, /* key2 */ + dd->dd_dbdiff->dfe_vec1, /* vec1 */ + dd->dd_dbdiff->dfe_vec2, /* vec2 */ + dp /* callback */ + ) < 0){ + firsterr = clicon_err_save(); /* save this error */ + break; + } + } + /* 5. Failed deletion, add the key value back to running */ + if (i >= 0){ /* failed */ + for (j=i+1; jdd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + /* original mode 2 where CHANGE=DEL/ADD */ + if (clicon_commit_order(h) == 2 && op == CO_CHANGE) + op = CO_DELETE; + if (op != CO_DELETE) + continue; + if (plugin_commit_callback(h, + op, /* oper */ + candidate, /* db1 */ + running, /* db2 */ + dd->dd_mkey2, /* key1 */ + dd->dd_mkey1, /* key2 */ + dd->dd_dbdiff->dfe_vec2, /* vec1 */ + dd->dd_dbdiff->dfe_vec1, /* vec2 */ + dp /* callback */ + ) < 0){ + /* ignore errors or signal major setback ? */ + clicon_log(LOG_NOTICE, "Error in rollback, trying to continue"); + continue; + } + } + goto done; + } + /* + * 6. For all added or changed keys + */ + for (i=0; i < nvec; i++){ + dd = &ddvec[i]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + if (op != CO_CHANGE && op != CO_ADD) + continue; + /* original mode 2 where CHANGE=DEL/ADD */ + if (clicon_commit_order(h) == 2 && op == CO_CHANGE) + op = CO_ADD; + if (plugin_commit_callback(h, + op, /* oper */ + running, /* db1 */ + candidate, /* db2 */ + dd->dd_mkey1, /* key1 */ + dd->dd_mkey2, /* key2 */ + dd->dd_dbdiff->dfe_vec1, /* vec1 */ + dd->dd_dbdiff->dfe_vec2, /* vec2 */ + dp /* callback */ + ) < 0){ + firsterr = clicon_err_save(); /* save this error */ + failed++; + break; + } + } + if (!failed) /* Commit here in case cp fails */ + if (file_cp(candidate, running) < 0){ + clicon_err(OE_UNIX, errno, "file_cp(candidate; running)"); + failed++; + } + /* 10. Failed setting keys in running, first remove the keys set */ + if (failed){ /* failed */ + for (j=i-1; j>=0; j--){ /* revert in opposite order */ + dd = &ddvec[j]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + if (op != CO_CHANGE && op != CO_ADD) + continue; + /* original mode 2 where CHANGE=DEL/ADD */ + if (clicon_commit_order(h) == 2 && op == CO_CHANGE) + op = CO_ADD; + if (op == CO_ADD) /* reverse op */ + op = CO_DELETE; + if (plugin_commit_callback(h, + op, /* oper */ + candidate, /* db1 */ + running, /* db2 */ + dd->dd_mkey2, /* key1 */ + dd->dd_mkey1, /* key2 */ + dd->dd_dbdiff->dfe_vec2, /* vec1 */ + dd->dd_dbdiff->dfe_vec1, /* vec2 */ + dp /* callback */ + ) < 0){ + /* ignore errors or signal major setback ? */ + clicon_log(LOG_NOTICE, "Error in rollback, trying to continue"); + continue; + } + } + for (j=0; j < nvec; j++){ /* revert in opposite order */ + dd = &ddvec[j]; + dp = dd->dd_dep; /* op, callback, arg */ + if ((dp->dp_type & TRANS_CB_COMMIT) == 0) + continue; + dfe = dd->dd_dbdiff; /* key1/key2/op */ + op = dbdiff2commit_op(dfe->dfe_op); + /* original mode 2 where CHANGE=DEL/ADD */ + if (clicon_commit_order(h) == 2 && op == CO_CHANGE) + op = CO_DELETE; + if (op != CO_DELETE) + continue; + op = CO_ADD; + if (plugin_commit_callback(h, + op, /* oper */ + candidate, /* db1 */ + running, /* db2 */ + dd->dd_mkey2, /* key1 */ + dd->dd_mkey1, /* key2 */ + dd->dd_dbdiff->dfe_vec2, /* vec1 */ + dd->dd_dbdiff->dfe_vec1, /* vec2 */ + dp /* callback */ + ) < 0){ + /* ignore errors or signal major setback ? */ + clicon_log(LOG_NOTICE, "Error in rollback, trying to continue"); + continue; + } + } + goto done; + } + } /* commit_order */ +#endif /* OBSOLETE */ + + + retval = 0; + done: + /* In case of failure, call plugin transaction termination callbacks */ + if (retval < 0 && td) + plugin_transaction_abort(h, td); + if (td) + transaction_free(td); + if (firsterr) + clicon_err_restore(firsterr); + return retval; +} + +/*! Do a diff between candidate and running, then start a validate transaction + * + * @param[in] h Clicon handle + * @param[in] running The current database. The original backend state + * @param[in] candidate: The candidate database. The wanted backend state +*/ +int +candidate_validate(clicon_handle h, + char *candidate, + char *running) + { + int retval = -1; + struct stat sb; + yang_spec *yspec; + transaction_data_t *td = NULL; + + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_FATAL, 0, "No DB_SPEC"); + goto done; + } + /* Sanity checks that databases exists. */ + if (stat(running, &sb) < 0){ + clicon_err(OE_DB, errno, "%s", running); + goto done; + } + if (stat(candidate, &sb) < 0){ + clicon_err(OE_DB, errno, "%s", candidate); + goto done; + } + + /* 1. Start transaction */ + if ((td = transaction_new()) == NULL) + goto done; + + /* 2. Parse xml trees */ + if (xmldb_get(running, "/", yspec, &td->td_src) < 0) + goto done; + if (xmldb_get(candidate, "/", yspec, &td->td_target) < 0) + goto done; + + /* 3. Compute differences */ + if (xml_diff(yspec, + td->td_src, + td->td_target, + &td->td_dvec, /* removed: only in running */ + &td->td_dlen, + &td->td_avec, /* added: only in candidate */ + &td->td_alen, + &td->td_scvec, /* changed: original values */ + &td->td_tcvec, /* changed: wanted values */ + &td->td_clen) < 0) + goto done; + + if (debug) + transaction_print(stderr, td); + + /* 4. Call plugin start transaction callbacks */ + if (plugin_transaction_begin(h, td) < 0) + goto done; + + /* 5. Make generic validation on all new or changed data. */ + if (generic_validate(yspec, td) < 0) + goto done; + + /* 6. Call plugin validate transaction callbacks */ + if (plugin_transaction_validate(h, td) < 0) + goto done; + + /* 7. Call plugin complete transaction callbacks */ + if (plugin_transaction_complete(h, td) < 0) + goto done; + + retval = 0; + done: + /* In case of failure, call plugin transaction termination callbacks */ + if (retval < 0 && td) + plugin_transaction_abort(h, td); + if (td) + transaction_free(td); + return retval; + } + + +/*! Handle an incoming commit message from a client. + * XXX: If commit succeeds and snapshot/startup fails, we have strange state: + * the commit has succeeded but an error message is returned. + */ +int +from_client_commit(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + int retval = -1; + char *candidate; + char *running; + uint32_t snapshot; + uint32_t startup; + char *snapshot_0; + char *archive_dir; + char *startup_config; + + if (clicon_msg_commit_decode(msg, &candidate, &running, + &snapshot, &startup, label) < 0) + goto err; + + if (candidate_commit(h, candidate, running) < 0){ + clicon_debug(1, "Commit %s failed", candidate); + retval = 0; /* We ignore errors from commit, but maybe + we should fail on fatal errors? */ + goto err; + } + clicon_debug(1, "Commit %s", candidate); + if (snapshot){ + if ((archive_dir = clicon_archive_dir(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "snapshot set and clicon_archive_dir not defined"); + goto err; + } + if (config_snapshot(h, running, archive_dir) < 0) + goto err; + } + + if (startup){ + if ((archive_dir = clicon_archive_dir(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "startup set but clicon_archive_dir not defined"); + goto err; + } + if ((startup_config = clicon_startup_config(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "startup set but startup_config not defined"); + goto err; + } + snapshot_0 = chunk_sprintf(__FUNCTION__, "%s/0", archive_dir); + if (file_cp(snapshot_0, startup_config) < 0){ + clicon_err(OE_PROTO, errno, "%s: Error when creating startup", + __FUNCTION__); + goto err; + } + } + retval = 0; + if (send_msg_ok(s) < 0) + goto done; + goto done; + err: + /* XXX: more elaborate errstring? */ + if (send_msg_err(s, clicon_errno, clicon_suberrno, "%s", clicon_err_reason) < 0) + retval = -1; + done: + unchunk_group(__FUNCTION__); + + return retval; /* may be zero if we ignoring errors from commit */ +} /* from_client_commit */ + + + +/* + * Call backend plugin + */ +int +from_client_validate(clicon_handle h, + int s, + struct clicon_msg *msg, + const char *label) +{ + char *dbname; + char *running_db; + int retval = -1; + + if (clicon_msg_validate_decode(msg, &dbname, label) < 0){ + send_msg_err(s, clicon_errno, clicon_suberrno, + clicon_err_reason); + goto err; + } + + clicon_debug(1, "Validate %s", dbname); + if ((running_db = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto err; + } + if (candidate_validate(h, dbname, running_db) < 0){ + clicon_debug(1, "Validate %s failed", dbname); + retval = 0; /* We ignore errors from commit, but maybe + we should fail on fatal errors? */ + goto err; + } + retval = 0; + if (send_msg_ok(s) < 0) + goto done; + goto done; + err: + /* XXX: more elaborate errstring? */ + if (send_msg_err(s, clicon_errno, clicon_suberrno, "%s", clicon_err_reason) < 0) + retval = -1; + done: + unchunk_group(__FUNCTION__); + return retval; +} /* from_client_validate */ diff --git a/apps/backend/backend_commit.h b/apps/backend/backend_commit.h new file mode 100644 index 000000000..1e7ffe252 --- /dev/null +++ b/apps/backend/backend_commit.h @@ -0,0 +1,34 @@ +/* + * + 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 + . + + */ + + +#ifndef _BACKEND_COMMIT_H_ +#define _BACKEND_COMMIT_H_ + +/* + * Prototypes + */ +int from_client_validate(clicon_handle h, int s, struct clicon_msg *msg, const char *label); +int from_client_commit(clicon_handle h, int s, struct clicon_msg *msg, const char *label); +int candidate_commit(clicon_handle h, char *candidate, char *running); + +#endif /* _BACKEND_COMMIT_H_ */ diff --git a/apps/backend/backend_handle.h b/apps/backend/backend_handle.h new file mode 100644 index 000000000..bee871330 --- /dev/null +++ b/apps/backend/backend_handle.h @@ -0,0 +1,43 @@ +/* + * + 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 + . + + * + */ + +#ifndef _BACKEND_HANDLE_H_ +#define _BACKEND_HANDLE_H_ + + +/* + * Prototypes + * not exported. + */ +/* backend handles */ +clicon_handle backend_handle_init(void); + +int backend_handle_exit(clicon_handle h); + +struct client_entry *backend_client_add(clicon_handle h, struct sockaddr *addr); + +struct client_entry *backend_client_list(clicon_handle h); + +int backend_client_delete(clicon_handle h, struct client_entry *ce); + +#endif /* _BACKEND_HANDLE_H_ */ diff --git a/apps/backend/backend_lock.c b/apps/backend/backend_lock.c new file mode 100644 index 000000000..8a33bbb47 --- /dev/null +++ b/apps/backend/backend_lock.c @@ -0,0 +1,95 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "backend_lock.h" + +/* + * Easy way out: store an integer for candidate db which contains + * the session-id of the client holding the lock. + * more general: any database + * we dont make any sanity check on who is locking. + */ +static int _db_locked = 0; + +/* + * db_lock + */ +int +db_lock(clicon_handle h, int id) +{ + _db_locked = id; + clicon_debug(1, "%s: lock db by %u", __FUNCTION__, id); + return 0; +} + +/* + * db_unlock + */ +int +db_unlock(clicon_handle h) +{ + if (!_db_locked ) + return 0; + _db_locked = 0; + return 0; +} + +/* + * db_islocked + * returns id of locker + */ +int +db_islocked(clicon_handle h) +{ + return _db_locked; +} + diff --git a/apps/backend/backend_lock.h b/apps/backend/backend_lock.h new file mode 100644 index 000000000..fa5c604fc --- /dev/null +++ b/apps/backend/backend_lock.h @@ -0,0 +1,37 @@ +/* + * + 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 + . + + * + * Database logical lock functions. + * Only one lock (candidate_db) + * Not persistent (needs another db) + */ + +#ifndef _BACKEND_LOCK_H_ +#define _BACKEND_LOCK_H_ + +/* + * Prototypes + */ +int db_lock(clicon_handle h, int id); +int db_unlock(clicon_handle h); +int db_islocked(clicon_handle h); + +#endif /* _BACKEND_LOCK_H_ */ diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c new file mode 100644 index 000000000..a399ceecd --- /dev/null +++ b/apps/backend/backend_main.c @@ -0,0 +1,617 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_backend_handle.h" +#include "backend_socket.h" +#include "backend_client.h" +#include "backend_commit.h" +#include "backend_plugin.h" +#include "backend_handle.h" + +/* Command line options to be passed to getopt(3) */ +#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc::rg:pt" + +/* Cannot use h after this */ +static int +config_terminate(clicon_handle h) +{ + yang_spec *yspec; + char *pidfile = clicon_backend_pidfile(h); + char *sockpath = clicon_sock(h); + + clicon_debug(1, "%s", __FUNCTION__); + if ((yspec = clicon_dbspec_yang(h)) != NULL) + yspec_free(yspec); + plugin_finish(h); + if (pidfile) + unlink(pidfile); + if (sockpath) + unlink(sockpath); + backend_handle_exit(h); /* Cannot use h after this */ + clicon_log_register_callback(NULL, NULL); + clicon_debug(1, "%s done", __FUNCTION__); + if (debug) + chunk_check(stderr, NULL); + return 0; +} + +/* + config_sig_term + Unlink pidfile and quit +*/ +static void +config_sig_term(int arg) +{ + static int i=0; + if (i++ == 0) + clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d", + __PROGRAM__, __FUNCTION__, getpid(), arg); + clicon_exit_set(); /* checked in event_loop() */ +} + +/* + * usage + */ +static void +usage(char *argv0, clicon_handle h) +{ + char *plgdir = clicon_backend_dir(h); + char *confsock = clicon_sock(h); + char *confpid = clicon_backend_pidfile(h); + char *startup = clicon_startup_config(h); + char *group = clicon_sock_group(h); + + fprintf(stderr, "usage:%s\n" + "where options are\n" + " -h\t\tHelp\n" + " -D \tdebug\n" + " -f \tCLICON config file (mandatory)\n" + " -d \tSpecify backend plugin directory (default: %s)\n" + " -z\t\tKill other config daemon and exit\n" + " -F\t\tforeground\n" + " -1\t\tonce (dont wait for events)\n" + " -u \tconfig UNIX domain path / ip address (default: %s)\n" + " -P \tPid filename (default: %s)\n" + " -I\t\tInitialize running state database\n" + " -R\t\tCall plugin_reset() in plugins to reset system state in running db (use with -I)\n" + " -C\t\tCall plugin_reset() in plugins to reset system state in candidate db (use with -I)\n" + " -c []\tLoad specified application config. Default is\n" + " \t\"CLICON_STARTUP_CONFIG\" = %s\n" + " -r\t\tReload running database\n" + " -p \t\tPrint database yang specification\n" + " -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n" + " -g \tClient membership required to this group (default: %s)\n", + argv0, + plgdir ? plgdir : "none", + confsock ? confsock : "none", + confpid ? confpid : "none", + startup ? startup : "none", + group ? group : "none" + ); + exit(0); +} + +static int +rundb_init(clicon_handle h, char *running_db) +{ + if (unlink(running_db) != 0 && errno != ENOENT) { + clicon_err(OE_UNIX, errno, "unlink"); + return -1; + } + if (db_init(running_db) < 0) + return -1; + + return 0; +} + +/*! Initialize running-config from file application configuration + * + * @param[in] h clicon handle + * @param[in] app_config_file clicon application configuration file + * @param[in] running_db Name of running db + * @retval 0 OK + * @retval -1 Error. clicon_err set + */ +static int +rundb_main(clicon_handle h, + char *app_config_file, + char *running_db) +{ + char *tmp = NULL; + int retval = -1; + int fd = -1; + yang_spec *yspec; + cxobj *xt = NULL; + cxobj *xn; + + if ((tmp = clicon_tmpfile(__FUNCTION__)) == NULL) + goto done; + if (file_cp(running_db, tmp) < 0){ + clicon_err(OE_UNIX, errno, "file copy"); + goto done; + } + if ((fd = open(app_config_file, O_RDONLY)) < 0){ + clicon_err(OE_UNIX, errno, "open(%s)", app_config_file); + goto done; + } + if (clicon_xml_parse_file(fd, &xt, "") < 0) + goto done; + yspec = clicon_dbspec_yang(h); + if ((xn = xml_child_i(xt, 0)) != NULL) + if (xmldb_put(tmp, xn, yspec, OP_MERGE) < 0) + goto done; + if (candidate_commit(h, tmp, running_db) < 0) + goto done; + retval = 0; +done: + if (tmp) + unlink(tmp); + if (xt) + xml_free(xt); + if (fd != -1) + close(fd); + unchunk_group(__FUNCTION__); + return retval; +} + + +static int +candb_reset(clicon_handle h, char *running_db) +{ + int retval = -1; + char *tmp = NULL; + + if ((tmp = clicon_tmpfile(__FUNCTION__)) == NULL) + goto done; + if (file_cp(running_db, tmp) < 0){ + clicon_err(OE_UNIX, errno, "file copy"); + goto done; + } + /* Request plugins to reset system state, eg initiate running from system + * -R + */ + if (plugin_reset_state(h, tmp) < 0) + goto done; + if (candidate_commit(h, tmp, running_db) < 0) + goto done; + retval = 0; + done: + if (tmp) + unlink(tmp); + unchunk_group(__FUNCTION__); + return retval; +} + + +/*! Create backend server socket and register callback + */ +static int +server_socket(clicon_handle h) +{ + int ss; + + /* Open control socket */ + if ((ss = config_socket_init(h)) < 0) + return -1; + /* ss is a server socket that the clients connect to. The callback + therefore accepts clients on ss */ + if (event_reg_fd(ss, config_accept_client, h, "server socket") < 0) { + close(ss); + return -1; + } + return ss; +} + +/*! Callback for CLICON log events + * If you make a subscription to CLICON stream, this function is called for every + * log event. + */ +static int +config_log_cb(int level, char *msg, void *arg) +{ + size_t n; + char *ptr; + char *nptr; + char *newmsg = NULL; + int retval = -1; + + /* backend_notify() will go through all clients and see if any has registered "CLICON", + and if so make a clicon_proto notify message to those clients. */ + + + /* Sanitize '%' into "%%" to prevent segvfaults in vsnprintf later. + At this stage all formatting is already done */ + n = 0; + for(ptr=msg; *ptr; ptr++) + if (*ptr == '%') + n++; + if ((newmsg = malloc(strlen(msg) + n + 1)) == NULL) { + clicon_err(OE_UNIX, errno, "malloc"); + return -1; + } + for(ptr=msg, nptr=newmsg; *ptr; ptr++) { + *nptr++ = *ptr; + if (*ptr == '%') + *nptr++ = '%'; + } + + retval = backend_notify(arg, "CLICON", level, newmsg); + free(newmsg); + + return retval; +} + +int +main(int argc, char **argv) +{ + char c; + int zap; + int foreground; + int once; + int init_rundb; + char *running_db; + char *candidate_db; + int reload_running; + int reset_state_running; + int reset_state_candidate; + char *app_config_file = NULL; + char *config_group; + char *argv0 = argv[0]; + char *tmp; + struct stat st; + clicon_handle h; + int help = 0; + int printspec = 0; + int printalt = 0; + int pid; + char *pidfile; + char *sock; + int sockfamily; + + /* In the startup, logs to stderr & syslog and debug flag set later */ + clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG); + /* Initiate CLICON handle */ + if ((h = backend_handle_init()) == NULL) + return -1; + if (config_plugin_init(h) != 0) + return -1; + foreground = 0; + once = 0; + zap = 0; + init_rundb = 0; + reload_running = 0; + reset_state_running = 0; + reset_state_candidate = 0; + + /* + * Command-line options for help, debug, and config-file + */ + opterr = 0; + optind = 1; + while ((c = getopt(argc, argv, BACKEND_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 measn 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; + } + /* + * Syslogs also to stderr, but later turn stderr off in daemon mode. + * error only to syslog. debug to syslog + */ + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG); + clicon_debug_init(debug, NULL); + + /* Find and read configfile */ + if (clicon_options_main(h) < 0){ + if (help) + usage(argv[0], h); + return -1; + } + + /* Now run through the operational args */ + opterr = 1; + optind = 1; + while ((c = getopt(argc, argv, BACKEND_OPTS)) != -1) + switch (c) { + case 'D' : /* debug */ + case 'f': /* config file */ + break; /* see above */ + case 'd': /* Plugin directory */ + if (!strlen(optarg)) + usage(argv[0], h); + clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg); + break; + case 'F' : /* foreground */ + foreground = 1; + break; + case '1' : /* Quit after reading database once - dont wait for events */ + once = 1; + break; + case 'z': /* Zap other process */ + zap++; + break; + case 'u': /* config unix domain path / ip address */ + if (!strlen(optarg)) + usage(argv[0], h); + clicon_option_str_set(h, "CLICON_SOCK", optarg); + break; + case 'P': /* pidfile */ + clicon_option_str_set(h, "CLICON_BACKEND_PIDFILE", optarg); + break; + case 'I': /* Initiate running db */ + init_rundb++; + break; + case 'R': /* Reset state directly into running */ + reset_state_running++; + break; + case 'C': /* Reset state into candidate and then commit it */ + reset_state_candidate++; + break; + case 'c': /* Load application config */ + app_config_file = optarg ? optarg : clicon_startup_config(h); + if (app_config_file == NULL) { + fprintf(stderr, "Option \"CLICON_STARTUP_CONFIG\" not set\n"); + return -1; + } + break; + case 'r': /* Reload running */ + reload_running++; + break; + case 'g': /* config socket group */ + clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg); + break; + case 'p' : /* Print spec */ + printspec++; + break; + case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */ + printalt++; + 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); + + /* Check pid-file, if zap kil the old daemon, else return here */ + if ((pidfile = clicon_backend_pidfile(h)) == NULL){ + clicon_err(OE_FATAL, 0, "pidfile not set"); + goto done; + } + sockfamily = clicon_sock_family(h); + if ((sock = clicon_sock(h)) == NULL){ + clicon_err(OE_FATAL, 0, "sock not set"); + goto done; + } + if (pidfile_get(pidfile, &pid) < 0) + return -1; + if (zap){ + if (pid && pidfile_zapold(pid) < 0) + return -1; + if (lstat(pidfile, &st) == 0) + unlink(pidfile); + if (sockfamily==AF_UNIX && lstat(sock, &st) == 0) + unlink(sock); + exit(0); + } + else + if (pid){ + clicon_err(OE_DEMON, 0, "Daemon already running with pid %d\n(Try killing it with %s -z)", + pid, argv0); + return -1; /* goto done deletes pidfile */ + } + + /* After this point we can goto done on error + * Here there is either no old process or we have killed it,.. + */ + if (lstat(pidfile, &st) == 0) + unlink(pidfile); + if (sockfamily==AF_UNIX && lstat(sock, &st) == 0) + unlink(sock); + + /* Sanity check: config group exists */ + if ((config_group = clicon_sock_group(h)) == NULL){ + clicon_err(OE_FATAL, 0, "clicon_sock_group option not set"); + return -1; + } + + if (group_name2gid(config_group, NULL) < 0){ + clicon_log(LOG_ERR, "'%s' does not seem to be a valid user group.\n" + "The config demon requires a valid group to create a server UNIX socket\n" + "Define a valid CLICON_SOCK_GROUP in %s or via the -g option\n" + "or create the group and add the user to it. On linux for example:" + " sudo groupadd %s\n" + " sudo usermod -a -G %s user\n", + config_group, clicon_configfile(h), config_group, config_group); + return -1; + } + + /* Parse db spec file */ + if (yang_spec_main(h, stdout, printspec) < 0) + goto done; + + if ((running_db = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + /* If running exists and reload_running set, make a copy to candidate */ + if (reload_running){ + if (stat(running_db, &st) && errno == ENOENT){ + clicon_log(LOG_NOTICE, "%s: -r (reload running) option given but no running_db found, proceeding without", __PROGRAM__); + reload_running = 0; /* void it, so we dont commit candidate below */ + } + else + if (file_cp(running_db, candidate_db) < 0){ + clicon_err(OE_UNIX, errno, "FATAL: file_cp"); + goto done; + } + } + /* Init running db + * -I + */ + if (init_rundb || (stat(running_db, &st) && errno == ENOENT)) + if (rundb_init(h, running_db) < 0) + goto done; + + /* Initialize plugins + (also calls plugin_init() and plugin_start(argc,argv) in each plugin */ + if (plugin_initiate(h) != 0) + goto done; + + if (reset_state_candidate){ + if (candb_reset(h, running_db) < 0) + goto done; + } + else + if (reset_state_running){ + if (plugin_reset_state(h, running_db) < 0) + goto done; + } + /* Call plugin_start */ + tmp = *(argv-1); + *(argv-1) = argv0; + if (plugin_start_hooks(h, argc+1, argv-1) < 0) + goto done; + *(argv-1) = tmp; + + if (reload_running){ + if (candidate_commit(h, candidate_db, running_db) < 0) + goto done; + } + + /* Have we specified a config file to load? eg + -c + -r replace running (obsolete) + */ + if (app_config_file) + if (rundb_main(h, app_config_file, running_db) < 0) + goto done; + + /* Initiate the shared candidate. Maybe we should not do this? */ + if (file_cp(running_db, candidate_db) < 0){ + clicon_err(OE_UNIX, errno, "FATAL: file_cp"); + goto done; + } + /* XXX Hack for now. Change mode so that we all can write. Security issue*/ + chmod(candidate_db, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + + if (once) + goto done; + + /* Daemonize and initiate logging. Note error is initiated here to make + demonized errors OK. Before this stage, errors are logged on stderr + also */ + if (foreground==0){ + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, CLICON_LOG_SYSLOG); + if (daemon(0, 0) < 0){ + fprintf(stderr, "config: daemon"); + exit(0); + } + } + /* Write pid-file */ + + if ((pid = pidfile_write(pidfile)) < 0) + goto done; + + /* Register log notifications */ + if (clicon_log_register_callback(config_log_cb, h) < 0) + goto done; + clicon_log(LOG_NOTICE, "%s: %u Started", __PROGRAM__, getpid()); + if (set_signal(SIGTERM, config_sig_term, NULL) < 0){ + clicon_err(OE_DEMON, errno, "Setting signal"); + goto done; + } + if (set_signal(SIGINT, config_sig_term, NULL) < 0){ + clicon_err(OE_DEMON, errno, "Setting signal"); + goto done; + } + + /* Initialize server socket */ + if (server_socket(h) < 0) + goto done; + + if (debug) + clicon_option_dump(h, debug); + + if (event_loop() < 0) + goto done; + done: + clicon_log(LOG_NOTICE, "%s: %u Terminated", __PROGRAM__, getpid()); + config_terminate(h); /* Cannot use h after this */ + + return 0; +} diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c new file mode 100644 index 000000000..e06743a32 --- /dev/null +++ b/apps/backend/backend_plugin.c @@ -0,0 +1,751 @@ +/* + * + 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 + . + + * + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#define __USE_GNU /* strverscmp */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_backend_transaction.h" +#include "backend_plugin.h" +#include "backend_commit.h" + +/* + * Types + */ +/* Following are specific to backend. For common see clicon_plugin.h + * @note the following should match the prototypes in clicon_backend.h + */ +#define PLUGIN_RESET "plugin_reset" +typedef int (plgreset_t)(clicon_handle h, char *dbname); /* Reset system status */ + +#define PLUGIN_TRANS_BEGIN "transaction_begin" +#define PLUGIN_TRANS_VALIDATE "transaction_validate" +#define PLUGIN_TRANS_COMPLETE "transaction_complete" +#define PLUGIN_TRANS_COMMIT "transaction_commit" +#define PLUGIN_TRANS_END "transaction_end" +#define PLUGIN_TRANS_ABORT "transaction_abort" + +typedef int (trans_cb_t)(clicon_handle h, transaction_data td); /* Transaction cbs */ + +/* Backend (config) plugins */ +struct plugin { + char p_name[PATH_MAX]; /* Plugin name */ + void *p_handle; /* Dynamic object handle */ + plginit_t *p_init; /* Init */ + plgstart_t *p_start; /* Start */ + plgexit_t *p_exit; /* Exit */ + plgreset_t *p_reset; /* Reset state */ + trans_cb_t *p_trans_begin; /* Transaction start */ + trans_cb_t *p_trans_validate; /* Transaction validation */ + trans_cb_t *p_trans_complete; /* Transaction validation complete */ + trans_cb_t *p_trans_commit; /* Transaction commit */ + trans_cb_t *p_trans_end; /* Transaction completed */ + trans_cb_t *p_trans_abort; /* Transaction aborted */ +}; + +/* + * Local variables + */ +static int nplugins = 0; +static struct plugin *plugins = NULL; + +/*! Find a plugin by name and return the dlsym handl + * Used by libclicon code to find callback funcctions in plugins. + * @param[in] h Clicon handle + * @param[in] h Name of plugin + * @retval handle Plugin handle if found + * @retval NULL Not found + */ +static void * +config_find_plugin(clicon_handle h, + char *name) +{ + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++){ + p = &plugins[i]; + if (strcmp(p->p_name, name) == 0) + return p->p_handle; + } + return NULL; +} + +/*! Initialize plugin code (not the plugins themselves) + * @param[in] h Clicon handle + * @retval 0 OK + * @retval -1 Error + */ +int +config_plugin_init(clicon_handle h) +{ + find_plugin_t *fp = config_find_plugin; + clicon_hash_t *data = clicon_data(h); + + /* Register CLICON_FIND_PLUGIN in data hash */ + if (hash_add(data, "CLICON_FIND_PLUGIN", &fp, sizeof(fp)) == NULL) { + clicon_err(OE_UNIX, errno, "failed to register CLICON_FIND_PLUGIN"); + return -1; + } + return 0; +} + +/*! Unload a plugin + * @param[in] h Clicon handle + * @param[in] plg Plugin structure + * @retval 0 OK + * @retval -1 Error + */ +static int +plugin_unload(clicon_handle h, + struct plugin *plg) +{ + char *error; + + /* Call exit function is it exists */ + if (plg->p_exit) + plg->p_exit(h); + + dlerror(); /* Clear any existing error */ + if (dlclose(plg->p_handle) != 0) { + error = (char*)dlerror(); + clicon_err(OE_UNIX, 0, "dlclose: %s", error?error:"Unknown error"); + return -1; + /* Just report */ + } + else + clicon_debug(1, "Plugin '%s' unloaded.", plg->p_name); + return 0; +} + + +/*! Load a dynamic plugin and call its init-function + * @param[in] h Clicon handle + * @param[in] file The plugin (.so) to load + * @param[in] dlflags Arguments to dlopen(3) + * @param[in] label Chunk label + * @retval plugin Plugin struct + * @retval NULL Error + */ +static struct plugin * +plugin_load (clicon_handle h, + char *file, + int dlflags, + const char *label) +{ + char *error; + void *handle; + char *name; + struct plugin *new; + plginit_t *initfun; + + dlerror(); /* Clear any existing error */ + if ((handle = dlopen (file, dlflags)) == NULL) { + error = (char*)dlerror(); + clicon_err(OE_UNIX, 0, "dlopen: %s", error?error:"Unknown error"); + return NULL; + } + + initfun = dlsym(handle, PLUGIN_INIT); + if ((error = (char*)dlerror()) != NULL) { + clicon_err(OE_UNIX, 0, "dlsym: %s", error); + return NULL; + } + + if (initfun(h) != 0) { + dlclose(handle); + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error", + file); + return NULL; + } + + if ((new = chunk(sizeof(*new), label)) == NULL) { + clicon_err(OE_UNIX, errno, "dhunk: %s", strerror(errno)); + dlclose(handle); + return NULL; + } + memset(new, 0, sizeof(*new)); + name = strrchr(file, '/') ? strrchr(file, '/')+1 : file; + clicon_debug(2, "Loading plugin '%s'.", name); + snprintf(new->p_name, sizeof(new->p_name), "%*s", + (int)strlen(name)-2, name); + new->p_handle = handle; + new->p_init = initfun; + if ((new->p_start = dlsym(handle, PLUGIN_START)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_START); + if ((new->p_exit = dlsym(handle, PLUGIN_EXIT)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_EXIT); + if ((new->p_reset = dlsym(handle, PLUGIN_RESET)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_RESET); + if ((new->p_trans_begin = dlsym(handle, PLUGIN_TRANS_BEGIN)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_BEGIN); + if ((new->p_trans_validate = dlsym(handle, PLUGIN_TRANS_VALIDATE)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_VALIDATE); + if ((new->p_trans_complete = dlsym(handle, PLUGIN_TRANS_COMPLETE)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_COMPLETE); + if ((new->p_trans_commit = dlsym(handle, PLUGIN_TRANS_COMMIT)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_COMMIT); + if ((new->p_trans_end = dlsym(handle, PLUGIN_TRANS_END)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_END); + if ((new->p_trans_abort = dlsym(handle, PLUGIN_TRANS_ABORT)) != NULL) + clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_ABORT); + clicon_debug(2, "Plugin '%s' loaded.\n", name); + + return new; +} + +/*! Request plugins to reset system state + * The system 'state' should be the same as the contents of running_db + * @param[in] h Clicon handle + * @param[in] dbname Name of database + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_reset_state(clicon_handle h, + char *dbname) +{ + int i; + struct plugin *p; + + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + if (p->p_reset) { + clicon_debug(1, "Calling plugin_reset() for %s\n", + p->p_name); + if (((p->p_reset)(h, dbname)) < 0) { + clicon_err(OE_FATAL, 0, "plugin_reset() failed for %s\n", + p->p_name); + return -1; + } + } + } + return 0; +} + +/*! Call plugin_start in all plugins + * @param[in] h Clicon handle + * @param[in] argc Command-line arguments + * @param[in] argv Command-line arguments + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_start_hooks(clicon_handle h, + int argc, + char **argv) +{ + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + if (p->p_start) { + optind = 0; + if (((p->p_start)(h, argc, argv)) < 0) { + clicon_err(OE_FATAL, 0, "plugin_start() failed for %s\n", + p->p_name); + return -1; + } + } + } + return 0; +} + +/*! Append plugin to list + * @param[in] p Plugin + * @retval 0 OK + * @retval -1 Error + */ +static int +plugin_append(struct plugin *p) +{ + struct plugin *new; + + if ((new = rechunk(plugins, (nplugins+1) * sizeof (*p), NULL)) == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + return -1; + } + + memset (&new[nplugins], 0, sizeof(new[nplugins])); + memcpy (&new[nplugins], p, sizeof(new[nplugins])); + plugins = new; + nplugins++; + + return 0; +} + +/*! Load backend plugins found in a directory + * The plugins must have the '.so' suffix + * @param[in] h Clicon handle + * @param[in] dir Backend plugin directory + * @retval 0 OK + * @retval -1 Error + */ +static int +config_plugin_load_dir(clicon_handle h, + const char *dir) +{ + int retval = -1; + int i; + int np = 0; + int ndp; + struct stat st; + char *filename; + struct dirent *dp; + struct plugin *new; + struct plugin *p = NULL; + char *master; + char *master_plugin; + + /* Format master plugin path */ + if ((master_plugin = clicon_master_plugin(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "clicon_master_plugin option not set"); + goto quit; + } + master = chunk_sprintf(__FUNCTION__, "%s.so", master_plugin); + if (master == NULL) { + clicon_err(OE_PLUGIN, errno, "chunk_sprintf master plugin"); + goto quit; + } + + /* Allocate plugin group object */ + /* Get plugin objects names from plugin directory */ + if((ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG, __FUNCTION__))<0) + goto quit; + + /* reset num plugins */ + np = 0; + + /* Master plugin must be loaded first if it exists. */ + filename = chunk_sprintf(__FUNCTION__, "%s/%s", dir, master); + if (filename == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + goto quit; + } + if (stat(filename, &st) == 0) { + clicon_debug(1, "Loading master plugin '%.*s' ...", + (int)strlen(filename), filename); + + new = plugin_load(h, filename, RTLD_NOW|RTLD_GLOBAL, __FUNCTION__); + if (new == NULL) + goto quit; + if (plugin_append(new) < 0) + goto quit; + } + + /* Now load the rest */ + for (i = 0; i < ndp; i++) { + if (strcmp(dp[i].d_name, master) == 0) + continue; /* Skip master now */ + filename = chunk_sprintf(__FUNCTION__, "%s/%s", dir, dp[i].d_name); + clicon_debug(1, "Loading plugin '%.*s' ...", (int)strlen(filename), filename); + if (filename == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + goto quit; + } + new = plugin_load (h, filename, RTLD_NOW, __FUNCTION__); + if (new == NULL) + goto quit; + if (plugin_append(new) < 0) + goto quit; + } + + /* All good. */ + retval = 0; + +quit: + if (retval != 0) { + if (p) { + while (--np >= 0) + plugin_unload (h, &p[np]); + unchunk(p); + } + } + unchunk_group(__FUNCTION__); + return retval; +} + + +/*! Load a plugin group. + * @param[in] h Clicon handle + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_initiate(clicon_handle h) +{ + char *dir; + + /* First load CLICON system plugins */ + if (config_plugin_load_dir(h, CLICON_BACKEND_SYSDIR) < 0) + return -1; + + /* Then load application plugins */ + if ((dir = clicon_backend_dir(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "backend_dir not defined"); + return -1; + } + if (config_plugin_load_dir(h, dir) < 0) + return -1; + + return 0; +} + +/*! Unload and deallocate all backend plugins + * @param[in] h Clicon handle + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_finish(clicon_handle h) +{ + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + plugin_unload(h, p); + } + if (plugins) + unchunk(plugins); + nplugins = 0; + return 0; +} + +/*! Call from frontend to function 'func' in plugin 'plugin'. + * Plugin function is supposed to populate 'retlen' and 'retarg' where + * 'retarg' is malloc:ed data if non-NULL. + * @param[in] h Clicon handle + * @param[in] req Clicon message containing information about the downcall + * @param[out] retlen Length of return value + * @param[out] ret Return value + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_downcall(clicon_handle h, + struct clicon_msg_call_req *req, + uint16_t *retlen, + void **retarg) +{ + int retval = -1; + int i; + downcall_cb funcp; + char name[PATH_MAX]; + char *error; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + strncpy(name, p->p_name, sizeof(name)-1); + if (!strcmp(name+strlen(name)-3, ".so")) + name[strlen(name)-3] = '\0'; + /* If no plugin is given or the plugin-name matches */ + if (req->cr_plugin == NULL || strlen(req->cr_plugin)==0 || + strcmp(name, req->cr_plugin) == 0) { + funcp = dlsym(p->p_handle, req->cr_func); + if ((error = (char*)dlerror()) != NULL) { + clicon_err(OE_PROTO, ENOENT, + "Function does not exist: %s()", req->cr_func); + return -1; + } + retval = funcp(h, req->cr_op, req->cr_arglen, req->cr_arg, retlen, retarg); + goto done; + } + } + clicon_err(OE_PROTO, ENOENT,"%s: %s(): Plugin does not exist: %s", + __FUNCTION__, req->cr_func, req->cr_plugin); + return -1; + +done: + return retval; +} + +/*! Create and initialize transaction */ +transaction_data_t * +transaction_new(void) +{ + transaction_data_t *td; + static uint64_t id = 0; /* Global transaction id */ + + if ((td = malloc(sizeof(*td))) == NULL){ + clicon_err(OE_CFG, errno, "malloc"); + return NULL; + } + memset(td, 0, sizeof(*td)); + td->td_id = id++; + return td; +} + +/*! Free transaction structure */ +int +transaction_free(transaction_data_t *td) +{ + if (td->td_src) + xml_free(td->td_src); + if (td->td_target) + xml_free(td->td_target); + if (td->td_dvec) + free(td->td_dvec); + if (td->td_avec) + free(td->td_avec); + if (td->td_scvec) + free(td->td_scvec); + if (td->td_tcvec) + free(td->td_tcvec); + free(td); + return 0; +} + +/* The plugin_transaction routines need access to struct plugin which is local to this file */ + +/*! Call transaction_begin() in all plugins before a validate/commit. + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK + * @retval -1 Error: one of the plugin callbacks returned error + */ +int +plugin_transaction_begin(clicon_handle h, + transaction_data_t *td) +{ + int i; + int retval = 0; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + if (p->p_trans_begin) + if ((retval = (p->p_trans_begin)(h, (transaction_data)td)) < 0){ + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_log(LOG_NOTICE, "%s: Plugin '%s' %s callback does not make clicon_err call on error", + __FUNCTION__, p->p_name, PLUGIN_TRANS_BEGIN); + + break; + } + + } + return retval; +} + +/*! Call transaction_validate callbacks in all backend plugins + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK. Validation succeeded in all plugins + * @retval -1 Error: one of the plugin callbacks returned validation fail + */ +int +plugin_transaction_validate(clicon_handle h, + transaction_data_t *td) +{ + int retval = 0; + int i; + + struct plugin *p; + + for (i = 0; i < nplugins; i++){ + p = &plugins[i]; + if (p->p_trans_validate) + if ((retval = (p->p_trans_validate)(h, (transaction_data)td)) < 0){ + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_log(LOG_NOTICE, "%s: Plugin '%s' %s callback does not make clicon_err call on error", + __FUNCTION__, p->p_name, PLUGIN_TRANS_VALIDATE); + + break; + } + } + return retval; +} + +/*! Call transaction_complete() in all plugins after validation (before commit) + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK + * @retval -1 Error: one of the plugin callbacks returned error + * @note Call plugins which have commit dependencies? + * @note Rename to transaction_complete? + */ +int +plugin_transaction_complete(clicon_handle h, + transaction_data_t *td) +{ + int i; + int retval = 0; + struct plugin *p; + + for (i = 0; i < nplugins; i++){ + p = &plugins[i]; + if (p->p_trans_complete) + if ((retval = (p->p_trans_complete)(h, (transaction_data)td)) < 0){ + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_log(LOG_NOTICE, "%s: Plugin '%s' %s callback does not make clicon_err call on error", + __FUNCTION__, p->p_name, PLUGIN_TRANS_COMPLETE); + + break; + } + } + return retval; +} + +int +plugin_transaction_revert(clicon_handle h, + transaction_data_t *td, + int nr) +{ + int retval = 0; + transaction_data_t tr; /* revert transaction */ + int i; + struct plugin *p; + + /* Create a new reversed transaction from the original where src and target + are swapped */ + memcpy(&tr, td, sizeof(tr)); + tr.td_src = td->td_target; + tr.td_target = td->td_src; + tr.td_dlen = td->td_alen; + tr.td_dvec = td->td_avec; + tr.td_alen = td->td_dlen; + tr.td_avec = td->td_dvec; + tr.td_scvec = td->td_tcvec; + tr.td_tcvec = td->td_scvec; + + for (i = nr-1; i; i--){ + p = &plugins[i]; + if (p->p_trans_commit) + if ((p->p_trans_commit)(h, (transaction_data)&tr) < 0){ + clicon_log(LOG_NOTICE, "Plugin '%s' %s revert callback failed", + p->p_name, PLUGIN_TRANS_COMMIT); + break; + } + } + return retval; /* ignore errors */ +} + +/*! Call transaction_commit callbacks in all backend plugins + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK + * @retval -1 Error: one of the plugin callbacks returned error + * If any of the commit callbacks fail by returning -1, a revert of the + * transaction is tried by calling the commit callbacsk with reverse arguments + * and in reverse order. + */ +int +plugin_transaction_commit(clicon_handle h, + transaction_data_t *td) +{ + int retval = 0; + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++){ + p = &plugins[i]; + if (p->p_trans_commit) + if ((retval = (p->p_trans_commit)(h, (transaction_data)td)) < 0){ + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_log(LOG_NOTICE, "%s: Plugin '%s' %s callback does not make clicon_err call on error", + __FUNCTION__, p->p_name, PLUGIN_TRANS_COMMIT); + /* Make an effort to revert transaction */ + plugin_transaction_revert(h, td, i); + break; + } + } + return retval; +} + +/*! Call transaction_end() in all plugins after a successful commit. + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_transaction_end(clicon_handle h, + transaction_data_t *td) +{ + int retval = 0; + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + if (p->p_trans_end) + if ((retval = (p->p_trans_end)(h, (transaction_data)td)) < 0){ + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_log(LOG_NOTICE, "%s: Plugin '%s' %s callback does not make clicon_err call on error", + __FUNCTION__, p->p_name, PLUGIN_TRANS_END); + + break; + } + } + return retval; +} + +/*! Call transaction_abort() in all plugins after a failed validation/commit. + * @param[in] h Clicon handle + * @param[in] td Transaction data + * @retval 0 OK + * @retval -1 Error + */ +int +plugin_transaction_abort(clicon_handle h, + transaction_data_t *td) +{ + int retval = 0; + int i; + struct plugin *p; + + for (i = 0; i < nplugins; i++) { + p = &plugins[i]; + if (p->p_trans_abort) + (p->p_trans_abort)(h, (transaction_data)td); /* dont abort on error */ + } + return retval; +} + + diff --git a/apps/backend/backend_plugin.h b/apps/backend/backend_plugin.h new file mode 100644 index 000000000..f7707b4b9 --- /dev/null +++ b/apps/backend/backend_plugin.h @@ -0,0 +1,72 @@ +/* + * + 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 + . + + */ + +#ifndef _BACKEND_PLUGIN_H_ +#define _BACKEND_PLUGIN_H_ + +/* + * Types + */ + + +/*! Transaction data + * Clicon internal, presented as void* to app's callback in the 'transaction_data' + * type in clicon_backend_api.h + * XXX: move to .c file? + */ +typedef struct { + uint64_t td_id; /* Transaction id */ + void *td_arg; /* Callback argument */ + cxobj *td_src; /* Source database xml tree */ + cxobj *td_target; /* Target database xml tree */ + cxobj **td_dvec; /* Delete xml vector */ + size_t td_dlen; /* Delete xml vector length */ + cxobj **td_avec; /* Add xml vector */ + size_t td_alen; /* Add xml vector length */ + cxobj **td_scvec; /* Source changed xml vector */ + cxobj **td_tcvec; /* Target changed xml vector */ + size_t td_clen; /* Changed xml vector length */ +} transaction_data_t; + +/* + * Prototypes + */ +int config_plugin_init(clicon_handle h); +int plugin_initiate(clicon_handle h); +int plugin_finish(clicon_handle h); + +int plugin_reset_state(clicon_handle h, char *dbname); +int plugin_start_hooks(clicon_handle h, int argc, char **argv); +int plugin_downcall(clicon_handle h, struct clicon_msg_call_req *req, + uint16_t *retlen, void **retarg); + +transaction_data_t * transaction_new(void); +int transaction_free(transaction_data_t *); + +int plugin_transaction_begin(clicon_handle h, transaction_data_t *td); +int plugin_transaction_validate(clicon_handle h, transaction_data_t *td); +int plugin_transaction_complete(clicon_handle h, transaction_data_t *td); +int plugin_transaction_commit(clicon_handle h, transaction_data_t *td); +int plugin_transaction_end(clicon_handle h, transaction_data_t *td); +int plugin_transaction_abort(clicon_handle h, transaction_data_t *td); + +#endif /* _BACKEND_PLUGIN_H_ */ diff --git a/apps/backend/backend_socket.c b/apps/backend/backend_socket.c new file mode 100644 index 000000000..5de10cbd2 --- /dev/null +++ b/apps/backend/backend_socket.c @@ -0,0 +1,262 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_UCRED_H +#include +#include +#endif +#define __USE_GNU +#include +#include +#include + +#include +#include +#include + +#include + +/* clicon */ +#include + +#include "backend_socket.h" +#include "backend_client.h" +#include "backend_handle.h" + +static int +config_socket_init_ipv4(clicon_handle h, char *dst) +{ + int s; + struct sockaddr_in addr; + uint16_t port; + + port = clicon_sock_port(h); + + /* create inet socket */ + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + clicon_err(OE_UNIX, errno, "socket"); + return -1; + } +// setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one)); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (inet_pton(addr.sin_family, dst, &addr.sin_addr) != 1){ + clicon_err(OE_UNIX, errno, "inet_pton: %s (Expected IPv4 address. Check settings of CLICON_SOCK_FAMILY and CLICON_SOCK)", dst); + goto err; /* Could check getaddrinfo */ + } + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0){ + clicon_err(OE_UNIX, errno, "%s: bind", __FUNCTION__); + goto err; + } + clicon_debug(1, "Listen on server socket at %s:%hu", dst, port); + if (listen(s, 5) < 0){ + clicon_err(OE_UNIX, errno, "%s: listen", __FUNCTION__); + goto err; + } + return s; + err: + close(s); + return -1; +} + +/*! Open a socket and bind it to a file descriptor + * + * The socket is accessed via CLICON_SOCK option, has 770 permissions + * and group according to CLICON_SOCK_GROUP option. + */ +static int +config_socket_init_unix(clicon_handle h, char *sock) +{ + int s; + struct sockaddr_un addr; + mode_t old_mask; + char *config_group; + gid_t gid; + struct stat st; + + if (lstat(sock, &st) == 0 && unlink(sock) < 0){ + clicon_err(OE_UNIX, errno, "%s: unlink(%s)", __FUNCTION__, sock); + return -1; + } + /* then find configuration group (for clients) and find its groupid */ + if ((config_group = clicon_sock_group(h)) == NULL){ + clicon_err(OE_FATAL, 0, "clicon_sock_group option not set"); + return -1; + } + if (group_name2gid(config_group, &gid) < 0) + return -1; +#if 0 + if (gid == 0) + clicon_log(LOG_WARNING, "%s: No such group: %s\n", __FUNCTION__, config_group); +#endif + /* create unix socket */ + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + clicon_err(OE_UNIX, errno, "%s: socket", __FUNCTION__); + return -1; + } +// setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one)); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1); + old_mask = umask(S_IRWXO | S_IXGRP | S_IXUSR); + if (bind(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){ + clicon_err(OE_UNIX, errno, "%s: bind", __FUNCTION__); + umask(old_mask); + goto err; + } + umask(old_mask); + /* change socket path file group */ + if (lchown(sock, -1, gid) < 0){ + clicon_err(OE_UNIX, errno, "%s: lchown(%s, %s)", __FUNCTION__, + sock, config_group); + goto err; + } + clicon_debug(1, "Listen on server socket at %s", addr.sun_path); + if (listen(s, 5) < 0){ + clicon_err(OE_UNIX, errno, "%s: listen", __FUNCTION__); + goto err; + } + return s; + err: + close(s); + return -1; +} + +int +config_socket_init(clicon_handle h) +{ + char *sock; + + if ((sock = clicon_sock(h)) == NULL){ + clicon_err(OE_FATAL, 0, "CLICON_SOCK option not set"); + return -1; + } + switch (clicon_sock_family(h)){ + case AF_UNIX: + return config_socket_init_unix(h, sock); + break; + case AF_INET: + return config_socket_init_ipv4(h, sock); + break; + } + return 0; +} + +/* + * config_accept_client + * XXX: credentials not properly implemented + */ +int +config_accept_client(int fd, void *arg) +{ + int retval = -1; + clicon_handle h = (clicon_handle)arg; + int s; + struct sockaddr_un from; + socklen_t len; + struct client_entry *ce; +#ifdef DONT_WORK /* XXX HAVE_SYS_UCRED_H */ + struct xucred credentials; /* FreeBSD. */ + socklen_t clen; +#elif defined(SO_PEERCRED) + struct ucred credentials; /* Linux. */ + socklen_t clen; +#endif + char *config_group; + struct group *gr; + char *mem; + int i; + + clicon_debug(1, "%s", __FUNCTION__); + len = sizeof(from); + if ((s = accept(fd, (struct sockaddr*)&from, &len)) < 0){ + clicon_err(OE_UNIX, errno, "%s: accept", __FUNCTION__); + goto done; + } +#if defined(SO_PEERCRED) + /* fill in the user data structure */ + clen = sizeof(credentials); + if(getsockopt(s, SOL_SOCKET, SO_PEERCRED/* XXX finns ej i freebsd*/, &credentials, &clen)){ + clicon_err(OE_UNIX, errno, "%s: getsockopt", __FUNCTION__); + goto done; + } +#endif + if ((ce = backend_client_add(h, (struct sockaddr*)&from)) == NULL) + goto done; +#if defined(SO_PEERCRED) + ce->ce_pid = credentials.pid; + ce->ce_uid = credentials.uid; +#endif + ce->ce_handle = h; + + /* check credentials of caller (not properly implemented yet) */ + if ((config_group = clicon_sock_group(h)) == NULL){ + clicon_err(OE_FATAL, 0, "clicon_sock_group option not set"); + goto done; + } + if ((gr = getgrnam(config_group)) != NULL){ + i = 0; /* one of mem should correspond to ce->ce_uid */ + while ((mem = gr->gr_mem[i++]) != NULL) + ; + } + +#if 0 + { /* XXX */ + int ii; + struct client_entry *c; + for (c = ce_list, ii=0; c; c = c->ce_next, ii++); + clicon_debug(1, "Open client socket (nr:%d pid:%d [Total: %d])", + ce->ce_nr, ce->ce_pid, ii); + } +#endif + ce->ce_s = s; + + /* + * Here we register callbacks for actual data socket + */ + if (event_reg_fd(s, from_client, (void*)ce, "client socket") < 0) + goto done; + retval = 0; + done: + return retval; +} + + diff --git a/apps/backend/backend_socket.h b/apps/backend/backend_socket.h new file mode 100644 index 000000000..1af58ba89 --- /dev/null +++ b/apps/backend/backend_socket.h @@ -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 + . + + */ + + +#ifndef _BACKEND_SOCKET_H_ +#define _BACKEND_SOCKET_H_ + +/* + * Prototypes + */ +int config_socket_init(clicon_handle h); +int config_accept_client(int fd, void *arg); + +#endif /* _BACKEND_SOCKET_H_ */ diff --git a/apps/backend/clicon_backend.h b/apps/backend/clicon_backend.h new file mode 100644 index 000000000..c49f15323 --- /dev/null +++ b/apps/backend/clicon_backend.h @@ -0,0 +1,92 @@ +/* + * + 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 + . + + * + * The exported interface to plugins. External apps (eg backend plugins) should + * only include this file. + * Internal code should not include this file + */ + +#ifndef _CLICON_BACKEND_H_ +#define _CLICON_BACKEND_H_ + +/* + * Use this constant to disable some prototypes that should not be visible outside the lib. + * This is an alternative to use separate internal include files. + */ + +/* Common code (API and Backend daemon) */ +#include +#include + +/*! Clicon Backend plugin callbacks: use these in your backend 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); + +/*! Reset system state to original state. Eg at reboot before running thru config. + * @see plgreset_t + */ +int plugin_reset(clicon_handle h, char *dbname); + +/*! Called before a commit/validate sequence begins. Eg setup state before commit + * @see trans_cb_t + */ +int transaction_begin(clicon_handle h, transaction_data td); + +/*! Validate. + * @see trans_cb_t + */ +int transaction_validate(clicon_handle h, transaction_data td); + +/* Called after a validation completed succesfully (but before commit). + * @see trans_cb_t + */ +int transaction_complete(clicon_handle h, transaction_data td); + +/* Commit. + * @see trans_cb_t + */ +int transaction_commit(clicon_handle h, transaction_data td); + +/* Called after a commit sequence completed succesfully. + * @see trans_cb_t + */ +int transaction_end(clicon_handle h, transaction_data td); + +/* Called if commit or validate sequence fails. After eventual rollback. + * @see trans_cb_t + */ +int transaction_abort(clicon_handle h, transaction_data td); + +#endif /* _CLICON_BACKEND_H_ */ diff --git a/apps/backend/clicon_backend_handle.c b/apps/backend/clicon_backend_handle.c new file mode 100644 index 000000000..c12f86f5e --- /dev/null +++ b/apps/backend/clicon_backend_handle.c @@ -0,0 +1,353 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_backend_handle.h" +#include "backend_client.h" +#include "backend_handle.h" + +/* header part is copied from struct clicon_handle in lib/src/clicon_handle.c */ + +#define CLICON_MAGIC 0x99aafabe + +#define handle(h) (assert(clicon_handle_check(h)==0),(struct backend_handle *)(h)) + +/* Clicon_handle for backends. + * First part of this is header, same for clicon_handle and cli_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 backend_handle { + int cb_magic; /* magic (HDR)*/ + clicon_hash_t *cb_copt; /* clicon option list (HDR) */ + clicon_hash_t *cb_data; /* internal clicon data (HDR) */ + /* ------ end of common handle ------ */ + struct client_entry *cb_ce_list; /* The client list */ + int cb_ce_nr; /* Number of clients, just increment */ + struct handle_subscription *cb_subscription; /* Event subscription list */ +}; + +/*! Creates and returns a clicon config handle for other CLICON API calls + */ +clicon_handle +backend_handle_init(void) +{ + return clicon_handle_init0(sizeof(struct backend_handle)); +} + +/*! Deallocates a backend handle, including all client structs + * @Note: handle 'h' cannot be used in calls after this + */ +int +backend_handle_exit(clicon_handle h) +{ + struct client_entry *ce; + + /* only delete client structs, not close sockets, etc, see backend_client_rm */ + while ((ce = backend_client_list(h)) != NULL) + backend_client_delete(h, ce); + clicon_handle_exit(h); /* frees h and options */ + return 0; +} + +/*! Notify event and distribute to all registered clients + * + * @param[in] h Clicon handle + * @param[in] stream Name of event stream. CLICON is predefined as LOG stream + * @param[in] level Event level (not used yet) + * @param[in] event Actual message as text format + * + * Stream is a string used to qualify the event-stream. Distribute the + * event to all clients registered to this backend. + * XXX: event-log NYI. + * @see also subscription_add() + * @see also backend_notify_xml() + */ +int +backend_notify(clicon_handle h, char *stream, int level, char *event) +{ + struct client_entry *ce; + struct client_subscription *su; + struct handle_subscription *hs; + int retval = -1; + + /* First thru all clients(sessions), and all subscriptions and find matches */ + for (ce = backend_client_list(h); ce; ce = ce->ce_next) + for (su = ce->ce_subscription; su; su = su->su_next) + if (strcmp(su->su_stream, stream) == 0){ + if (fnmatch(su->su_filter, event, 0) == 0) + if (send_msg_notify(ce->ce_s, level, event) < 0) + goto done; + } + /* Then go thru all global (handle) subscriptions and find matches */ + hs = NULL; + while ((hs = subscription_each(h, hs)) != NULL){ + if (hs->hs_format != MSG_NOTIFY_TXT) + continue; + if (strcmp(hs->hs_stream, stream)) + continue; + if (fnmatch(hs->hs_filter, event, 0) == 0) + if ((*hs->hs_fn)(h, event, hs->hs_arg) < 0) + goto done; + } + retval = 0; + done: + return retval; +} + +/*! Notify event and distribute to all registered clients + * + * @param[in] h Clicon handle + * @param[in] stream Name of event stream. CLICON is predefined as LOG stream + * @param[in] level Event level (not used yet) + * @param[in] event Actual message as xml tree + * + * Stream is a string used to qualify the event-stream. Distribute the + * event to all clients registered to this backend. + * XXX: event-log NYI. + * @see also subscription_add() + * @see also backend_notify() + */ +int +backend_notify_xml(clicon_handle h, char *stream, int level, cxobj *x) +{ + struct client_entry *ce; + struct client_subscription *su; + int retval = -1; + cbuf *cb = NULL; + struct handle_subscription *hs; + + /* Now go thru all clients(sessions), and all subscriptions and find matches */ + for (ce = backend_client_list(h); ce; ce = ce->ce_next) + for (su = ce->ce_subscription; su; su = su->su_next) + if (strcmp(su->su_stream, stream) == 0){ + if (strlen(su->su_filter)==0 || xpath_first(x, su->su_filter) != NULL){ + if (cb==NULL){ + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_PLUGIN, errno, "cbuf_new"); + goto done; + } + if (clicon_xml2cbuf(cb, x, 0, 0) < 0) + goto done; + } + if (send_msg_notify(ce->ce_s, level, cbuf_get(cb)) < 0) + goto done; + } + } + /* Then go thru all global (handle) subscriptions and find matches */ + /* XXX: x contains name==dk-ore, but filter is + id==/[userid=d2d5e46c-c6f9-42f3-9a69-fb52fe60940d] */ + hs = NULL; + while ((hs = subscription_each(h, hs)) != NULL){ + if (hs->hs_format != MSG_NOTIFY_XML) + continue; + if (strcmp(hs->hs_stream, stream)) + continue; + if (strlen(hs->hs_filter)==0 || xpath_first(x, hs->hs_filter) != NULL) + if ((*hs->hs_fn)(h, x, hs->hs_arg) < 0) + goto done; + } + retval = 0; + done: + if (cb) + cbuf_free(cb); + return retval; + +} + +struct client_entry * +backend_client_add(clicon_handle h, struct sockaddr *addr) +{ + struct backend_handle *cb = handle(h); + struct client_entry *ce; + + if ((ce = (struct client_entry *)malloc(sizeof(*ce))) == NULL){ + clicon_err(OE_PLUGIN, errno, "malloc"); + return NULL; + } + memset(ce, 0, sizeof(*ce)); + ce->ce_nr = cb->cb_ce_nr++; + memcpy(&ce->ce_addr, addr, sizeof(*addr)); + ce->ce_next = cb->cb_ce_list; + cb->cb_ce_list = ce; + return ce; +} + +struct client_entry * +backend_client_list(clicon_handle h) +{ + struct backend_handle *cb = handle(h); + + return cb->cb_ce_list; +} + +/*! Actually remove client from list + * See also backend_client_rm() + */ +int +backend_client_delete(clicon_handle h, struct client_entry *ce) +{ + struct client_entry *c; + struct client_entry **ce_prev; + struct backend_handle *cb = handle(h); + + ce_prev = &cb->cb_ce_list; + for (c = *ce_prev; c; c = c->ce_next){ + if (c == ce){ + *ce_prev = c->ce_next; + free(ce); + break; + } + ce_prev = &c->ce_next; + } + return 0; +} + +/*! Add subscription given stream name, callback and argument + * @param[in] h Clicon handle + * @param[in] stream Name of event stream + * @param[in] format Expected format of event, eg text or xml + * @param[in] filter Filter to match event, depends on format, eg xpath for xml + * @param[in] fn Callback when event occurs + * @param[in] arg Argument to use with callback. Also handle when deleting + * Note that arg is not a real handle. + * @see subscription_delete + * @see subscription_each + */ +struct handle_subscription * +subscription_add(clicon_handle h, + char *stream, + enum format_enum format, + char *filter, + subscription_fn_t fn, + void *arg) +{ + struct backend_handle *cb = handle(h); + struct handle_subscription *hs = NULL; + + if ((hs = malloc(sizeof(*hs))) == NULL){ + clicon_err(OE_PLUGIN, errno, "malloc"); + goto done; + } + memset(hs, 0, sizeof(*hs)); + hs->hs_stream = strdup(stream); + hs->hs_format = format; + hs->hs_filter = strdup(filter); + hs->hs_next = cb->cb_subscription; + hs->hs_fn = fn; + hs->hs_arg = arg; + cb->cb_subscription = hs; + done: + return hs; +} + +/*! Delete subscription given stream name, callback and argument + * @param[in] h Clicon handle + * @param[in] stream Name of event stream + * @param[in] fn Callback when event occurs + * @param[in] arg Argument to use with callback and handle + * Note that arg is not a real handle. + * @see subscription_add + * @see subscription_each + */ +int +subscription_delete(clicon_handle h, + char *stream, + subscription_fn_t fn, + void *arg) +{ + struct backend_handle *cb = handle(h); + struct handle_subscription *hs; + struct handle_subscription **hs_prev; + + hs_prev = &cb->cb_subscription; /* this points to stack and is not real backpointer */ + for (hs = *hs_prev; hs; hs = hs->hs_next){ + /* XXX arg == hs->hs_arg */ + if (strcmp(hs->hs_stream, stream)==0 && hs->hs_fn == fn){ + *hs_prev = hs->hs_next; + free(hs->hs_stream); + if (hs->hs_filter) + free(hs->hs_filter); + if (hs->hs_arg) + free(hs->hs_arg); + free(hs); + break; + } + hs_prev = &hs->hs_next; + } + return 0; +} + +/*! Iterator over subscriptions + * + * NOTE: Never manipulate the child-list during operation or using the + * same object recursively, the function uses an internal field to remember the + * index used. It works as long as the same object is not iterated concurrently. + * + * @param[in] h clicon handle + * @param[in] hprev iterator, initialize with NULL + * @code + * clicon_handle h; + * struct handle_subscription *hs = NULL; + * while ((hs = subscription_each(h, hs)) != NULL) { + * ... + * } + * @endcode + */ +struct handle_subscription * +subscription_each(clicon_handle h, + struct handle_subscription *hprev) +{ + struct backend_handle *cb = handle(h); + struct handle_subscription *hs = NULL; + + if (hprev) + hs = hprev->hs_next; + else + hs = cb->cb_subscription; + return hs; +} diff --git a/apps/backend/clicon_backend_handle.h b/apps/backend/clicon_backend_handle.h new file mode 100644 index 000000000..f760d50f3 --- /dev/null +++ b/apps/backend/clicon_backend_handle.h @@ -0,0 +1,71 @@ +/* + * + 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 + . + + * + * Part of the external API to plugins. Applications should not include + * this file directly (only via clicon_backend.h). + * Internal code should include this + */ + +#ifndef _CLICON_BACKEND_HANDLE_H_ +#define _CLICON_BACKEND_HANDLE_H_ + +/* + * Types + */ + +/*! Generic downcall registration. + * Enables any function to be called from (cli) frontend + * to backend. Like an RPC on application-level. + */ +typedef int (*downcall_cb)(clicon_handle h, uint16_t op, uint16_t len, + void *arg, uint16_t *retlen, void **retarg); + +/* + * Log for netconf notify function (config_client.c) + */ +int backend_notify(clicon_handle h, char *stream, int level, char *txt); +int backend_notify_xml(clicon_handle h, char *stream, int level, cxobj *x); + +/* subscription callback */ +typedef int (*subscription_fn_t)(clicon_handle, void *filter, void *arg); + +/* Notification subscription info + * @see client_subscription in config_client.h + */ +struct handle_subscription{ + struct handle_subscription *hs_next; + enum format_enum hs_format; /* format (enum format_enum) XXX not needed? */ + char *hs_stream; /* name of notify stream */ + char *hs_filter; /* filter, if format=xml: xpath, if text: fnmatch */ + subscription_fn_t hs_fn; /* Callback when event occurs */ + void *hs_arg; /* Callback argument */ +}; + +struct handle_subscription *subscription_add(clicon_handle h, char *stream, + enum format_enum format, char *filter, + subscription_fn_t fn, void *arg); + +int subscription_delete(clicon_handle h, char *stream, + subscription_fn_t fn, void *arg); + +struct handle_subscription *subscription_each(clicon_handle h, + struct handle_subscription *hprev); +#endif /* _CLICON_BACKEND_HANDLE_H_ */ diff --git a/apps/backend/clicon_backend_transaction.c b/apps/backend/clicon_backend_transaction.c new file mode 100644 index 000000000..7f2461a3e --- /dev/null +++ b/apps/backend/clicon_backend_transaction.c @@ -0,0 +1,206 @@ +/* + * + 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 + . + + */ +/* + * Note that the functions in this file are accessible from the plugins + */ +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_backend_transaction.h" +#include "backend_plugin.h" + +/* Access functions for transaction-data handle in callbacks + * Expressed in a transition from an current -> wanted state. + * For example, adding a database symbol 'a' in candidate and commiting + * would give running in source and 'a' and candidate in 'target'. + */ +/*! Get transaction id + * @param[in] td transaction_data + * @retval id transaction id + */ +uint64_t +transaction_id(transaction_data td) +{ + return ((transaction_data_t *)td)->td_id; +} + +/*! Get plugin/application specific callbackargument + * @param[in] td transaction_data + * @retval arg callback argument + * @note NYI + */ +void * +transaction_arg(transaction_data td) +{ + return ((transaction_data_t *)td)->td_arg; +} + +/*! Get Source database xml tree + * @param[in] td transaction_data + * @retval src source xml tree containing original state + */ +cxobj * +transaction_src(transaction_data td) +{ + return ((transaction_data_t *)td)->td_src; +} + +/*! Get target database xml tree + * @param[in] td transaction_data + * @retval xml target xml tree containing wanted state + */ +cxobj * +transaction_target(transaction_data td) +{ + return ((transaction_data_t *)td)->td_target; +} + +/*! Get delete xml vector, ie vector of xml nodes that are deleted src->target + * @param[in] td transaction_data + * @retval vec Vector of xml nodes + */ +cxobj ** +transaction_dvec(transaction_data td) +{ + return ((transaction_data_t *)td)->td_dvec; +} + +/*! Get length of delete xml vector + * @param[in] td transaction_data + * @retval len Length of vector of xml nodes + * @see transaction_dvec + */ +size_t +transaction_dlen(transaction_data td) +{ + return ((transaction_data_t *)td)->td_dlen; +} + +/*! Get add xml vector, ie vector of xml nodes that are added src->target + * @param[in] td transaction_data + * @retval vec Vector of xml nodes + */ +cxobj ** +transaction_avec(transaction_data td) +{ + return ((transaction_data_t *)td)->td_avec; +} + +/*! Get length of add xml vector + * @param[in] td transaction_data + * @retval len Length of vector of xml nodes + * @see transaction_avec + */ +size_t +transaction_alen(transaction_data td) +{ + return ((transaction_data_t *)td)->td_alen; +} + +/*! Get source changed xml vector, ie vector of xml nodes that changed + * @param[in] td transaction_data + * @retval vec Vector of xml nodes + * These are only nodes of type LEAF. + * For each node in this vector which contains the original value, there + * is a node in tcvec with the changed value + * @see transaction_dcvec + */ +cxobj ** +transaction_scvec(transaction_data td) +{ + return ((transaction_data_t *)td)->td_scvec; +} + +/*! Get target changed xml vector, ie vector of xml nodes that changed + * @param[in] td transaction_data + * @retval vec Vector of xml nodes + * These are only nodes of type LEAF. + * For each node in this vector which contains the original value, there + * is a node in tcvec with the changed value + * @see transaction_scvec + */ +cxobj ** +transaction_tcvec(transaction_data td) +{ + return ((transaction_data_t *)td)->td_dvec; +} + +/*! Get length of changed xml vector + * @param[in] td transaction_data + * @retval len Length of vector of xml nodes + * This is the length of both the src change vector and the target change vector + */ +size_t +transaction_clen(transaction_data td) +{ + return ((transaction_data_t *)td)->td_clen; +} + +int +transaction_print(FILE *f, + transaction_data th) +{ + cxobj *xn; + int i; + transaction_data_t *td; + + td = (transaction_data_t *)th; + + fprintf(f, "Transaction id: 0x%llx\n", td->td_id); + fprintf(f, "Removed\n=========\n"); + for (i=0; itd_dlen; i++){ + xn = td->td_dvec[i]; + clicon_xml2file(f, xn, 0, 1); + } + fprintf(f, "Added\n=========\n"); + for (i=0; itd_alen; i++){ + xn = td->td_avec[i]; + clicon_xml2file(f, xn, 0, 1); + } + fprintf(stderr, "Changed\n=========\n"); + for (i=0; itd_clen; i++){ + xn = td->td_scvec[i]; + clicon_xml2file(f, xn, 0, 1); + xn = td->td_tcvec[i]; + clicon_xml2file(f, xn, 0, 1); + } + return 0; +} diff --git a/apps/backend/clicon_backend_transaction.h b/apps/backend/clicon_backend_transaction.h new file mode 100644 index 000000000..1466662a7 --- /dev/null +++ b/apps/backend/clicon_backend_transaction.h @@ -0,0 +1,60 @@ +/* + * + 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 + . + + * + * Part of the external API to plugins. Applications should not include + * this file directly (only via clicon_backend.h). + * Internal code should include this + */ + +#ifndef _CLICON_BACKEND_TRANSACTION_H_ +#define _CLICON_BACKEND_TRANSACTION_H_ + +/* + * Types + */ + +/*! Generic downcall registration. + * Enables any function to be called from (cli) frontend + * to backend. Like an RPC on application-level. + */ +typedef int (*downcall_cb)(clicon_handle h, uint16_t op, uint16_t len, + void *arg, uint16_t *retlen, void **retarg); + +/* Transaction callback data accessors for client plugins + * (defined in config_dbdep.c) + * @see transaction_data_t internal structure + */ +typedef void *transaction_data; +uint64_t transaction_id(transaction_data td); +void *transaction_arg(transaction_data td); +cxobj *transaction_src(transaction_data td); +cxobj *transaction_target(transaction_data td); +cxobj **transaction_dvec(transaction_data td); +size_t transaction_dlen(transaction_data td); +cxobj **transaction_avec(transaction_data td); +size_t transaction_alen(transaction_data td); +cxobj **transaction_scvec(transaction_data td); +cxobj **transaction_tcvec(transaction_data td); +size_t transaction_clen(transaction_data td); + +int transaction_print(FILE *f, transaction_data th); + +#endif /* _CLICON_BACKEND_TRANSACTION_H_ */ diff --git a/apps/backend/clicon_transaction_api.o b/apps/backend/clicon_transaction_api.o new file mode 100644 index 0000000000000000000000000000000000000000..3075b019e0d6329af0831f4231486e03c59a1615 GIT binary patch literal 7432 zcmbtY4R93Y8UFTeFWF6w5E6s{sXZ|W3b_j*jX(htAYe2VN5Jt1TrYQfKjm_Fy&oDZ z<4+?B6B!4mRL3$cirQ+eZ7o`LT3ZE6r*#~vb*9d!)9KV!EuFUGPp68~=lS;AyS+5h zI{hZQ&-=XJ^S+8Wc?|EZ7X z@8kGmfA*~HF!pTf2<{zYzrl3$bdT-?&|KRQJO&L%2h=&_y<=_ED$%il6JX*m%b2on z`uOG(&-}rs9Y^YccM%a}1T#=HKJe~@CdLL%Xb6$9ZOfi5JmqP#*@;wbE(Dvr&G!GJ z&5&$U4qi^iB!gWsNyAy$;f_z)unb!8DTBN-vs%Vb6y#AWtKZo3_CSm~Aq(I1c3I@YA3*<`J2yuIVd-hdD~TM)W-74F(1 zY?>FjaZs*Q=vxlr`)wEQe!ac{UcYACgO&FC>M!<7=X`=zcT741RO)&loh=E!5m-Q{ zQU5AHCiI^lWxh2G8QUe31~#&C89g`WoM!p~0liLtfK;oy1EIb%pwhcIBlUN|{953> zrEnV$QTjf+FO1(IN8rPQFm>Y<+yf_R8^(V6KcXEpE=Ew`W7^He0o((pXiqoi(iR#? zoB2Z$O_Fx=7Do6a37JnZl`ct#St1EYvcNopF?EtGGLMrOS{|WY<~5WxXxl-0%wLiO z<$NzS_mVVAvcfbO)1qAm=reD^5Cb!`RUm84LzK5o7H~Iyu;; zE_1;!*#P|JxlAUEvyjF-kJX0pC)~}29Cy%o1445V?PgyS*e?1*#?ACEroY43M!TE#0^?4$yM&rW=pA$WVs!PqjQiAHw4$w&y@Fy2F73eG zh-)sz;r|uY`yhK4hBn9!Q_?79&$zO|ii~rtZDbp571^7vY-2^Xg^g~d?Cgqcs;(N{ zT9NVXt0g&#a7EVZ%90h?uF|O6?Igny<)00W~3yxUy+a zQ+AjQeg)U-?81Q^lqKM%fwgKbrG)mF6QZ|_W`*`+x#s&aEoq@W!C>FMcng>J$s1%y z3ftm)aM$T6^s{v~(&`U!C51Lko7dFZ=x>_SG)-%%Yo3YN8N%PRyz%pmgROW5Iz(gR zD%2xFnfTTQroxMK1gh#=HGflMBZD+hV@f5%Qpik21B0!k4Q_r+s-_LLG9q}E7;KH8 za!M=S-799{p=#Bt38#j&3uZZ;nm=o>l|AiiyL0s{hBgNf;dIxBEjev6>DL`;OHYlo z6;uuMf>~@+v~%ikVX*SfoBLIweHatx6AfGy?Zc)ixXUved8Aw{L^A2&NHP|SqfJpSJG2iE+NU(xZ}`R7qaA(pQI7vaBzaqj9SwtXw8;P%cZxCZxP3A5UnFXT#gtduKwTF#fi5}9bSD4oOQ zgf$#3+QPfm`2u@oA@w%9;OGiAhQ=|VPsKv4Mjm4y6PaAJRO60sw_{@6;Lrf~hFvHy zG+IcCOfH)Y$s1eowwspeWt^4C#kM)piK-HkU}n96#TeVNV&#Gr%Vo+VSz+aK=y(ys zlf#tVC})f5WY&&{VyP%5!OBPDOKQ@@IS{X=jJA7wur$>^SCUNZ78W@sVxzg?FNzus zcYrgK=nt2iefq=)40D88V2ra-+SHt6hxU>Ffo$#k=Kn z$i3@Kt` z50|s0vh$pFc9$hveEs5{a92-w@wtwlFSF^+D@|zEU51l{q0I^E`fj{U`C;J2!sC(X zZ!&iIR!<2GJ_m(Uw?ft7D^{&vU#;H)w|i!)#Cz&@qW)}LpA>%pb?zx?viP5%-aQ^o zR{tvM*PbT-Nz}OqqRHahF%RxZXtMehsJBm(pGQLX>@zXG193Z1?;d(8^=rrc{+G2Q z{mwLsX6WvNjs?^1lyGs!2sV!h7fS^PQ?6C8GvN{+uCUzT;o)LYgbO)`up(?(qf2|k zcxzetm{m%Zv)jVMqtGBQZV#7}Ryv!=Aza$g;o*Y4-CG;QcQ|P?X(a&PecKH{KSVf| z8yT_jJ`HE_&JW{@(J8+HPK=$h5{2jpB9et%ne+3%mSYf3^N9J|5YA?T{}s05;{5RX zEG|x29WIs?xV(oNHJxG({QQToQg9*~1z|pZ;+c#2=iy=ujuW!%cTP--IdvopaZ&%@ zbY0LepPPpHxDVap_HQX1wCj}ckHE?vP<4#C!ef)a3Ee&%gWclh+XRPqyrURzGdj!h zvfu7_-HJ+&)2fE0Tv8po*(2fP35Bjm6@=X1jd$-FElDc4J_QZzJdl zkHa;0q0XD{F63kXnUC)(H{X8PjNyEjXVAauvUJ@4tZSOLci@VUiJ?QN5F z_aRXTotOce^UZujw&~4x6#oM)bCaOXV}ezS*RP9zoT}C^pF3K|>zA!n6@L8i<1PNm z)9LE@%Wk#!<%)WFLzTetJ70~8&+mMtJiK;s{55Y5#&d?N#V=>Z%QZ1uQSPZ0jPG0^ zZSGleetX>S8~Gsk*`E3>u-)$$>qo#DdhwAYz`G~#)0`YV|E%#K?V%G-W)lzalbopK zA>5lo9+bQedETvY@bv6;I43c$=Rc2x@@VRnsQ*1C{a{+_hc>M4AF?*ATeopwleMXT z_0WJN5;7zq67t0CP7wah?B+qv{pSO7J%-DN=Y0>b;WI+q4>a+J90uxV3h^7oUm?c_ zZ6@Yk4+$ZEL4%GzO42{B{PzO=X9@8%ka>PVKk9WnmW*4bkl#cNFUuei8YYN{|_?|-kJi+=Y3i-v3i}maqVQ^kDTQT)UsZU!!UGB)R49L_L;fR* zA6NLA!nYOvQz6%b{h6llOoa;-a-CS;r*KH&6$;}D4=MbC!p9Wy=VivfuJCPz?<@4- z#n1XCg|ii&qp(}yDuov*yj)>gA%B)1>eus$0{|#N_2H*ey literal 0 HcmV?d00001 diff --git a/apps/cli/Makefile.in b/apps/cli/Makefile.in new file mode 100644 index 000000000..4e54b7c78 --- /dev/null +++ b/apps/cli/Makefile.in @@ -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 +# . +# +# + +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 + diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c new file mode 100644 index 000000000..fc72b3467 --- /dev/null +++ b/apps/cli/cli_common.c @@ -0,0 +1,1930 @@ +/* + * + 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 + . + + * + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_CRYPT_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_cli_api.h" + +#include "cli_common.h" + +static int xml2csv(FILE *f, cxobj *x, cvec *cvv); +//static int xml2csv_raw(FILE *f, cxobj *x); + +/*! Initialize candidate database + * We have implemented these: + * shared - all users share a common candidate db + */ +int +init_candidate_db(clicon_handle h, enum candidate_db_type type) +{ + int retval = -1; + struct stat sb; + char *running_db; + char *candidate_db; + + if ((running_db = clicon_running_db(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: RUNNING_CANDIDATE_DB option not set", __FUNCTION__); + goto err; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: CLICON_CANDIDATE_DB option not set", __FUNCTION__); + goto err; + } + cli_set_candidate_type(h, type); + switch(type){ + case CANDIDATE_DB_NONE: + break; + case CANDIDATE_DB_PRIVATE: + if (lstat(candidate_db, &sb) < 0){ + if (file_cp(running_db, candidate_db) < 0){ + clicon_err(OE_UNIX, errno, "Error when copying %s to %s", + running_db, candidate_db); + unlink(candidate_db); + goto err; + } + } + break; + case CANDIDATE_DB_SHARED: + if (lstat(running_db, &sb) < 0){ + clicon_err(OE_FATAL, 0, "Running db (%s) does not exist", + running_db); + goto err; + } + if (lstat(candidate_db, &sb) < 0){ + if (cli_send2backend(h)) { + clicon_rpc_copy(h, running_db, candidate_db); + } + else + if (file_cp(running_db, candidate_db) < 0){ + clicon_err(OE_UNIX, errno, "Error when copying %s to %s", + running_db, candidate_db); + goto err; + } + } + break; + case CANDIDATE_DB_CURRENT: + clicon_option_str_set(h, "CLICON_CANDIDATE_DB", running_db); + break; + } + retval = 0; + err: + return retval; +} + +/* + * exit_candidate_db + * private canddidates should be removed + */ +int +exit_candidate_db(clicon_handle h) +{ +// struct stat sb; + + switch(cli_candidate_type(h)){ + case CANDIDATE_DB_PRIVATE: +#if 0 /* XXX: maybe we should remove it, but I want several cli:s to edit it */ + if (lstat(clicon_candidate_db(h), &sb) == 0) + unlink(clicon_candidate_db(h)); +#endif + break; + default: + break; + } + return 0; +} + +/* + * cli_debug + * set debug level on stderr (not syslog). + * The level is either what is specified in arg as int argument. + * _or_ if a 'level' variable is present in vars use that value instead. + */ +int +cli_debug(clicon_handle h, cvec *vars, cg_var *arg) +{ + cg_var *cv; + int level; + + if ((cv = cvec_find_var(vars, "level")) == NULL) + cv = arg; + level = cv_int32_get(cv); + /* cli */ + clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */ + /* config daemon */ + if (cli_send2backend(h)) { + if (clicon_rpc_debug(h, level) < 0) + goto done; + } + done: + return 0; +} + + +void +cli_signal_block(clicon_handle h) +{ + clicon_signal_block (SIGTSTP); + clicon_signal_block (SIGQUIT); + clicon_signal_block (SIGCHLD); + if (!clicon_quiet_mode(h)) + clicon_signal_block (SIGINT); +} + +void +cli_signal_unblock(clicon_handle h) +{ + clicon_signal_unblock (SIGTSTP); + clicon_signal_unblock (SIGQUIT); + clicon_signal_unblock (SIGCHLD); + clicon_signal_unblock (SIGINT); +} + +/* + * Flush pending signals for a given signal type + */ +void +cli_signal_flush(clicon_handle h) +{ + /* XXX A bit rough. Use sigpending() and more clever logic ?? */ + + sigfn_t h1, h2, h3, h4; + + set_signal (SIGTSTP, SIG_IGN, &h1); + set_signal (SIGQUIT, SIG_IGN, &h2); + set_signal (SIGCHLD, SIG_IGN, &h3); + set_signal (SIGINT, SIG_IGN, &h4); + + cli_signal_unblock (h); + + set_signal (SIGTSTP, h1, NULL); + set_signal (SIGQUIT, h2, NULL); + set_signal (SIGCHLD, h3, NULL); + set_signal (SIGINT, h4, NULL); + + cli_signal_block (h); +} + + +/* Code for recording which CLI commands have been issued */ + +static FILE *_recordf = NULL; +static int _isrecording = 0; + +int +isrecording(void) +{ + return _isrecording; +} + +int +cli_record(clicon_handle h, cvec *vars, cg_var *arg) +{ + _isrecording = cv_int32_get(arg); + return 0; +} + +static int +record_open(void) +{ + char file[] = "/tmp/cli.record.XXXXXX"; + int fd; + + if ((fd = mkstemp(file)) < 0 || (_recordf = fdopen(fd, "w")) < 0) { + clicon_err(OE_UNIX, errno, "mkstemp/fdopen"); + return -1; + } + return 0; +} + +/* + * record commands in file + */ +int +record_command(char *str) +{ + if (_recordf==NULL) + if (record_open() < 0) + return -1; + fprintf(_recordf, "%s\n", str); + fflush(_recordf); + return 0; +} + + +/* + * Callback to set syntax mode + */ +int +cli_set_mode(clicon_handle h, cvec *vars, cg_var *arg) +{ + int retval = -1; + char *str = NULL; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + cli_set_syntax_mode(h, str); + retval = 0; + done: + return retval; +} + +/* + * XXX Application specific?? + * cli_start_shell + * Start bash from cli callback + */ +int +cli_start_shell(clicon_handle h, cvec *vars, cg_var *arg) +{ + char *cmd; + struct passwd *pw; + int retval; + char bcmd[128]; + cg_var *cv1 = cvec_i(vars, 1); + + cmd = (cvec_len(vars)>1 ? cv_string_get(cv1) : NULL); + + if ((pw = getpwuid(getuid())) == NULL){ + fprintf(stderr, "%s: getpwuid: %s\n", + __FUNCTION__, strerror(errno)); + return -1; + } + if (chdir(pw->pw_dir) < 0){ + fprintf(stderr, "%s: chdir(%s): %s\n", + __FUNCTION__, pw->pw_dir, strerror(errno)); + endpwent(); + return -1; + } + endpwent(); + cli_signal_flush(h); + cli_signal_unblock(h); + if (cmd){ + snprintf(bcmd, 128, "bash -l -c \"%s\"", cmd); + if ((retval = system(bcmd)) < 0){ + cli_signal_block(h); + fprintf(stderr, "%s: system(bash -c): %s\n", + __FUNCTION__, strerror(errno)); + return -1; + } + } + else + if ((retval = system("bash -l")) < 0){ + cli_signal_block(h); + fprintf(stderr, "%s: system(bash): %s\n", + __FUNCTION__, strerror(errno)); + return -1; + } + cli_signal_block(h); +#if 0 /* Allow errcodes from bash */ + if (retval != 0){ + fprintf(stderr, "%s: system(%s) code=%d\n", __FUNCTION__, cmd, retval); + return -1; + } +#endif + + return 0; +} + +/* + * Generic quit callback + */ +int +cli_quit(clicon_handle h, cvec *vars, cg_var *arg) +{ + cli_set_exiting(h, 1); + return 0; +} + +/* + * Generic commit callback + * if arg is 1, then snapshot and copy to startup config + */ +int +cli_commit(clicon_handle h, cvec *vars, cg_var *arg) +{ + int retval = -1; + int snapshot = arg?cv_int32_get(arg):0; + char *candidate; + char *running; + + if ((running = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + if ((candidate = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + if ((retval = clicon_rpc_commit(h, + running, + candidate, + snapshot, /* snapshot */ + snapshot)) < 0){ /* startup */ + cli_output(stderr, "Commit failed. Edit and try again or discard changes\n"); + goto done; + } + retval = 0; + done: + return retval; +} + +/* + * Generic validatecallback + */ +int +cli_validate(clicon_handle h, cvec *vars, cg_var *arg) +{ + char *candidate_db; + int retval = -1; + + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + return -1; + } + if (cli_send2backend(h)) { + if ((retval = clicon_rpc_validate(h, candidate_db)) < 0) + cli_output(stderr, "Validate failed. Edit and try again or discard changes\n"); + } + return retval; +} + + + + +/*! Completion callback primarily intended for automatically generated data model + * + * Returns an expand-type list of commands as used by cligen 'expand' + * functionality. + * arg is a string: " ". + * is either running or candidate + * matches a set of database keys following clicon_dbspec. + * Eg a[].b[] $!x $!y + * the last being the variable to expand for. + * Example: + * dbspec is a[].b[] $!x $!y + * clispec is a b (|; + * db contains entries: + * a.0 $x=5 + * a.1 $x=10 + * a.0.b.0 $x=5 $y=12 + * a.0.b.1 $x=5 $y=20 + * a.1.b.0 $x=10 $y=99 + * + * The user types a 5 b which produces the following output: + * + * 12 + * 20 + * + * Assume callback given in a cligen spec: a " + * @param[out] len len of return commands & helptxt + * @param[out] commands vector of function pointers to callback functions + * @param[out] helptxt vector of pointers to helptexts + * @see cli_expand_var_generate This is where arg is generated + */ +int +expand_dbvar_dbxml(void *h, + char *name, + cvec *cvv, + cg_var *arg, + int *nr, + char ***commands, + char ***helptexts) +{ + char *dbname; + int nvec; + char **vec = NULL; + int retval = -1; + char *xkfmt; + char *str; + char *dbstr; + cxobj *xt = NULL; + char *xk = NULL; + int i; + int i0; + struct db_pair *pairs; + int npairs; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + /* In the example, str = "candidate a[].b[] $!x $!y" */ + if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); + goto done; + } + dbstr = vec[0]; + if (strcmp(dbstr, "running") == 0) + dbname = clicon_running_db(h); + else + if (strcmp(dbstr, "candidate") == 0) + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "db not set"); + goto done; + } + xkfmt = vec[1]; + /* xkfmt = "/test/kalle/%s/lasse" --> "^/test/kalle/.* /lasse$" */ + if (xmlkeyfmt2key2(xkfmt, cvv, &xk) < 0) + goto done; + if ((npairs = db_regexp(dbname, xk, __FUNCTION__, &pairs, 0)) < 0) + goto done; + i0 = *nr; + *nr += npairs; + if ((*commands = realloc(*commands, sizeof(char *) * (*nr))) == NULL) { + clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno)); + goto done; + } + for (i = 0; i < npairs; i++) + (*commands)[i0+i] = strdup(pairs[i].dp_val); + + retval = 0; + done: + unchunk_group(__FUNCTION__); + if (xt) + xml_free(xt); + if (xk) + free(xk); + return retval; + +} +#ifdef NOTUSED + +/*! Expand based on database key and variable value (of that key) + * + * Return an expand-type list of commands as used by cligen 'expand' + * functionality. + * arg is a string: " ". + * is either running or candidate + * matches a set of database keys + * is name of a variable occuring in the cli command string + * Example: "candidate ^Create.*$" GroupName" + * (See also expand_db_variable(). + * + * Assume callback given in a cligen spec: a ", + str); + goto done; + } + dbstr = vec[0]; + keystr = vec[1]; + varstr = vec[2]; + if (strcmp(dbstr, "running") == 0) + dbname = clicon_running_db(h); + else + if (strcmp(dbstr, "candidate") == 0) + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "dbname not set"); + goto done; + } + if ((retval = expand_db_variable(h, dbname, keystr, varstr, nr, commands)) < 0) + goto done; + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +/*! Expand database variable + * Given a database, a basekey (pattern) and a variable, return an expand-type + * list of commands as used by cligen 'expand' functionality. + * @see expand_dbvar + */ +int +expand_db_variable(clicon_handle h, + char *dbname, + char *basekey, + char *variable, + int *nr, + char ***commands) +{ + char *key; + int i; + int j; + int retval = -1; + cvec *cvv; + cg_var *cv = NULL; + char **tmp; + char *val = NULL; + cvec **cvvp = NULL; + size_t len = 0; + + /* adhoc to detect regexp keys. If so, dont call db_gen_rxkey */ + if (index(basekey, '^') == NULL){ + if ((key = db_gen_rxkey(basekey, __FUNCTION__)) == NULL) + goto quit; + } + else + key = chunkdup(basekey, strlen(basekey)+1, __FUNCTION__); + + if (clicon_dbitems(dbname, key, &cvvp, &len) < 0) + goto quit; + for (i = 0; i < len; i++) { + cvv = cvvp[i]; + cv = NULL; + while ((cv = cvec_each(cvv, cv)) != NULL) { + if (strcmp(cv_name_get(cv), variable) != 0) + continue; + if ((val = cv2str_dup(cv)) == NULL) + goto quit; + /* Check if value already in vector? No duplicates */ + for (j=0; j<*nr; j++) + if (strcmp(val, (*commands)[j]) == 0) + break; + if (j<*nr){ + free(val); + val = NULL; + continue; + } + if ((tmp = realloc(*commands, sizeof(char *) * ((*nr)+1))) == NULL) { + clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno)); + goto quit; + } + *commands = tmp; + (*commands)[*nr] = val; + val = NULL; + (*nr)++; + break; + } + } + retval = 0; +quit: + if (cvvp) + clicon_dbitems_free(cvvp, len); + unchunk_group(__FUNCTION__); + return retval; +} + +/*! Pattern match in candidate_db + */ +int +expand_db_symbol(clicon_handle h, + char *symbol, + int element, + int *nr, + char ***commands) +{ + int retval = -1; + char **tmp; + cvec **cvvp = NULL; + cvec *cvv; + size_t len = 0; + int i; + char *key; + int nvec; + int n; + char **vec = NULL; + char str[128]; + char *dbname; + + if ((dbname = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + snprintf(str, sizeof(str), "^%s\\..", symbol); + if (clicon_rpc_dbitems(h, dbname, str, NULL, NULL, &cvvp, &len) < 0) + goto done; + for (i = 0; i < len; i++) { + cvv = cvvp[i]; + key = cvec_name_get(cvv); + if ((vec = clicon_strsplit(key, ".", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_UNDEF, errno, "clicon_strsplit"); + goto done; + } + /* Check if already exists */ + for (n=0; n<*nr; n++) + if (strcmp((*commands)[n], vec[element]) == 0) + break; /* Already exists */ + if (n<*nr) + continue; + /* Allocate new pointer */ + if ((tmp = realloc(*commands, sizeof(char *) * ((*nr)+1))) == NULL) { + clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno)); + goto done; + } + *commands = tmp; + /* Duplicate string */ + if (((*commands)[*nr] = strdup(vec[element])) == NULL) { + clicon_err(OE_UNDEF, errno, "strdup: %s", strerror (errno)); + goto done; + } + (*nr)++; + } + retval = 0; + done: + unchunk_group(__FUNCTION__) ; + if (cvvp) + clicon_dbitems_free(cvvp, len); + if (retval < 0 && *commands){ + while ((*nr) >= 0) + free((*commands)[(*nr)--]); + free (*commands); + } + return retval; +} +#endif /* NOTUSED */ + +/* + * expand_dir + * List files in a directory + */ +int +expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail) +{ + DIR *dirp; + struct dirent *dp; + struct stat st; + char *str; + char *cmd; + int len; + int retval = -1; + struct passwd *pw; + char filename[MAXPATHLEN]; + + if ((dirp = opendir(dir)) == 0){ + fprintf(stderr, "expand_dir: opendir(%s) %s\n", + dir, strerror(errno)); + return -1; + } + *nr = 0; + while ((dp = readdir(dirp)) != NULL) { + if ( +#if 0 + strcmp(dp->d_name, ".") != 0 && + strcmp(dp->d_name, "..") != 0 +#else + dp->d_name[0] != '.' +#endif + ) { + snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp->d_name); + if (lstat(filename, &st) == 0){ + if ((st.st_mode & flags) == 0) + continue; + +#if EXPAND_RECURSIVE + if (S_ISDIR(st.st_mode)) { + int nrsav = *nr; + if(expand_dir(filename, nr, commands, detail) < 0) + goto quit; + while(nrsav < *nr) { + len = strlen(dp->d_name) + strlen((*commands)[nrsav]) + 2; + if((str = malloc(len)) == NULL) { + fprintf(stderr, "expand_dir: malloc: %s\n", + strerror(errno)); + goto quit; + } + snprintf(str, len-1, "%s/%s", + dp->d_name, (*commands)[nrsav]); + free((*commands)[nrsav]); + (*commands)[nrsav] = str; + + nrsav++; + } + continue; + } +#endif + if ((cmd = strdup(dp->d_name)) == NULL) { + fprintf(stderr, "expand_dir: strdup: %s\n", + strerror(errno)); + goto quit; + } + if (0 &&detail){ + if ((pw = getpwuid(st.st_uid)) == NULL){ + fprintf(stderr, "expand_dir: getpwuid(%d): %s\n", + st.st_uid, strerror(errno)); + goto quit; + } + len = strlen(cmd) + + strlen(pw->pw_name) + +#ifdef __FreeBSD__ + strlen(ctime(&st.st_mtimespec.tv_sec)) + +#else + strlen(ctime(&st.st_mtim.tv_sec)) + +#endif + + strlen("{ by }") + 1 /* \0 */; + if ((str=realloc(cmd, strlen(cmd)+len)) == NULL) { + fprintf(stderr, "expand_dir: malloc: %s\n", + strerror(errno)); + goto quit; + } + snprintf(str + strlen(dp->d_name), + len - strlen(dp->d_name), + "{%s by %s}", +#ifdef __FreeBSD__ + ctime(&st.st_mtimespec.tv_sec), +#else + ctime(&st.st_mtim.tv_sec), +#endif + + pw->pw_name + ); + cmd = str; + } + if (((*commands) = + realloc(*commands, ((*nr)+1)*sizeof(char**))) == NULL){ + perror("expand_dir: realloc"); + goto quit; + } + (*commands)[(*nr)] = cmd; + (*nr)++; + if (*nr >= 128) /* Limit number of options */ + break; + } + } + } + retval = 0; + quit: + closedir(dirp); + return retval; +} + +/*! Compare two dbs using XML. Write to file and run diff + */ +static int +compare_xmls(cxobj *xc1, cxobj *xc2, int astext) +{ + int fd; + FILE *f; + char filename1[MAXPATHLEN]; + char filename2[MAXPATHLEN]; + char cmd[MAXPATHLEN]; + int retval = -1; + cxobj *xc; + + snprintf(filename1, sizeof(filename1), "/tmp/cliconXXXXXX"); + snprintf(filename2, sizeof(filename2), "/tmp/cliconXXXXXX"); + if ((fd = mkstemp(filename1)) < 0){ + clicon_err(OE_UNDEF, errno, "tmpfile: %s", strerror (errno)); + goto done; + } + if ((f = fdopen(fd, "w")) == NULL) + goto done; + xc = NULL; + if (astext) + while ((xc = xml_child_each(xc1, xc, -1)) != NULL) + xml2txt(f, xc, 0); + else + while ((xc = xml_child_each(xc1, xc, -1)) != NULL) + clicon_xml2file(f, xc, 0, 1); + + fclose(f); + close(fd); + + if ((fd = mkstemp(filename2)) < 0){ + clicon_err(OE_UNDEF, errno, "mkstemp: %s", strerror (errno)); + goto done; + } + if ((f = fdopen(fd, "w")) == NULL) + goto done; + xc = NULL; + if (astext) + while ((xc = xml_child_each(xc2, xc, -1)) != NULL) + xml2txt(f, xc, 0); + else + while ((xc = xml_child_each(xc2, xc, -1)) != NULL) + clicon_xml2file(f, xc, 0, 1); + fclose(f); + close(fd); + + snprintf(cmd, sizeof(cmd), "/usr/bin/diff -dU 1 %s %s | grep -v @@ | sed 1,2d", filename1, filename2); + if (system(cmd) < 0) + goto done; + + retval = 0; + done: + unlink(filename1); + unlink(filename2); + return retval; +} + +/*! Compare two dbs using XML. Write to file and run diff + * @param[in] h Clicon handle + * @param[in] cvv + * @param[in] arg arg: 0 as xml, 1: as text + */ +int +compare_dbs(clicon_handle h, cvec *cvv, cg_var *arg) +{ + cxobj *xc1 = NULL; /* running xml */ + cxobj *xc2 = NULL; /* candidate xml */ + int retval = -1; + char *running; + char *candidate; + + if ((running = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + if ((candidate = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + if (xmldb_get(running, "/", clicon_dbspec_yang(h), &xc1) < 0) + goto done; + if (xmldb_get(candidate, "/", clicon_dbspec_yang(h), &xc2) < 0) + goto done; + if (compare_xmls(xc1, xc2, arg?cv_int32_get(arg):0) < 0) /* astext? */ + goto done; + retval = 0; + done: + if (xc1) + xml_free(xc1); + if (xc2) + xml_free(xc2); + + return retval; +} + + +/*! Modify xml database frm a callback using xml key format strings + * @param[in] h Clicon handle + * @param[in] cvv Vector of cli string and instantiated variables + * @param[in] arg An xml key format string, eg /aaa/%s + * @param[in] op Operation to perform on database + * Cvv will contain forst the complete cli string, and then a set of optional + * instantiated variables. + * Example: + * cvv[0] = "set interfaces interface eth0 type bgp" + * cvv[1] = "eth0" + * cvv[2] = "bgp" + * arg = "/interfaces/interface/%s/type" + * op: OP_MERGE + * @see cli_callback_xmlkeyfmt_generate where arg is generated + */ +static int +cli_dbxml(clicon_handle h, + cvec *cvv, + cg_var *arg, + enum operation_type op) +{ + int retval = -1; + char *str = NULL; + char *candidate; + char *running; + char *xkfmt; /* xml key format */ + char *xk = NULL; /* xml key */ + cg_var *cval; + char *val = NULL; + yang_spec *yspec; + + /* + * clicon_rpc_xmlput(h, db, MERGE,"eth0hej"); + * Wanted database content: + * /interfaces + * /interfaces/interface/eth0 + * /interfaces/interface/eth0/name eth0 + * /interfaces/interface/eth0/type hej + * Algorithm alt1: + * arg = "$1$2" + * Where is arg computed? In eg yang2cli_leaf, otherwise in yang_parse,.. + * Create string using cbuf and save that. + */ + if ((candidate = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + return -1; + } + if ((running = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + return -1; + } + xkfmt = cv_string_get(arg); + if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0) + goto done; + cval = cvec_i(cvv, cvec_len(cvv)-1); + if ((val = cv2str_dup(cval)) == NULL){ + clicon_err(OE_UNIX, errno, "cv2str_dup"); + goto done; + } + if (cli_send2backend(h)) { + if (clicon_rpc_change(h, candidate, op, xk, val) < 0) + goto done; + if (clicon_autocommit(h)) { + if (clicon_rpc_commit(h, running, candidate, 0, 0) < 0) + goto done; + } + } + else{ + yspec = clicon_dbspec_yang(h); + if (xmldb_put_xkey(candidate, xk, val, yspec, op) < 0) + goto done; + if (clicon_autocommit(h)) + clicon_log(LOG_WARNING, "Cant combine no backend and autocommit"); + } + retval = 0; + done: + if (str) + free(str); + if (xk) + free(xk); + return retval; +} + +int +cli_set(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int retval = 1; + + if (cli_dbxml(h, cvv, arg, OP_REPLACE) < 0) + goto done; + retval = 0; + done: + return retval; +} + +int +cli_merge(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int retval = -1; + + if (cli_dbxml(h, cvv, arg, OP_MERGE) < 0) + goto done; + retval = 0; + done: + return retval; +} + +int +cli_del(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int retval = -1; + + if (cli_dbxml(h, cvv, arg, OP_REMOVE) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Load a configuration file to candidate database + * Utility function used by cligen spec file + * @param[in] h CLICON handle + * @param[in] cvv Vector of variables (where is found) + * @param[in] arg A string: " (merge|replace)" + * is name of a variable occuring in "cvv" containing filename + * @note that "filename" is local on client filesystem not backend. + * @note file is assumed to have a dummy top-tag, eg + * @code + * # cligen spec + * load file , load_config_file("name2 merge"); + * @endcode + * @see save_config_file + */ +int +load_config_file(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int ret = -1; + struct stat st; + char **vec; + char **vecp; + char *filename; + int replace; + char *dbname; + char *str; + cg_var *cv; + int nvec; + char *opstr; + char *varstr; + int fd = -1; + cxobj *xt = NULL; + cxobj *xn; + cxobj *x; + cbuf *cbxml; + yang_spec *yspec; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); + goto done; + } + if (nvec != 2){ + clicon_err(OE_PLUGIN, 0, "Arg syntax is "); + goto done; + } + varstr = vec[0]; + opstr = vec[1]; + if (strcmp(opstr, "merge") == 0) + replace = 0; + else + if (strcmp(opstr, "replace") == 0) + replace = 1; + else{ + clicon_err(OE_PLUGIN, 0, "No such op: %s, expected merge or replace", opstr); + goto done; + } + if ((cv = cvec_find_var(cvv, varstr)) == NULL){ + clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr); + goto done; + } + if ((vecp = clicon_realpath(NULL, cv_string_get(cv), __FUNCTION__)) == NULL){ + cli_output(stderr, "Failed to resolve filename\n"); + goto done; + } + filename = vecp[0]; + if ((dbname = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + if (stat(filename, &st) < 0){ + clicon_err(OE_UNIX, 0, "load_config: stat(%s): %s\n", + filename, strerror(errno)); + goto done; + } + if (cli_send2backend(h)) { + /* Open and parse local file into xml */ + if ((fd = open(filename, O_RDONLY)) < 0){ + clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename); + goto done; + } + if (clicon_xml_parse_file(fd, &xt, "") < 0) + goto done; + if ((xn = xml_child_i(xt, 0)) != NULL){ + if ((cbxml = cbuf_new()) == NULL) + goto done; + x = NULL; + while ((x = xml_child_each(xn, x, -1)) != NULL) + if (clicon_xml2cbuf(cbxml, x, 0, 0) < 0) + goto done; + if (clicon_rpc_xmlput(h, dbname, + replace?OP_REPLACE:OP_MERGE, + cbuf_get(cbxml)) < 0) + goto done; + cbuf_free(cbxml); + } + } + else{ + if (replace){ + if (unlink(dbname) < 0){ + clicon_err(OE_UNIX, 0, "rm %s %s", filename, strerror(errno)); + goto done; + } + if (db_init(dbname) < 0) + goto done; + } + if ((fd = open(filename, O_RDONLY)) < 0){ + clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename); + goto done; + } + if (clicon_xml_parse_file(fd, &xt, "") < 0) + goto done; + yspec = clicon_dbspec_yang(h); + if ((xn = xml_child_i(xt, 0)) != NULL){ + if (xmldb_put(dbname, xn, yspec, replace?OP_REPLACE:OP_MERGE) < 0) + goto done; + } + } + ret = 0; + done: + if (xt) + xml_free(xt); + if (fd != -1) + close(fd); + return ret; +} + +/*! Copy database to local file + * Utility function used by cligen spec file + * @param[in] h CLICON handle + * @param[in] cvv variable vector (containing ) + * @param[in] arg a string: " " + * is running or candidate + * is name of cligen variable in the "cvv" vector containing file name + * Note that "filename" is local on client filesystem not backend. + * The function can run without a local database + * @note The file is saved with dummy top-tag: clicon: + * @code + * save file , save_config_file("running name"); + * @endcode + * @see load_config_file + */ +int +save_config_file(clicon_handle h, + cvec *cvv, + cg_var *arg) +{ + int retval = -1; + char **vec; + char **vecp; + char *filename; + char *dbname; + cg_var *cv; + int nvec; + char *str; + char *dbstr; + char *varstr; + cxobj *xt = NULL; + FILE *f = NULL; + yang_spec *yspec; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); + goto done; + } + if (nvec != 2){ + clicon_err(OE_PLUGIN, 0, "Arg syntax is "); + goto done; + } + dbstr = vec[0]; + varstr = vec[1]; + if (strcmp(dbstr, "running") == 0) + dbname = clicon_running_db(h); + else + if (strcmp(dbstr, "candidate") == 0) + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "dbname not set"); + goto done; + } + + if ((cv = cvec_find_var(cvv, varstr)) == NULL){ + clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr); + goto done; + } + if ((vecp = clicon_realpath(NULL, cv_string_get(cv), __FUNCTION__)) == NULL){ + cli_output(stderr, "Failed to resolve filename\n"); + goto done; + } + filename = vecp[0]; + yspec = clicon_dbspec_yang(h); + if (xmldb_get(dbname, "/", yspec, &xt) < 0) + goto done; + if ((f = fopen(filename, "wb")) == NULL){ + clicon_err(OE_CFG, errno, "Creating file %s", filename); + goto done; + } + if (clicon_xml2file(f, xt, 0, 1) < 0) + goto done; + retval = 0; + /* Fall through */ + done: + unchunk_group(__FUNCTION__); + if (xt) + xml_free(xt); + if (f != NULL) + fclose(f); + return retval; +} + +/*! Delete all elements in a database + * Utility function used by cligen spec file + */ +int +delete_all(clicon_handle h, cvec *cvv, cg_var *arg) +{ + char *dbname; + char *dbstr; + int retval = -1; + + if (arg == NULL || (dbstr = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + if (strcmp(dbstr, "running") == 0) + dbname = clicon_running_db(h); + else + if (strcmp(dbstr, "candidate") == 0) + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "dbname not set"); + goto done; + } + if (cli_send2backend(h)) { + clicon_rpc_rm(h, dbname); + clicon_rpc_initdb(h, dbname); + } + else{ + if (unlink(dbname) < 0){ + clicon_err(OE_FATAL, errno, "unlink(%s)", dbname); + goto done; + } + if (db_init(dbname) < 0) + goto done; + } + retval = 0; + done: + return retval; +} + +/*! Discard all changes in candidate and replace with running + * Utility function used by cligen spec file + */ +int +discard_changes(clicon_handle h, cvec *cvv, cg_var *arg) +{ + char *running_db; + char *candidate_db; + int retval = -1; + + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + if ((running_db = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + clicon_rpc_copy(h, running_db, candidate_db); + retval = 0; + done: + return retval; +} + +/*! Generic function for showing configurations. + * the callback differs. + * @param[in] h CLICON handle + * @param[in] cvv Vector of variables (not needed) + * @param[in] arg A string: + * is either running or candidate + * xpath expression as in nertconf get-config + * @param fn + * @param fnarg + * @code + * # cligen spec + * show config id , show_conf_as("running interfaces/interface[name=eth*]"); + * @endcode + */ +static int +show_conf_xmldb_as(clicon_handle h, + cvec *cvv, + cg_var *arg, + cxobj **xt) /* top xml */ +{ + int retval = -1; + char *dbname; + char **vec = NULL; + int nvec; + char *str; + char *xpath; + yang_spec *yspec; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); + goto done; + } + if (nvec != 2){ + clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected ", str); + goto done; + } + /* Dont get attr here, take it from arg instead */ + if (strcmp(vec[0], "running") == 0) /* XXX: hardcoded */ + dbname = clicon_running_db(h); + else + if (strcmp(vec[0], "candidate") == 0) /* XXX: hardcoded */ + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", vec[0]); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "dbname not set"); + goto done; + } + xpath = vec[1]; + yspec = clicon_dbspec_yang(h); + if (xmldb_get(dbname, xpath, yspec, xt) < 0) + goto done; + retval = 0; +done: + unchunk_group(__FUNCTION__); + return retval; +} + + +/*! Show a configuration database on stdout using XML format + * Utility function used by cligen spec file + */ +static int +show_conf_as_xml1(clicon_handle h, cvec *cvv, cg_var *arg, int netconf) +{ + cxobj *xt = NULL; + cxobj *xc; + int retval = -1; + + if (show_conf_xmldb_as(h, cvv, arg, &xt) < 0) + goto done; + if (netconf) /* netconf prefix */ + fprintf(stdout, "\n"); + xc = NULL; /* Dont print xt itself */ + while ((xc = xml_child_each(xt, xc, -1)) != NULL) + clicon_xml2file(stdout, xc, netconf?2:0, 1); + if (netconf) /* netconf postfix */ + fprintf(stdout, "]]>]]>\n"); + retval = 0; + done: + if (xt) + xml_free(xt); + return retval; + +} + +/*! Show configuration as prettyprinted xml + * Utility function used by cligen spec file + */ +int +show_conf_as_xml(clicon_handle h, cvec *cvv, cg_var *arg) +{ + return show_conf_as_xml1(h, cvv, arg, 0); +} + +/*! Show configuration as prettyprinted xml with netconf hdr/tail + * Utility function used by cligen spec file + */ +int +show_conf_as_netconf(clicon_handle h, cvec *cvv, cg_var *arg) +{ + return show_conf_as_xml1(h, cvv, arg, 1); +} + +/*! Show configuration as JSON + * Utility function used by cligen spec file + */ +int +show_conf_as_json(clicon_handle h, cvec *cvv, cg_var *arg) +{ + cxobj *xt = NULL; + cxobj *xc; + int retval = -1; + + if (show_conf_xmldb_as(h, cvv, arg, &xt) < 0) + goto done; + xc = NULL; /* Dont print xt itself */ + while ((xc = xml_child_each(xt, xc, -1)) != NULL) + xml2json(stdout, xc, 1); + retval = 0; + done: + if (xt) + xml_free(xt); + return retval; +} + +int +show_conf_xpath(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int retval = -1; + char *dbname; + char **vec = NULL; + char *str; + char *xpath; + yang_spec *yspec; + cg_var *cv; + cxobj *xt = NULL; + cxobj **xv = NULL; + int xlen; + int i; + + if (arg == NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + /* Dont get attr here, take it from arg instead */ + if (strcmp(str, "running") == 0) /* XXX: hardcoded */ + dbname = clicon_running_db(h); + else + if (strcmp(str, "candidate") == 0) /* XXX: hardcoded */ + dbname = clicon_candidate_db(h); + else{ + clicon_err(OE_PLUGIN, 0, "No such db name: %s", vec[0]); + goto done; + } + if (dbname == NULL){ + clicon_err(OE_FATAL, 0, "dbname not set"); + goto done; + } + cv = cvec_find_var(cvv, "xpath"); + xpath = cv_string_get(cv); + yspec = clicon_dbspec_yang(h); + if (xmldb_get_xpath(dbname, xpath, yspec, &xt, &xv, &xlen) < 0) + goto done; + for (i=0; iop_type); + switch (type){ + case CLICON_MSG_NOTIFY: + if (clicon_msg_notify_decode(reply, &level, &eventstr, __FUNCTION__) < 0) + goto done; + if (strcmp(format, SHOWAS_TXT) == 0){ + fprintf(stdout, "%s", eventstr); + } + else + if (strcmp(format, SHOWAS_XML) == 0){ + if (clicon_xml_parse_string(&eventstr, &xt) < 0) + goto done; + if ((xn = xml_child_i(xt, 0)) != NULL) + if (clicon_xml2file(stdout, xn, 0, 1) < 0) + goto done; + } + else + if (strcmp(format, SHOWAS_XML2TXT) == 0){ + if (clicon_xml_parse_string(&eventstr, &xt) < 0) + goto done; + if ((xn = xml_child_i(xt, 0)) != NULL) + if (xml2txt(stdout, xn, 0) < 0) + goto done; + } + else + if (strcmp(format, SHOWAS_XML2JSON) == 0){ + if (clicon_xml_parse_string(&eventstr, &xt) < 0) + goto done; + if ((xn = xml_child_i(xt, 0)) != NULL){ + if (xml2json(stdout, xn, 0) < 0) + goto done; + } + } + break; + default: + clicon_err(OE_PROTO, 0, "%s: unexpected reply: %d", + __FUNCTION__, type); + goto done; + break; + } + retval = 0; + done: + if (xt) + xml_free(xt); + unchunk_group(__FUNCTION__); /* event allocated by chunk */ + return retval; + +} + + +/*! Make a notify subscription to backend and un/register callback for return messages. + * + * @param[in] h Clicon handle + * @param[in] cvv Not used + * @param[in] arg A string with [] + * where is "0" or "1" + * and is XXX + * Example code: Start logging of mystream and show logs as xml + * @code + * cmd("comment"), cli_notify("mystream 1 xml"); + * @endcode + * XXX: format is a memory leak + */ +int +cli_notify(clicon_handle h, cvec *cvv, cg_var *arg) +{ + char *stream = NULL; + int retval = -1; + char **vec = NULL; + int nvec; + char *str; + int status; + char *formatstr = NULL; + enum format_enum format = MSG_NOTIFY_TXT; + + if (arg==NULL || (str = cv_string_get(arg)) == NULL){ + clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); + goto done; + } + if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ + clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); + goto done; + } + if (nvec < 2){ + clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected ", str); + goto done; + } + stream = vec[0]; + status = atoi(vec[1]); + if (nvec > 2){ + formatstr = strdup(vec[2]); /* memory leak */ + if (strcmp(formatstr, "SHOWAS_TXT") != 0) + format = MSG_NOTIFY_XML; + } + if (cli_notification_register(h, + stream, + format, + "", + status, + cli_notification_cb, + (void*)formatstr) < 0) + goto done; + + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +/*! Register log notification stream + * @param[in] h Clicon handle + * @param[in] stream Event stream. CLICON is predefined, others are application-defined + * @param[in] filter Filter. For xml notification ie xpath: /[name=kalle] + * @param[in] status 0 for stop, 1 to start + * @param[in] fn Callback function called when notification occurs + * @param[in] arg Argumnent to function + */ +int +cli_notification_register(clicon_handle h, + char *stream, + enum format_enum format, + char *filter, + int status, + int (*fn)(int, void*), + void *arg) +{ + int retval = -1; + char *logname; + void *p; + int s; + clicon_hash_t *cdat = clicon_data(h); + size_t len; + int s_exist = -1; + + if ((logname = chunk_sprintf(__FUNCTION__, "log_socket_%s", stream)) == NULL){ + clicon_err(OE_PLUGIN, errno, "%s: chunk_sprintf", __FUNCTION__); + goto done; + } + if ((p = hash_value(cdat, logname, &len)) != NULL) + s_exist = *(int*)p; + + if (status){ + if (s_exist!=-1){ + clicon_err(OE_PLUGIN, 0, "%s: result log socket already exists", __FUNCTION__); + goto done; + } + if (clicon_rpc_subscription(h, status, stream, format, filter, &s) < 0) + goto done; + if (cligen_regfd(s, fn, arg) < 0) + goto done; + if (hash_add(cdat, logname, &s, sizeof(s)) == NULL) + goto done; + } + else{ + if (s_exist != -1){ + cligen_unregfd(s_exist); + } + hash_del(cdat, logname); + if (clicon_rpc_subscription(h, status, stream, format, filter, NULL) < 0) + goto done; + + } + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + + +#ifdef notused +/*! XML to CSV raw variant + * @see xml2csv + */ +static int +xml2csv_raw(FILE *f, cxobj *x) +{ + cxobj *xc; + cxobj *xb; + int retval = -1; + int i = 0; + + xc = NULL; + while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) { + if (xml_child_nr(xc)){ + xb = xml_child_i(xc, 0); + if (xml_type(xb) == CX_BODY){ + if (i++) + fprintf(f, ";"); + fprintf(f, "%s", xml_value(xb)); + } + } + } + fprintf(f, "\n"); + retval = 0; + return retval; +} +#endif + +/*! Translate XML -> CSV commands + * Can only be made in a 'flat tree', ie on the form: + * B --> + * Type, A + * X, B + * @param[in] f Output file + * @param[in] x XML tree + * @param[in] cvv A vector of field names present in XML + * This means that only fields in x that are listed in cvv will be printed. + */ +static int +xml2csv(FILE *f, cxobj *x, cvec *cvv) +{ + cxobj *xe, *xb; + int retval = -1; + cg_var *vs; + + fprintf(f, "%s", xml_name(x)); + xe = NULL; + + vs = NULL; + while ((vs = cvec_each(cvv, vs))) { + if ((xe = xml_find(x, cv_name_get(vs))) == NULL){ + fprintf(f, ";"); + continue; + } + if (xml_child_nr(xe)){ + xb = xml_child_i(xe, 0); + fprintf(f, ";%s", xml_value(xb)); + } + } + fprintf(f, "\n"); + retval = 0; + return retval; +} + + +static int +show_conf_as_csv1(clicon_handle h, cvec *cvv0, cg_var *arg) +{ + cxobj *xt = NULL; + cxobj *xc; + int retval = -1; + cvec *cvv=NULL; + char *str; + + if (show_conf_xmldb_as(h, cvv0, arg, &xt) < 0) + goto done; + xc = NULL; /* Dont print xt itself */ + while ((xc = xml_child_each(xt, xc, -1)) != NULL){ + if ((str = chunk_sprintf(__FUNCTION__, "%s[]", xml_name(xc))) == NULL) + goto done; +#ifdef NOTYET /* yang-spec? */ + if (ds==NULL && (ds = key2spec_key(dbspec, str)) != NULL){ + cg_var *vs; + fprintf(stdout, "Type"); + cvv = db_spec2cvec(ds); + vs = NULL; + while ((vs = cvec_each(cvv, vs))) + fprintf(stdout, ";%s", cv_name_get(vs)); + fprintf(stdout, "\n"); + } /* Now values just need to follow,... */ +#endif /* yang-spec? */ + if (cvv== NULL) + goto done; + xml2csv(stdout, xc, cvv); /* csv syntax */ + } + retval = 0; + done: + if (xt) + xml_free(xt); + unchunk_group(__FUNCTION__); + return retval; +} + +int +show_conf_as_csv(clicon_handle h, cvec *cvv, cg_var *arg) +{ + return show_conf_as_csv1(h, cvv, arg); +} diff --git a/apps/cli/cli_common.h b/apps/cli/cli_common.h new file mode 100644 index 000000000..f047b1c25 --- /dev/null +++ b/apps/cli/cli_common.h @@ -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 + . + + * + */ + +#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_ */ diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c new file mode 100644 index 000000000..245b95639 --- /dev/null +++ b/apps/cli/cli_generate.c @@ -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 + . + + * + * 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 +#include +#include +#include +#include +#include +#include + + +/* cligen */ +#include + +/* clicon */ +#include + +#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 (),cli_set("ntp.logging $status:bool"); + } + server("Configure NTP Server") (("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr"); + } +#endif +#if 0 /* examples/datamodel */ + +WITH COMPLETION: + a (|),cli_set("a[] $!x");{ + b,cli_set("a[].b $!x");{ + y (|),cli_set("a[].b $!x $y"); + } + 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 . + * One complication is yang union, that needs a recursion since it consists of sub-types. + * eg type union{ type int32; type 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; iys_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: [ ]* */ + 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; iys_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; iys_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; iys_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; iyp_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; +} diff --git a/apps/cli/cli_generate.h b/apps/cli/cli_generate.h new file mode 100644 index 000000000..64665fe75 --- /dev/null +++ b/apps/cli/cli_generate.h @@ -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 + . + + */ + +#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_ */ diff --git a/apps/cli/cli_handle.c b/apps/cli/cli_handle.c new file mode 100644 index 000000000..f89a3b446 --- /dev/null +++ b/apps/cli/cli_handle.c @@ -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 + . + + * + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#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); +} diff --git a/apps/cli/cli_handle.h b/apps/cli/cli_handle.h new file mode 100644 index 000000000..be485acb5 --- /dev/null +++ b/apps/cli/cli_handle.h @@ -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 + . + + * + */ + +#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_ */ diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c new file mode 100644 index 000000000..241385d4f --- /dev/null +++ b/apps/cli/cli_main.c @@ -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 + . + + * + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#define __USE_GNU /* strverscmp */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#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 \tDebug\n" + "\t-f \tConfig-file (mandatory)\n" + "\t-F \tRead commands from file (default stdin)\n" + "\t-1\t\tDo not enter interactive mode\n" + "\t-u \tconfig UNIX domain path (default: %s)\n" + "\t-d \tSpecify plugin directory (default: %s)\n" + "\t-m \tSpecify plugin syntax mode\n" + "\t-c \t\tWrite to candidate db directly, not via config backend\n" + "\t-P \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 \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; +} diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c new file mode 100644 index 000000000..0a57b69fb --- /dev/null +++ b/apps/cli/cli_plugin.c @@ -0,0 +1,1153 @@ +/* + * + 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 + . + + * + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +/* clicon_cli */ +#include "clicon_cli_api.h" +#include "cli_plugin.h" +#include "cli_handle.h" + + +/* + * Name of plugin functions + * More in clicon_plugin.h + */ +#define PLUGIN_PROMPT_HOOK "plugin_prompt_hook" +#define PLUGIN_PARSE_HOOK "plugin_parse_hook" +#define PLUGIN_SUSP_HOOK "plugin_susp_hook" + +/* + * + * CLI PLUGIN INTERFACE, INTERNAL SECTION + * + */ + +/* + * Find syntax mode named 'mode'. Create if specified + */ +static cli_syntaxmode_t * +syntax_mode_find(cli_syntax_t *stx, const char *mode, int create) +{ + cli_syntaxmode_t *m; + + m = stx->stx_modes; + if (m) { + do { + if (strcmp(m->csm_name, mode) == 0) + return m; + m = NEXTQ(cli_syntaxmode_t *, m); + } while (m && m != stx->stx_modes); + } + + if (create == 0) + return NULL; + + if ((m = chunk(sizeof(cli_syntaxmode_t), stx->stx_cnklbl)) == NULL) { + perror("chunk"); + return NULL; + } + memset (m, 0, sizeof (*m)); + strncpy(m->csm_name, mode, sizeof(m->csm_name)-1); + strncpy(m->csm_prompt, CLI_DEFAULT_PROMPT, sizeof(m->csm_prompt)-1); + INSQ(m, stx->stx_modes); + stx->stx_nmodes++; + + return m; +} + +/* + * Find plugin by name + */ +static struct cli_plugin * +plugin_find_cli(cli_syntax_t *stx, char *plgnam) +{ + struct cli_plugin *p; + + if ((p = stx->stx_plugins) != NULL) + do { + if (strcmp (p->cp_name, plgnam) == 0) + return p; + p = NEXTQ(struct cli_plugin *, p); + } while (p && p != stx->stx_plugins); + + return NULL; +} + +/* + * Generate parse tree for syntax mode + */ +static int +gen_parse_tree(clicon_handle h, cli_syntaxmode_t *m) +{ + cli_tree_add(h, m->csm_name, m->csm_pt); + return 0; +} + + +/* + * Append syntax + */ +static int +syntax_append(clicon_handle h, + cli_syntax_t *stx, + const char *name, + parse_tree pt) +{ + cli_syntaxmode_t *m; + + if ((m = syntax_mode_find(stx, name, 1)) == NULL) + return -1; + + if (cligen_parsetree_merge(&m->csm_pt, NULL, pt) < 0) + return -1; + + return 0; +} + +/* + * Unload a plugin + */ +static int +plugin_unload(clicon_handle h, void *handle) +{ + int retval = 0; + char *error; + plgexit_t *exitfun; + + /* Call exit function is it exists */ + exitfun = dlsym(handle, PLUGIN_EXIT); + if (dlerror() == NULL) + exitfun(h); + + dlerror(); /* Clear any existing error */ + if (dlclose(handle) != 0) { + error = (char*)dlerror(); + cli_output (stderr, "dlclose: %s\n", error ? error : "Unknown error"); + /* Just report */ + } + + return retval; +} + +/* + * Unload all plugins in a group + */ +static int +syntax_unload(clicon_handle h) +{ + struct cli_plugin *p; + cli_syntax_t *stx = cli_syntax(h); + + if (stx == NULL) + return 0; + + while (stx->stx_nplugins > 0) { + p = stx->stx_plugins; + plugin_unload(h, p->cp_handle); + clicon_debug(1, "DEBUG: Plugin '%s' unloaded.", p->cp_name); + DELQ(stx->stx_plugins, stx->stx_plugins, struct cli_plugin *); + stx->stx_nplugins--; + } + while (stx->stx_nmodes > 0) { + DELQ(stx->stx_modes, stx->stx_modes, cli_syntaxmode_t *); + stx->stx_nmodes--; + } + + unchunk_group(stx->stx_cnklbl); + return 0; +} + + +/*! Dynamic string to function mapper + * + * The cli load function uses this function to map from strings to names. + * handle is the dlopen handle, so it only looks in the current plugin being + * loaded. It should also look in libraries? + * + * Returns a function pointer to the callback. Beware that this pointer + * can theoretically be NULL depending on where the callback is loaded + * into memory. Caller must check the error string which is non-NULL is + * an error occured + * + * Compare with expand_str2fn - essentially identical. + */ +cg_fnstype_t * +load_str2fn(char *name, void *handle, char **error) +{ + cg_fnstype_t *fn = NULL; + + /* Reset error */ + *error = NULL; + + /* First check given plugin if any */ + if (handle) { + dlerror(); /* Clear any existing error */ + fn = dlsym(handle, name); + if ((*error = (char*)dlerror()) == NULL) + return fn; /* If no error we found the address of the callback */ + } + + /* Now check global namespace which includes any shared object loaded + * into the global namespace. I.e. all lib*.so as well as the + * master plugin if it exists + */ + dlerror(); /* Clear any existing error */ + fn = dlsym(NULL, name); + if ((*error = (char*)dlerror()) == NULL) + return fn; /* If no error we found the address of the callback */ + + /* Return value not really relevant here as the error string is set to + * signal an error. However, just checking the function pointer for NULL + * should work in most cases, although it's not 100% correct. + */ + return NULL; +} + +/* + * expand_str2fn + * maps strings from the CLI specification file to real funtions using dlopen + * mapping. One could do something more elaborate with namespaces and plugins: + * x::a, x->a, but this is not done yet. + * Compare with load_str2fn - essentially identical. + * @param[in] name Name of function + * @param[in] handle Handle to plugin .so module as returned by dlopen, see cli_plugin_load + */ +expand_cb * +expand_str2fn(char *name, void *handle, char **error) +{ + expand_cb *fn = NULL; + + /* Reset error */ + *error = NULL; + + /* First check given plugin if any */ + if (handle) { + dlerror(); /* Clear any existing error */ + fn = dlsym(handle, name); + if ((*error = (char*)dlerror()) == NULL) + return fn; /* If no error we found the address of the callback */ + } + + /* Now check global namespace which includes any shared object loaded + * into the global namespace. I.e. all lib*.so as well as the + * master plugin if it exists + */ + dlerror(); /* Clear any existing error */ + fn = dlsym(NULL, name); + if ((*error = (char*)dlerror()) == NULL) + return fn; /* If no error we found the address of the callback */ + + /* Return value not really relevant here as the error string is set to + * signal an error. However, just checking the function pointer for NULL + * should work in most cases, although it's not 100% correct. + */ + return NULL; +} + + +/* + * Load a dynamic plugin object and call it's init-function + * Note 'file' may be destructively modified + */ +static plghndl_t +cli_plugin_load (clicon_handle h, char *file, int dlflags, const char *cnklbl) +{ + char *error; + char *name; + void *handle = NULL; + plginit_t *initfun; + struct cli_plugin *cp = NULL; + + dlerror(); /* Clear any existing error */ + if ((handle = dlopen (file, dlflags)) == NULL) { + error = (char*)dlerror(); + cli_output (stderr, "dlopen: %s\n", error ? error : "Unknown error"); + goto quit; + } + /* call plugin_init() if defined */ + if ((initfun = dlsym(handle, PLUGIN_INIT)) != NULL) { + if (initfun(h) != 0) { + cli_output (stderr, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file); + goto quit; + } + } + + if ((cp = chunk(sizeof (struct cli_plugin), cnklbl)) == NULL) { + perror("chunk"); + goto quit; + } + memset (cp, 0, sizeof(*cp)); + + name = basename(file); + snprintf(cp->cp_name, sizeof(cp->cp_name), "%.*s", (int)strlen(name)-3, name); + cp->cp_handle = handle; + +quit: + if (cp == NULL) { + if (handle) + dlclose(handle); + } + return cp; +} + +/* + * Append to syntax mode from file + * Arguments: + * filename : Name of file where syntax is specified (in syntax-group dir) + */ +static int +cli_load_syntax(clicon_handle h, const char *filename, const char *clispec_dir) +{ + void *handle = NULL; /* Handle to plugin .so module */ + char *mode = NULL; /* Name of syntax mode to append new syntax */ + parse_tree pt = {0,}; + int retval = -1; + FILE *f; + char *filepath; + cvec *vr = NULL; + char *prompt = NULL; + char **vec = NULL; + int i, nvec; + char *plgnam; + struct cli_plugin *p; + + if ((filepath = chunk_sprintf(__FUNCTION__, "%s/%s", + clispec_dir, + filename)) == NULL){ + clicon_err(OE_PLUGIN, errno, "chunk"); + goto done; + } + if ((vr = cvec_new(0)) == NULL){ + clicon_err(OE_PLUGIN, errno, "cvec_new"); + goto done; + } + /* Build parse tree from syntax spec. */ + if ((f = fopen(filepath, "r")) == NULL){ + clicon_err(OE_PLUGIN, errno, "fopen %s", filepath); + goto done; + } + + /* Assuming this plugin is first in queue */ + if (cli_parse_file(h, f, filepath, &pt, vr) < 0){ + clicon_err(OE_PLUGIN, 0, "failed to parse cli file %s", filepath); + fclose(f); + goto done; + } + fclose(f); + + /* Get CLICON specific global variables */ + prompt = cvec_find_str(vr, "CLICON_PROMPT"); + plgnam = cvec_find_str(vr, "CLICON_PLUGIN"); + mode = cvec_find_str(vr, "CLICON_MODE"); + + if (plgnam != NULL) { /* Find plugin for callback resolving */ + if ((p = plugin_find_cli (cli_syntax(h), plgnam)) != NULL) + handle = p->cp_handle; + if (handle == NULL){ + clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s\n", + plgnam, filename, plgnam, + clicon_cli_dir(h)); + goto done; + } + } + + /* Resolve callback names to function pointers */ + if (cligen_callback_str2fn(pt, load_str2fn, handle) < 0){ + clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)", + filename, plgnam, plgnam); + goto done; + } + if (cligen_expand_str2fn(pt, expand_str2fn, handle) < 0) + goto done; + + + /* Make sure we have a syntax mode specified */ + if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */ + clicon_err(OE_PLUGIN, 0, "No syntax mode specified in %s", filepath); + goto done; + } + if ((vec = clicon_strsplit(mode, ":", &nvec, __FUNCTION__)) == NULL) { + goto done; + } + for (i = 0; i < nvec; i++) { + if (syntax_append(h, cli_syntax(h), vec[i], pt) < 0) { + goto done; + } + if (prompt) + cli_set_prompt(h, vec[i], prompt); + } + + cligen_parsetree_free(pt, 1); + retval = 0; + +done: + if (vr) + cvec_free(vr); + unchunk_group(__FUNCTION__); + return retval; +} + +/* + * Load plugins within a directory + */ +static int +cli_plugin_load_dir(clicon_handle h, char *dir, cli_syntax_t *stx) +{ + int i; + int ndp; + struct dirent *dp; + char *file; + char *master_plugin; + char *master; + struct cli_plugin *cp; + struct stat st; + int retval = -1; + + + /* Format master plugin path */ + if ((master_plugin = clicon_master_plugin(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "clicon_master_plugin option not set"); + goto quit; + } + if ((master = chunk_sprintf(__FUNCTION__, "%s.so", master_plugin)) == NULL){ + clicon_err(OE_PLUGIN, errno, "chunk_sprintf master plugin"); + goto quit; + } + /* Get plugin objects names from plugin directory */ + ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG, __FUNCTION__); + if (ndp < 0) + goto quit; + + /* Load master plugin first */ + file = chunk_sprintf(__FUNCTION__, "%s/%s", dir, master); + if (file == NULL) { + clicon_err(OE_UNIX, errno, "chunk_sprintf dir"); + goto quit; + } + if (stat(file, &st) == 0) { + clicon_debug(1, "DEBUG: Loading master plugin '%s'", master); + cp = cli_plugin_load(h, file, RTLD_NOW|RTLD_GLOBAL, stx->stx_cnklbl); + if (cp == NULL) + goto quit; + /* Look up certain call-backs in master plugin */ + stx->stx_prompt_hook = + dlsym(cp->cp_handle, PLUGIN_PROMPT_HOOK); + stx->stx_parse_hook = + dlsym(cp->cp_handle, PLUGIN_PARSE_HOOK); + stx->stx_susp_hook = + dlsym(cp->cp_handle, PLUGIN_SUSP_HOOK); + INSQ(cp, stx->stx_plugins); + stx->stx_nplugins++; + } + unchunk (file); + + /* Load the rest */ + for (i = 0; i < ndp; i++) { + if (strcmp (dp[i].d_name, master) == 0) + continue; /* Skip master now */ + file = chunk_sprintf(__FUNCTION__, "%s/%s", dir, dp[i].d_name); + if (file == NULL) { + clicon_err(OE_UNIX, errno, "chunk_sprintf dir"); + goto quit; + } + clicon_debug(1, "DEBUG: Loading plugin '%s'", dp[i].d_name); + + if ((cp = cli_plugin_load (h, file, RTLD_NOW, stx->stx_cnklbl)) == NULL) + goto quit; + INSQ(cp, stx->stx_plugins); + stx->stx_nplugins++; + unchunk (file); + } + if (dp) + unchunk(dp); + + retval = 0; + + quit: + unchunk_group(__FUNCTION__); + + return retval; +} + + +/* + * Load a syntax group. + */ +int +cli_syntax_load (clicon_handle h) +{ + int retval = -1; + char *plugin_dir = NULL; + char *clispec_dir = NULL; + int ndp; + int i; + char *cnklbl = "__CLICON_CLI_SYNTAX_CNK_LABEL__"; + struct dirent *dp; + cli_syntax_t *stx; + cli_syntaxmode_t *m; + + /* Syntax already loaded. XXX should we re-load?? */ + if ((stx = cli_syntax(h)) != NULL) + return 0; + + /* Format plugin directory path */ + if ((plugin_dir = clicon_cli_dir(h)) == NULL){ + clicon_err(OE_FATAL, 0, "clicon_cli_dir not set"); + goto quit; + } + if ((clispec_dir = clicon_clispec_dir(h)) == NULL){ + clicon_err(OE_FATAL, 0, "clicon_clispec_dir not set"); + goto quit; + } + + /* Allocate plugin group object */ + if ((stx = chunk(sizeof(*stx), cnklbl)) == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + goto quit; + } + memset (stx, 0, sizeof (*stx)); /* Zero out all */ + /* populate name and chunk label */ + strncpy (stx->stx_cnklbl, cnklbl, sizeof(stx->stx_cnklbl)-1); + + cli_syntax_set(h, stx); + + /* First load CLICON system plugins. CLICON_CLI_SYSDIR is defined + in Makefile*/ + if (cli_plugin_load_dir(h, CLICON_CLI_SYSDIR, stx) < 0) + goto quit; + + /* Then load application plugins */ + if (cli_plugin_load_dir(h, plugin_dir, stx) < 0) + goto quit; + + /* load syntaxfiles */ + if ((ndp = clicon_file_dirent(clispec_dir, &dp, "(.cli)$", S_IFREG, __FUNCTION__)) < 0) + goto quit; + /* Load the rest */ + for (i = 0; i < ndp; i++) { + clicon_debug(1, "DEBUG: Loading syntax '%.*s'", + (int)strlen(dp[i].d_name)-4, dp[i].d_name); + if (cli_load_syntax(h, dp[i].d_name, clispec_dir) < 0) + goto quit; + } + if (dp) + unchunk(dp); + + + /* Did we successfully load any syntax modes? */ + if (stx->stx_nmodes <= 0) { + retval = 0; + goto quit; + } + /* Parse syntax tree for all modes */ + m = stx->stx_modes; + do { + if (gen_parse_tree(h, m) != 0) + goto quit; + m = NEXTQ(cli_syntaxmode_t *, m); + } while (m && m != stx->stx_modes); + + + /* Set callbacks into CLIgen */ + cli_susp_hook(h, cli_syntax(h)->stx_susp_hook); + + /* All good. We can now proudly return a new group */ + retval = 0; + +quit: + if (retval != 0) { + syntax_unload(h); + unchunk_group(cnklbl); + cli_syntax_set(h, NULL); + } + unchunk_group(__FUNCTION__); + return retval; +} + +/* + * Call plugin_start() in all plugins + */ +int +cli_plugin_start(clicon_handle h, int argc, char **argv) +{ + struct cli_plugin *p; + cli_syntax_t *stx; + plgstart_t *startfun; +// XXX int (*startfun)(clicon_handle, int, char **); + + stx = cli_syntax(h); + + if ((p = stx->stx_plugins) != NULL) + do { + startfun = dlsym(p->cp_handle, PLUGIN_START); + if (dlerror() == NULL) + startfun(h, argc, argv); + p = NEXTQ(struct cli_plugin *, p); + } while (p && p != stx->stx_plugins); + + return 0; +} + +/* + + */ +int +cli_plugin_finish(clicon_handle h) +{ + syntax_unload(h); + cli_syntax_set(h, NULL); + return 0; +} + +/*! Help function to print a meaningful error string. + * Sometimes the libraries specify an error string, if so print that. + * Otherwise just print 'command error'. + */ +int +cli_handler_err(FILE *f) +{ + if (clicon_errno){ + cli_output(f, "%s: %s", + clicon_strerror(clicon_errno), + clicon_err_reason); + if (clicon_suberrno) + cli_output(f, ": %s", strerror(clicon_suberrno)); + cli_output(f, "\n"); + + } + else + cli_output(f, "CLI command error\n"); + return 0; +} + + +/* + * Evaluate a matched command + */ +int +clicon_eval(clicon_handle h, char *cmd, cg_obj *match_obj, cvec *vr) +{ + cli_output_reset(); +#ifdef notyet + if (isrecording()) + record_command(cmd); +#endif + if (!cli_exiting(h)) { + clicon_err_reset(); + if (cligen_eval(cli_cligen(h), match_obj, vr) < 0) { +#if 0 /* This is removed since we get two error messages on failure. + But maybe only sometime? + Both a real log when clicon_err is called, and the here again. + (Before clicon_err was silent) */ + cli_handler_err(stdout); +#endif + } + } + return 0; +} + + +/* + * clicon_parse + * Given a command string, parse and evaluate the string according to + * the syntax parse tree of the syntax mode specified by *mode. + * If there is no match in the tree for the command, the parse hook + * will be called to see if another mode should be evaluated. If a + * match is found in another mode, the mode variable is updated to point at + * the new mode string. + * + * INPUT: + * cmd The command string + * match_obj Pointer to CLIgen match object + * mode A pointer to the mode string pointer + * OUTPUT: + * kr Keyword vector + * vr Variable vector + * RETURNS: + * -2 : on eof (shouldnt happen) + * -1 : In parse error + * >=0 : Number of matches + */ +int +clicon_parse(clicon_handle h, char *cmd, char **mode, int *result) +{ + char *m, *msav; + int res = -1; + int r; + cli_syntax_t *stx; + cli_syntaxmode_t *smode; + char *treename; + parse_tree *pt; /* Orig */ + cg_obj *match_obj; + cvec *vr = NULL; + + stx = cli_syntax(h); + m = *mode; + if (m == NULL) { + smode = stx->stx_active_mode; + m = smode->csm_name; + } + else { + if ((smode = syntax_mode_find(stx, m, 0)) == NULL) { + cli_output(stderr, "Can't find syntax mode '%s'\n", m); + return -1; + } + } + msav = NULL; + while(smode) { + if (cli_tree_active(h)) + msav = strdup(cli_tree_active(h)); + cli_tree_active_set(h, m); + treename = cli_tree_active(h); + if ((pt = cli_tree(h, treename)) == NULL){ + fprintf(stderr, "No such parse-tree registered: %s\n", treename); + goto done;; + } + if ((vr = cvec_new(0)) == NULL){ + fprintf(stderr, "%s: cvec_new: %s\n", __FUNCTION__, strerror(errno)); + goto done;; + } + res = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, vr); + if (res != CG_MATCH) + pt_expand_cleanup_1(pt); + if (msav){ + cli_tree_active_set(h, msav); + free(msav); + } + msav = NULL; + switch (res) { + case CG_EOF: /* eof */ + case CG_ERROR: + cli_output(stderr, "CLI parse error: %s\n", cmd); + goto done; + case CG_NOMATCH: /* no match */ + smode = NULL; + if (stx->stx_parse_hook) { + /* Try to find a match in upper modes, a'la IOS. */ + if ((m = stx->stx_parse_hook(h, cmd, m)) != NULL) { + if ((smode = syntax_mode_find(stx, m, 0)) != NULL) + continue; + else + cli_output(stderr, "Can't find syntax mode '%s'\n", m); + } + } + cli_output(stderr, "CLI syntax error: \"%s\": %s\n", + cmd, cli_nomatch(h)); + break; + case CG_MATCH: + if (m != *mode){ /* Command in different mode */ + *mode = m; + cli_set_syntax_mode(h, m); + } + if ((r = clicon_eval(h, cmd, match_obj, vr)) < 0) + cli_handler_err(stdout); + pt_expand_cleanup_1(pt); + if (result) + *result = r; + goto done; + break; + default: + cli_output(stderr, "CLI syntax error: \"%s\" is ambiguous\n", cmd); + goto done; + break; + } + } +done: + if (vr) + cvec_free(vr); + return res; +} + +/* + * Read command from CLIgen's cliread() using current syntax mode. + */ +char * +clicon_cliread(clicon_handle h) +{ + char *ret; + char *pfmt = NULL; + cli_syntaxmode_t *mode; + cli_syntax_t *stx; + + stx = cli_syntax(h); + mode = stx->stx_active_mode; + + if (stx->stx_prompt_hook) + pfmt = stx->stx_prompt_hook(h, mode->csm_name); + if (clicon_quiet_mode(h)) + cli_prompt_set(h, ""); + else + cli_prompt_set(h, cli_prompt(pfmt ? pfmt : mode->csm_prompt)); + cli_tree_active_set(h, mode->csm_name); + ret = cliread(cli_cligen(h)); + if (pfmt) + free(pfmt); + return ret; +} + +/* + * cli_find_plugin + * Find a plugin by name and return the dlsym handl + * Used by libclicon code to find callback funcctions in plugins. + */ +static void * +cli_find_plugin(clicon_handle h, char *plugin) +{ + struct cli_plugin *p; + + p = plugin_find_cli(cli_syntax(h), plugin); + if (p) + return p->cp_handle; + + return NULL; +} + + +/*! Initialize plugin code (not the plugins themselves) + */ +int +cli_plugin_init(clicon_handle h) +{ + find_plugin_t *fp = cli_find_plugin; + clicon_hash_t *data = clicon_data(h); + + /* Register CLICON_FIND_PLUGIN in data hash */ + if (hash_add(data, "CLICON_FIND_PLUGIN", &fp, sizeof(fp)) == NULL) { + clicon_err(OE_UNIX, errno, "failed to register CLICON_FIND_PLUGIN"); + return -1; + } + + return 0; +} + + +/* + * + * CLI PLUGIN INTERFACE, PUBLIC SECTION + * + */ + + +/* + * Set syntax mode mode for existing current plugin group. + */ +int +cli_set_syntax_mode(clicon_handle h, const char *name) +{ + cli_syntaxmode_t *mode; + + if ((mode = syntax_mode_find(cli_syntax(h), name, 1)) == NULL) + return 0; + + cli_syntax(h)->stx_active_mode = mode; + return 1; +} + +/* + * Get syntax mode name + */ +char * +cli_syntax_mode(clicon_handle h) +{ + cli_syntaxmode_t *csm; + + if ((csm = cli_syntax(h)->stx_active_mode) == NULL) + return NULL; + return csm->csm_name; +} + + +/* + * Callback from cli_set_prompt(). Set prompt format for syntax mode + * Arguments: + * name : Name of syntax mode + * prompt : Prompt format + */ +int +cli_set_prompt(clicon_handle h, const char *name, const char *prompt) +{ + cli_syntaxmode_t *m; + + if ((m = syntax_mode_find(cli_syntax(h), name, 1)) == NULL) + return -1; + + strncpy(m->csm_prompt, prompt, sizeof(m->csm_prompt)-1); + return 0; +} + +/* + * Format prompt + * XXX: HOST_NAME_MAX from sysconf() + */ +static int +prompt_fmt (char *prompt, size_t plen, char *fmt, ...) +{ + va_list ap; + char *s = fmt; + char hname[1024]; + char tty[32]; + char *new; + char *tmp; + int ret = -1; + + /* Start with empty string */ + if((new = chunk_sprintf(__FUNCTION__, "%s", ""))==NULL) + goto done; + + while(*s) { + if (*s == '%' && *++s) { + switch(*s) { + + case 'H': /* Hostname */ + if (gethostname (hname, sizeof (hname)) != 0) + strncpy(hname, "unknown", sizeof(hname)-1); + if((new = chunk_strncat(new, hname, 0, __FUNCTION__))==NULL) + goto done; + break; + + case 'U': /* Username */ + tmp = getenv("USER"); + if((new = chunk_strncat(new, (tmp ? tmp : "nobody"), 0, __FUNCTION__))==NULL) + goto done; + break; + + case 'T': /* TTY */ + if(ttyname_r(fileno(stdin), tty, sizeof(tty)-1) < 0) + strcpy(tty, "notty"); + if((new = chunk_strncat(new, tty, strlen(tty), __FUNCTION__))==NULL) + goto done; + break; + + default: + if((new = chunk_strncat(new, "%", 1, __FUNCTION__))==NULL || + (new = chunk_strncat(new, s, 1, __FUNCTION__))) + goto done; + } + } + else { + if ((new = chunk_strncat(new, s, 1, __FUNCTION__))==NULL) + goto done; + } + s++; + } + +done: + if (new) + fmt = new; + va_start(ap, fmt); + ret = vsnprintf(prompt, plen, fmt, ap); + va_end(ap); + + unchunk_group(__FUNCTION__); + + return ret; +} + +/* + * Return a formatted prompt string + */ +char * +cli_prompt(char *fmt) +{ + static char prompt[CLI_PROMPT_LEN]; + + if (prompt_fmt(prompt, sizeof(prompt), fmt) < 0) + return CLI_DEFAULT_PROMPT; + + return prompt; +} + + +/* + * Run command in CLI engine + */ +int +cli_exec(clicon_handle h, char *cmd, char **mode, int *result) +{ + return clicon_parse(h, cmd, mode, result); +} + + +/* + * push_one + * nifty code that 'pushes' a syntax one ore more levels + * op: eg "set" + * cmd: eg "edit policy-options" + */ +int +cli_ptpush(clicon_handle h, char *mode, char *string, char *op) +{ + cg_obj *co, *co_cmd, *cc; + parse_tree *pt; + char **vec = NULL; + int i, j, nvec; + int found; + parse_tree pt_top; + cli_syntaxmode_t *m; + + if ((m = syntax_mode_find(cli_syntax(h), mode, 0)) == NULL) + return 0; + pt_top = m->csm_pt; + if ((co_cmd = co_find_one(pt_top, op)) == NULL) + return 0; + pt = &co_cmd->co_pt; + /* vec is the command, eg 'edit policy_option' */ + if ((vec = clicon_strsplit(string, " ", &nvec, __FUNCTION__)) == NULL) + goto catch; + co = NULL; + found = 0; + for (i=0; ipt_len; j++){ + co = pt->pt_vec[j]; + if (co && co->co_type == CO_COMMAND && + (strcmp(co->co_command, vec[i])==0)){ + pt = &co->co_pt; + found++; + break; + } + } + if (!found) + break;//not found on this level + } + if (found){ // match all levels + if (!co_cmd->co_pushed){ + co_cmd->co_pt_push = co_cmd->co_pt; + co_cmd->co_pushed++; + } + co_cmd->co_pt = co->co_pt; + pt = &co_cmd->co_pt; + for (i=0; ipt_len; i++) /* set correct parent */ + if ((cc = pt->pt_vec[i]) != NULL) + co_up_set(cc, co_cmd); + } + catch: + unchunk_group(__FUNCTION__) ; + return 0; +} + +int +cli_ptpop(clicon_handle h, char *mode, char *op) +{ + cg_obj *co_cmd, *cc; + int i; + parse_tree *pt; + parse_tree pt_top; + cli_syntaxmode_t *m; + + if ((m = syntax_mode_find(cli_syntax(h), mode, 0)) == NULL) + return 0; + pt_top = m->csm_pt; + if ((co_cmd = co_find_one(pt_top, op)) == NULL) //set + return 0; + if (!co_cmd->co_pushed) + return 0; + co_cmd->co_pushed = 0; + co_cmd->co_pt = co_cmd->co_pt_push; + pt = &co_cmd->co_pt; + for (i=0; ipt_len; i++) /* set correct parent */ + if ((cc = pt->pt_vec[i]) != NULL) + co_up_set(cc, co_cmd); + return 0; +} + + +/* + * clicon_valcb + * Callback from clicon_dbvars_parse() + * Find a cli plugin based on name if given and + * use dlsym to resolve a function pointer in it. + * Call the resolved function to get the cgv populated + */ +int +clicon_valcb(void *arg, cvec *vars, cg_var *cgv, char *fname, cg_var *funcarg) +{ + char *func; + char *plgnam = NULL; + void *handle; + struct cli_plugin *p; + cli_valcb_t *cb; + clicon_handle h = (clicon_handle)arg; + + /* Make copy */ + if ((fname = strdup(fname)) == NULL) { + clicon_err(OE_UNIX, errno, "strdup"); + return -1; + } + + /* Extract plugin name if any */ + if ((func = strstr(fname, "::")) != NULL) { + *func = '\0'; + func += 2; + plgnam = fname; + } + else + func = fname; + + /* If we have specified a plugin name, find the handle to be used + * with dlsym() + */ + handle = NULL; + if (plgnam && (p = plugin_find_cli(cli_syntax(h), plgnam))) + handle = p->cp_handle; + + /* Look up function pointer */ + if ((cb = dlsym(handle, func)) == NULL) { + clicon_err(OE_UNIX, errno, "unable to find %s()", func); + free(fname); + return -1; + } + free(fname); + + if (cb(vars, cgv, funcarg) < 0) + return -1; + + return 0; +} + diff --git a/apps/cli/cli_plugin.h b/apps/cli/cli_plugin.h new file mode 100644 index 000000000..9517bfcab --- /dev/null +++ b/apps/cli/cli_plugin.h @@ -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 + . + + */ + +#ifndef _CLI_PLUGIN_H_ +#define _CLI_PLUGIN_H_ + +#include +#include +#include + +/* 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_ */ diff --git a/apps/cli/clicon_cli.h b/apps/cli/clicon_cli.h new file mode 100644 index 000000000..39e10ec87 --- /dev/null +++ b/apps/cli/clicon_cli.h @@ -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 + . + + */ + +#ifndef _CLICON_CLI_H_ +#define _CLICON_CLI_H_ + +#include + +#/* Common code (API and clicon_cli) */ +include + +/*! 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_ */ diff --git a/apps/cli/clicon_cli_api.h b/apps/cli/clicon_cli_api.h new file mode 100644 index 000000000..d76004156 --- /dev/null +++ b/apps/cli/clicon_cli_api.h @@ -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 + . + + * 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_ */ diff --git a/apps/dbctrl/Makefile.in b/apps/dbctrl/Makefile.in new file mode 100644 index 000000000..25d264a51 --- /dev/null +++ b/apps/dbctrl/Makefile.in @@ -0,0 +1,99 @@ +# +# 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 +# . +# + +VPATH = @srcdir@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +sysconfdir = @sysconfdir@ + +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) + +# For dependency +LIBDEPS = $(top_srcdir)/lib/src/$(CLICON_LIB) + +LIBS = -L$(top_srcdir)/lib/src @LIBS@ -l:$(CLICON_LIB) + +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@ + +SRC = + +OBJS = $(SRC:.c=.o) + +APPSRC = dbctrl_main.c +APPOBJ = $(APPSRC:.c=.o) +APPL = clicon_dbctrl + +all: $(APPL) + +clean: + rm -f $(OBJS) *.core $(APPL) $(APPOBJ) + +distclean: clean + rm -f Makefile *~ .depend + +# Put demon in bin +# Put other executables in libexec/ +# Also create a libexec/ directory for writeable/temporary files. +# Put config file in etc/ +install: $(APPL) + install -d $(DESTDIR)$(bindir) + install $(APPL) $(DESTDIR)$(bindir) + +install-include: + +uninstall: + rm -f $(bindir)/$(APPL) + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(INCLUDES) -D__PROGRAM__=\"$(APPL)\" $(CPPFLAGS) $(CFLAGS) -c $< + +$(APPL) : $(APPOBJ) $(OBJS) $(LIBDEPS) + $(CC) $(LDFLAGS) $(APPOBJ) $(OBJS) $(LIBS) -o $@ + +TAGS: + find . -name '*.[chyl]' -print | etags - + +depend: + $(CC) $(DEPENDFLAGS) @DEFS@ $(INCLUDES) $(CFLAGS) -MM $(SRC) $(APPSRC) > .depend + +#include .depend + diff --git a/apps/dbctrl/dbctrl_main.c b/apps/dbctrl/dbctrl_main.c new file mode 100644 index 000000000..a88a322f3 --- /dev/null +++ b/apps/dbctrl/dbctrl_main.c @@ -0,0 +1,241 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +/* Command line options to be passed to getopt(3) */ +#define DBCTRL_OPTS "hDd:pbn:r:m:Zi" + +/*! Write database contents to file, xml database variant + * @param[in] dbspec If set make a sanity check if key dont match (just) + */ +static int +dump_database(FILE *f, + char *dbname, + char *rxkey) +{ + int retval = 0; + int npairs; + struct db_pair *pairs; + + /* Default is match all */ + if (rxkey == NULL) + rxkey = "^.*$"; + + /* Get all keys/values for vector */ + if ((npairs = db_regexp(dbname, rxkey, __FUNCTION__, &pairs, 0)) < 0) + return -1; + + for (npairs--; npairs >= 0; npairs--) + fprintf(f, "%s %s\n", pairs[npairs].dp_key, + pairs[npairs].dp_val?pairs[npairs].dp_val:""); + unchunk_group(__FUNCTION__); + return retval; +} + + +/* + * remove_entry + */ +static int +remove_entry(char *dbname, char *key) +{ + return db_del(dbname, key); +} + +/* + * usage + */ +static void +usage(char *argv0) +{ + fprintf(stderr, "usage:%s\n" + "where options are\n" + "\t-h\t\tHelp\n" + "\t-D\t\tDebug\n" + "\t-d \tDatabase name (default: running_db)\n" + "\t-p\t\tDump database on stdout\n" + "\t-b\t\tBrief output, just print keys. Combine with -p or -m\n" + "\t-n \" \" Add database entry\n" + "\t-r \tRemove database entry\n" + "\t-m \tMatch regexp key in database\n" + "\t-Z\t\tDelete database\n" + "\t-i\t\tInit database\n", + argv0 + ); + exit(0); +} + +int +main(int argc, char **argv) +{ + char c; + int zapdb; + int initdb; + int dumpdb; + int addent; + int rment; + char *matchkey = NULL; + char *addstr; + char rmkey[MAXPATHLEN]; + int brief; + char dbname[MAXPATHLEN] = {0,}; + int use_syslog; + yang_spec *yspec; + clicon_handle h; + + /* In the startup, logs to stderr & debug flag set later */ + clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR); + + /* Defaults */ + zapdb = 0; + initdb = 0; + dumpdb = 0; + addent = 0; + rment = 0; + brief = 0; + use_syslog = 0; + addstr = NULL; + memset(rmkey, '\0', sizeof(rmkey)); + + if ((h = clicon_handle_init()) == NULL) + goto done; + /* getopt in two steps, first find config-file before over-riding options. */ + while ((c = getopt(argc, argv, DBCTRL_OPTS)) != -1) + switch (c) { + case '?' : + case 'h' : /* help */ + usage(argv[0]); + break; + case 'D' : /* debug */ + debug = 1; + break; + case 'S': /* Log on syslog */ + use_syslog = 1; + break; + } + /* + * Logs, error and debug to stderr or syslog, set debug level + */ + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, + use_syslog?CLICON_LOG_SYSLOG:CLICON_LOG_STDERR); + clicon_debug_init(debug, NULL); + + /* Now rest of options */ + optind = 1; + while ((c = getopt(argc, argv, DBCTRL_OPTS)) != -1) + switch (c) { + case 'Z': /* Zap database */ + zapdb++; + break; + case 'i': /* Init database */ + initdb++; + break; + case 'p': /* Dump/print database */ + dumpdb++; + break; + case 'b': /* Dump/print/match database brief (combone w -p or -m) */ + brief++; + break; + case 'd': /* dbname */ + if (!optarg || sscanf(optarg, "%s", dbname) != 1) + usage(argv[0]); + break; + case 'n': /* add database entry */ + if (!optarg || !strlen(optarg) || (addstr = strdup(optarg)) == NULL) + usage(argv[0]); + /* XXX addign both key and value, for now only key */ + addent++; + break; + case 'r': + if (!optarg || sscanf(optarg, "%s", rmkey) != 1) + usage(argv[0]); + rment++; + break; + case 'm': + if (!optarg || !strlen(optarg) || (matchkey = strdup(optarg)) == NULL) + usage(argv[0]); + dumpdb++; + break; + case 'D': /* Processed earlier, ignore now. */ + case 'S': + break; + default: + usage(argv[0]); + break; + } + argc -= optind; + argv += optind; + + if (*dbname == '\0'){ + clicon_err(OE_FATAL, 0, "database not specified (with -d ): %s"); + goto done; + } + yspec = clicon_dbspec_yang(h); + if (dumpdb){ + if (dump_database(stdout, dbname, matchkey)) { + fprintf(stderr, "Match error\n"); + goto done; + } + } + if (addent) /* add entry */ + if (xmldb_put_xkey(dbname, addstr, NULL, yspec, OP_REPLACE) < 0) + goto done; + if (rment) + if (remove_entry(dbname, rmkey) < 0) + goto done; + if (zapdb) /* remove databases */ + unlink(dbname); + if (initdb) + if (db_init(dbname) < 0) + goto done; + + done: + return 0; +} diff --git a/apps/netconf/Makefile.in b/apps/netconf/Makefile.in new file mode 100644 index 000000000..dfa1f189e --- /dev/null +++ b/apps/netconf/Makefile.in @@ -0,0 +1,122 @@ +# +# 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 +# . +# +# +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) + +# For dependency +LIBDEPS = $(top_srcdir)/lib/src/$(CLICON_LIB) + +LIBS = -L$(top_srcdir)/lib/src @LIBS@ -l:$(CLICON_LIB) +CPPFLAGS = @CPPFLAGS@ -fPIC +INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@ + +APPL = clicon_netconf +SRC = netconf_main.c +OBJS = $(SRC:.c=.o) + +MYNAME = clicon_netconf +MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX) +MYLIB = $(MYLIBLINK).$(CLICON_MAJOR).$(CLICON_MINOR) +MYLIBSO = $(MYLIBLINK).$(CLICON_MAJOR) + +LIBSRC = netconf_hello.c netconf_rpc.c netconf_filter.c netconf_lib.c netconf_plugin.c +LIBOBJS = $(LIBSRC:.c=.o) + +all: $(MYLIB) $(APPL) + +clean: + rm -f $(OBJS) $(LIBOBJS) *.core $(APPL) $(MYLIB) $(MYLIBSO) $(MYLIBLINK) + +distclean: clean + rm -f Makefile *~ .depend + +# Put demon 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_netconf.so.2 + ln -sf $(MYLIBSO) $(DESTDIR)$(libdir)/$(MYLIBLINK) # -l:libclicon_netconf.so + +install-include: clicon_netconf.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)\" $(CFLAGS) -c $< + +$(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 + diff --git a/apps/netconf/clicon_netconf.h b/apps/netconf/clicon_netconf.h new file mode 100644 index 000000000..d24d34551 --- /dev/null +++ b/apps/netconf/clicon_netconf.h @@ -0,0 +1,73 @@ +/* + * + 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 + . + + * + * The exported interface to plugins. External apps (eg frontend netconf plugins) + * should only include this file (not the netconf_*.h) + */ + +#ifndef _CLICON_NETCONF_H_ +#define _CLICON_NETCONF_H_ + +/* + * Types + */ +typedef int (*netconf_cb_t)( + clicon_handle h, + cxobj *xorig, /* Original request. */ + cxobj *xn, /* Sub-tree (under xorig) at child: */ + cbuf *cb, /* Output xml stream. For reply */ + cbuf *cb_err, /* Error xml stream. For error reply */ + void *arg /* Argument given at netconf_register_callback() */ + ); + +/* + * Prototypes + * (Duplicated. Also in netconf_*.h) + */ +int netconf_output(int s, cbuf *xf, char *msg); + +int netconf_create_rpc_reply(cbuf *cb, /* msg buffer */ + cxobj *xr, /* orig request */ + char *body, + int ok); + +int netconf_register_callback(clicon_handle h, + netconf_cb_t cb, /* Callback called */ + void *arg, /* Arg to send to callback */ + char *tag); /* Xml tag when callback is made */ +int netconf_create_rpc_error(cbuf *xf, /* msg buffer */ + cxobj *xr, /* orig request */ + char *tag, + char *type, + char *severity, + char *message, + char *info); + +void netconf_ok_set(int ok); +int netconf_ok_get(void); + +int netconf_xpath(cxobj *xsearch, + cxobj *xfilter, + cbuf *xf, cbuf *xf_err, + cxobj *xt); + + +#endif /* _CLICON_NETCONF_H_ */ diff --git a/apps/netconf/netconf_filter.c b/apps/netconf/netconf_filter.c new file mode 100644 index 000000000..5f129e046 --- /dev/null +++ b/apps/netconf/netconf_filter.c @@ -0,0 +1,633 @@ +/* + * + 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 + . + + * + * netconf match & selection: get and edit operations + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "netconf_rpc.h" +#include "netconf_lib.h" +#include "netconf_filter.h" + +/* + * xml_filter + * xf specifices a filter, and xn is an xml tree. + * Select the part of xn that matches xf and return it. + * Change xn destructively by removing the parts of the sub-tree that does + * not match. + * Match according to Section 6 of RFC 4741. + NO_FILTER, select all + EMPTY_FILTER, select nothing + ATTRIBUTE_MATCH, select if attribute match + SELECTION, select this node + CONTENT_MATCH, select all siblings with matching content + CONTAINMENT select + */ + +/* return a string containing leafs value, NULL if no leaf or no value */ +static char* +leafstring(cxobj *x) +{ + cxobj *c; + + if (xml_type(x) != CX_ELMNT) + return NULL; + if (xml_child_nr(x) != 1) + return NULL; + c = xml_child_i(x, 0); + if (xml_child_nr(c) != 0) + return NULL; + if (xml_type(c) != CX_BODY) + return NULL; + return xml_value(c); +} + +/*! Internal recursive part where configuration xml tree is pruned frim filter + * assume parent has been selected and filter match (same name) as parent + * parent is pruned according to selection. + * @param[in] xfilter Filter xml + * @param[out] xconf Configuration xml + * @retval 0 OK + * @retval -1 Error + */ +static int +xml_filter2(cxobj *xfilter, + cxobj *xparent, + int *remove_me) +{ + cxobj *s; + cxobj *sprev; + cxobj *f; + cxobj *attr; + char *an; + char *af; + char *fstr; + char *sstr; + int containments; + int remove_s; + + *remove_me = 0; + assert(xfilter && xparent && strcmp(xml_name(xfilter), xml_name(xparent))==0); + /* 1. Check selection */ + if (xml_child_nr(xfilter) == 0) + goto match; + + /* Count containment/selection nodes in filter */ + f = NULL; + containments = 0; + while ((f = xml_child_each(xfilter, f, CX_ELMNT)) != NULL) { + if (leafstring(f)) + continue; + containments++; + } + + /* 2. Check attribute match */ + attr = NULL; + while ((attr = xml_child_each(xfilter, attr, CX_ATTR)) != NULL) { + af = xml_value(attr); + an = xml_find_value(xfilter, xml_name(attr)); + if (af && an && strcmp(af, an)==0) + ; // match + else + goto nomatch; + } + /* 3. Check content match */ + f = NULL; + while ((f = xml_child_each(xfilter, f, CX_ELMNT)) != NULL) { + if ((fstr = leafstring(f)) == NULL) + continue; + if ((s = xml_find(xparent, xml_name(f))) == NULL) + goto nomatch; + if ((sstr = leafstring(s)) == NULL) + continue; + if (strcmp(fstr, sstr)) + goto nomatch; + } + /* If filter has no further specifiers, accept */ + if (!containments) + goto match; + /* Check recursively the rest of the siblings */ + sprev = s = NULL; + while ((s = xml_child_each(xparent, s, CX_ELMNT)) != NULL) { + if ((f = xml_find(xfilter, xml_name(s))) == NULL){ + xml_prune(xparent, s, 1); + s = sprev; + continue; + } + if (leafstring(f)){ + sprev = s; + continue; // unsure?sk=lf + } + // XXX: s can be removed itself in the recursive call ! + remove_s = 0; + if (xml_filter2(f, s, &remove_s) < 0) + return -1; + if (remove_s){ + xml_prune(xparent, s, 1); + s = sprev; + } + sprev = s; + } + + match: + return 0; + nomatch: /* prune this parent node (maybe only children?) */ + *remove_me = 1; + return 0; +} + +/*! Remove parts of configuration xml tree that does not match filter xml tree + * @param[in] xfilter Filter xml + * @param[out] xconf Configuration xml + * @retval 0 OK + * @retval -1 Error + * This is the top-level function, calls a recursive variant. + */ +int +xml_filter(cxobj *xfilter, + cxobj *xconfig) +{ + int retval; + int remove_s; + + /* Call recursive variant */ + retval = xml_filter2(xfilter, + xconfig, + &remove_s); + return retval; +} + +/* + * netconf_xpath + * @param[in] xsearch where you search for xpath, grouped by a single top node which + * is not significant and will not be returned in any result. + * @param[in] xfilter the xml sub-tree, eg: + * + * @param[out] cb Output xml stream. For reply + * @param[out] cb_err Error xml stream. For error reply + * @param[in] xorig Original tree + * + */ +int +netconf_xpath(cxobj *xsearch, + cxobj *xfilter, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + cxobj *x; + int retval = -1; + char *selector; + cxobj **xv; + int xlen; + int i; + + if ((selector = xml_find_value(xfilter, "select")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "select"); + goto done; + } + + x = NULL; + + clicon_errno = 0; + if ((xv = xpath_vec(xsearch, selector, &xlen)) != NULL) { + for (i=0; ioperation"); + return -1; + } + } + return 0; +} + +/* forward */ +static int +xml_edit(cxobj *filter, + cxobj *parent, + enum operation_type op, + cbuf *xf_err, + cxobj *xorig); + + +/*! Merge two XML trees according to RFC4741/Junos + * 1. in configuration(parent) but not in new(filter) -> remain in configuration + * 2. not in configuration but in new -> add to configuration + * 3. Both in configuration and new: Do 1.2.3 with children. + * A key is: the configuration data identified by the element + */ +static int +edit_selection(cxobj *filter, + cxobj *parent, + enum operation_type op, + cbuf *xf_err, + cxobj *xorig) +{ + int retval = -1; + + assert(filter && parent && strcmp(xml_name(filter), xml_name(parent))==0); + fprintf(stderr, "%s: %s\n", __FUNCTION__, xml_name(filter)); + switch (op){ + case OP_MERGE: + break; + case OP_REPLACE: + xml_prune(xml_parent(parent), parent, 1); + break; + case OP_CREATE: + netconf_create_rpc_error(xf_err, xorig, + NULL, + "protocol", + "error", + "statement creation failed", + ""); + goto done; + break; + case OP_DELETE: + fprintf(stderr, "%s: %s DELETE\n", __FUNCTION__, xml_name(filter)); + if (xml_child_nr(parent) == 0){ + fprintf(stderr, "%s: %s ERROR\n", __FUNCTION__, xml_name(filter)); + netconf_create_rpc_error(xf_err, xorig, + NULL, + "protocol", + "error", + "statement not found", + ""); + goto done; + } + /* fall through */ + case OP_REMOVE: + fprintf(stderr, "%s: %s REMOVE\n", __FUNCTION__, xml_name(filter)); + xml_prune(xml_parent(parent), parent, 1); + break; + case OP_NONE: + break; + } + retval = 0; + netconf_ok_set(1); /* maybe cc_ok shouldnt be set if we continue? */ + done: + return retval; +} + +/* + * XXX: not called from external? + */ +static int +edit_match(cxobj *filter, + cxobj *parent, + enum operation_type op, + cbuf *xf_err, + cxobj *xorig, + int match + ) +{ + cxobj *f; + cxobj *s; + cxobj *copy; + int retval = -1; + + clicon_debug(1, "%s: %s op:%d", __FUNCTION__, xml_name(filter), op); + if (match) + switch (op){ + case OP_REPLACE: + case OP_CREATE: + s = NULL; + while ((s = xml_child_each(parent, s, -1)) != NULL){ + xml_prune(parent, s, 1); + s = NULL; + } + if (xml_copy(filter, parent) < 0) + goto done; + netconf_clean(parent); + retval = 0; + netconf_ok_set(1); + goto done; + break; + case OP_DELETE: + case OP_REMOVE: + xml_prune(xml_parent(parent), parent, 1); + netconf_ok_set(1); + goto done; + break; + case OP_MERGE: + case OP_NONE: + break; + } + + f = NULL; + while ((f = xml_child_each(filter, f, CX_ELMNT)) != NULL) { + s = xml_find(parent, xml_name(f)); + switch (op){ + case OP_MERGE: + /* things in filter: + not in conf should be added + in conf go down recursive + */ + if (s == NULL && match){ + if ((copy = xml_new(xml_name(f), parent)) == NULL) + goto done; + if (xml_copy(f, copy) < 0) + goto done; + netconf_clean(copy); + } + else{ + s = NULL; + while ((s = xml_child_each(parent, s, CX_ELMNT)) != NULL) { + if (strcmp(xml_name(f), xml_name(s))) + continue; + if ((retval = xml_edit(f, s, op, xf_err, xorig)) < 0) + goto done; + } + } + break; + case OP_REPLACE: +#if 1 + /* things in filter + in conf: remove from conf and + add to conf + */ +// if (!match) +// break; + if (s != NULL) + xml_prune(parent, s, 1); + if ((copy = xml_new(xml_name(f), parent)) == NULL) + goto done; + if (xml_copy(f, copy) < 0) + goto done; + netconf_clean(copy); +#endif + break; + case OP_CREATE: +#if 0 + /* things in filter + in conf: error + else add to conf + */ + if (!match) + break; + if (s != NULL){ + netconf_create_rpc_error(xf_err, xorig, + NULL, + "protocol", + "error", + "statement creation failed", + ""); + goto done; + } + if ((copy = xml_new(xml_name(f), parent)) == NULL) + goto done; + if (xml_copy(f, copy) < 0) + goto done; + netconf_clean(copy); +#endif + break; + case OP_DELETE: + /* things in filter + if not in conf: error + else remove from conf + */ +#if 0 + if (!match) + break; + if (s == NULL){ + netconf_create_rpc_error(xf_err, xorig, + NULL, + "protocol", + "error", + "statement not found", + ""); + goto done; + } +#endif + /* fall through */ + case OP_REMOVE: + /* things in filter + remove from conf + */ +#if 0 + if (!match) + break; + xml_prune(parent, s, 1); +#endif + break; + case OP_NONE: + /* recursive descent */ + s = NULL; + while ((s = xml_child_each(parent, s, CX_ELMNT)) != NULL) { + if (strcmp(xml_name(f), xml_name(s))) + continue; + if ((retval = xml_edit(f, s, op, xf_err, xorig)) < 0) + goto done; + } + break; + } + } /* while f */ + retval = 0; + netconf_ok_set(1); /* maybe cc_ok shouldnt be set if we continue? */ + done: + return retval; + +} + +/* + * xml_edit + * merge filter into parent + * XXX: not called from external? + */ +static int +xml_edit(cxobj *filter, + cxobj *parent, + enum operation_type op, + cbuf *xf_err, + cxobj *xorig) +{ + cxobj *attr; + cxobj *f; + cxobj *s; + int retval = -1; + char *an, *af; + char *fstr, *sstr; + int keymatch = 0; + + get_operation(filter, &op, xf_err, xorig); + /* 1. First try selection: filter is empty */ + if (xml_child_nr(filter) == 0){ /* no elements? */ + retval = edit_selection(filter, parent, op, xf_err, xorig); + goto done; + } + if (xml_child_nr(filter) == 1 && /* same as above */ + xpath_first(filter, "/[@operation]")){ + retval = edit_selection(filter, parent, op, xf_err, xorig); + goto done; + } + /* 2. Check attribute match */ + attr = NULL; + while ((attr = xml_child_each(filter, attr, CX_ATTR)) != NULL) { + af = xml_value(attr); + an = xml_find_value(filter, xml_name(attr)); + if (af && an && strcmp(af, an)==0) + ; // match + else + goto nomatch; + } + /* 3. Check content match */ + /* + * For content-match we do a somewhat strange thing, we find + * a match in first content-node and assume that is unique + * and then we remove/replace that + * For merge we just continue + */ + f = NULL; + while ((f = xml_child_each(filter, f, CX_ELMNT)) != NULL) { + if ((fstr = leafstring(f)) == NULL) + continue; + /* we found a filter leaf-match: no return we say it should match*/ + if ((s = xml_find(parent, xml_name(f))) == NULL) + goto nomatch; + if ((sstr = leafstring(s)) == NULL) + goto nomatch; + if (strcmp(fstr, sstr)) + goto nomatch; + keymatch++; + break; /* match */ + } + + if (debug && keymatch){ + fprintf(stderr, "%s: match\n", __FUNCTION__); + fprintf(stderr, "%s: filter:\n", __FUNCTION__); + clicon_xml2file(stdout, filter, 0, 1); + fprintf(stderr, "%s: config:\n", __FUNCTION__); + clicon_xml2file(stdout, parent, 0, 1); + } + + retval = edit_match(filter, parent, op, xf_err, xorig, keymatch); + /* match */ + netconf_ok_set(1); + retval = 0; + done: + return retval; + nomatch: + return 0; +} +#endif /* NOTUSED */ diff --git a/apps/netconf/netconf_filter.h b/apps/netconf/netconf_filter.h new file mode 100644 index 000000000..8cc8f0d5e --- /dev/null +++ b/apps/netconf/netconf_filter.h @@ -0,0 +1,36 @@ +/* + * + 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 + . + + * + * netconf match & selection: get and edit operations + *****************************************************************************/ +#ifndef _NETCONF_FILTER_H_ +#define _NETCONF_FILTER_H_ + +/* + * Prototypes + */ +int xml_filter(cxobj *xf, cxobj *xn); +int netconf_xpath(cxobj *xsearch, + cxobj *xfilter, + cbuf *xf, cbuf *xf_err, + cxobj *xt); + +#endif /* _NETCONF_FILTER_H_ */ diff --git a/apps/netconf/netconf_hello.c b/apps/netconf/netconf_hello.c new file mode 100644 index 000000000..f6a0275e4 --- /dev/null +++ b/apps/netconf/netconf_hello.c @@ -0,0 +1,118 @@ +/* + * + 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 + . + + * + * Code for handling netconf hello messages + *****************************************************************************/ +/* + Capabilities are advertised in messages sent by each peer during + session establishment. When the NETCONF session is opened, each peer + (both client and server) MUST send a element containing a + list of that peer's capabilities. Each peer MUST send at least the + base NETCONF capability, "urn:ietf:params:netconf:base:1.0". + + + URI + + + + */ + + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "netconf_lib.h" +#include "netconf_hello.h" + +static int +netconf_hello(cxobj *xn) +{ + cxobj *x; + + x = NULL; + while ((x = xpath_each(xn, "//capability", x)) != NULL) { + //fprintf(stderr, "cap: %s\n", xml_body(x)); + } + return 0; +} + +int +netconf_hello_dispatch(cxobj *xn) +{ + cxobj *xp; + int retval = -1; + + if ((xp = xpath_first(xn, "//hello")) != NULL) + retval = netconf_hello(xp); + return retval; +} + +/* + * netconf_create_hello + * create capability string (once) + */ +int +netconf_create_hello(cbuf *xf, /* msg buffer */ + int session_id) +{ + int retval = 0; + + add_preamble(xf); + cprintf(xf, ""); + cprintf(xf, ""); + cprintf(xf, "urn:ietf:params:xml:ns:netconf:base:1.0\n"); + cprintf(xf, "urn:ietf:params:xml:ns:netconf:capability:candidate:1:0\n"); + cprintf(xf, "urn:ietf:params:xml:ns:netconf:capability:validate:1.0\n"); + cprintf(xf, "urn:ietf:params:netconf:capability:xpath:1.0\n"); + cprintf(xf, "urn:ietf:params:netconf:capability:notification:1.0\n"); + + +// cprintf(xf, "urn:rnr:rnrapi:1:0"); + cprintf(xf, ""); + cprintf(xf, "%lu", 42+session_id); + cprintf(xf, ""); + add_postamble(xf); + return retval; +} diff --git a/apps/netconf/netconf_hello.h b/apps/netconf/netconf_hello.h new file mode 100644 index 000000000..e26296f09 --- /dev/null +++ b/apps/netconf/netconf_hello.h @@ -0,0 +1,34 @@ +/* + * + 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 + . + + * + * Code for handling netconf hello messages + *****************************************************************************/ +#ifndef _NETCONF_HELLO_H_ +#define _NETCONF_HELLO_H_ + +/* + * Prototypes + */ +int netconf_create_hello(cbuf *xf, int session_id); + +int netconf_hello_dispatch(cxobj *xn); + +#endif /* _NETCONF_HELLO_H_ */ diff --git a/apps/netconf/netconf_lib.c b/apps/netconf/netconf_lib.c new file mode 100644 index 000000000..0059c3162 --- /dev/null +++ b/apps/netconf/netconf_lib.c @@ -0,0 +1,261 @@ +/* + * + 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 + . + + * + * netconf lib + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "netconf_rpc.h" +#include "netconf_lib.h" + +/* + * Exported variables + */ +enum transport_type transport = NETCONF_SSH; +int cc_closed = 0; + +static int cc_ok = 0; + +void +netconf_ok_set(int ok) +{ + cc_ok = ok; +} + +int +netconf_ok_get(void) +{ + return cc_ok; +} + +int +add_preamble(cbuf *xf) +{ + if (transport == NETCONF_SOAP) + cprintf(xf, "\n\n" + ""); + return 0; +} + +/* + * add_postamble + * add netconf xml postamble of message. That is, xml after the body of the message. + * for soap this is the envelope stuff, for ssh this is ]]>]]> + */ +int +add_postamble(cbuf *xf) +{ + switch (transport){ + case NETCONF_SSH: + cprintf(xf, "]]>]]>"); /* Add RFC4742 end-of-message marker */ + break; + case NETCONF_SOAP: + cprintf(xf, "\n" ""); + break; + } + return 0; +} + +/* + * add_error_preamble + * compared to regular messages (see add_preamble), error message differ in some + * protocols (eg soap) by adding a longer and deeper header. + */ +int +add_error_preamble(cbuf *xf, char *reason) +{ + switch (transport){ + case NETCONF_SOAP: + cprintf(xf, "" + "" + "" + "" + "env:Receiver" + "" + "" + "%s" + "" + "", reason); + break; + default: + if (add_preamble(xf) < 0) + return -1; + break; + } + return 0; +} + +/* + * add_error_postamble + * compared to regular messages (see add_postamble), error message differ in some + * protocols (eg soap) by adding a longer and deeper header. + */ +int +add_error_postamble(cbuf *xf) +{ + switch (transport){ + case NETCONF_SOAP: + cprintf(xf, "" ""); + default: /* fall through */ + if (add_postamble(xf) < 0) + return -1; + break; + } + return 0; +} + +/*! Look for a text pattern in an input string, one char at a time + * @param[in] tag What to look for + * @param[in] ch New input character + * @param[in,out] state A state integer holding how far we have parsed. + * @retval 0 No, we havent detected end tag + * @retval 1 Yes, we have detected end tag! + * XXX: move to clicon_xml? + */ +int +detect_endtag(char *tag, char ch, int *state) +{ + int retval = 0; + + if (tag[*state] == ch){ + (*state)++; + if (*state == strlen(tag)){ + *state = 0; + retval = 1; + } + } + else + *state = 0; + return retval; +} + +/* + * target_locked + * return 1 if locked, 0 if not. + * return clientid if locked. + */ +int +target_locked(enum target_type target, int *client) +{ + return 0; +} + +/* + * unlock_target + */ +int +unlock_target(enum target_type target) +{ + return 0; +} + +int +lock_target(enum target_type target) +{ + return 0; +} + +/*! Get "target" attribute, return actual database given candidate or running + * Caller must do error handling + * @retval dbname Actual database file name + */ +char * +netconf_get_target(clicon_handle h, cxobj *xn, char *path) +{ + cxobj *x; + char *target = NULL; + char *running_db; + char *candidate_db; + + if ((running_db = clicon_running_db(h)) == NULL) + goto done; + if ((candidate_db = clicon_candidate_db(h)) == NULL) + goto done; + if ((x = xpath_first(xn, path)) != NULL){ + if (xpath_first(x, "candidate") != NULL) + target = candidate_db; + else + if (xpath_first(x, "running") != NULL) + target = running_db; + } + done: + return target; + +} + +/*! Send netconf message from cbuf on socket + * @param[in] s + * @param[in] cb Cligen buffer that contains the XML message + * @param[in] msg Only for debug + */ +int +netconf_output(int s, cbuf *xf, char *msg) +{ + char *buf = cbuf_get(xf); + int len = cbuf_len(xf); + int retval = -1; + + clicon_debug(1, "SEND %s", msg); + if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */ + cxobj *xt = NULL; + if (clicon_xml_parse_string(&buf, &xt) == 0){ + clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0); + fprintf(stderr, "\n"); + xml_free(xt); + } + } + if (write(s, buf, len) < 0){ + if (errno == EPIPE) + ; + else + clicon_log(LOG_ERR, "%s: write: %s", __FUNCTION__, strerror(errno)); + goto done; + } + retval = 0; + done: + return retval; +} diff --git a/apps/netconf/netconf_lib.h b/apps/netconf/netconf_lib.h new file mode 100644 index 000000000..61640d4c7 --- /dev/null +++ b/apps/netconf/netconf_lib.h @@ -0,0 +1,75 @@ +/* + * + 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 + . + + * + * Netconf lib + *****************************************************************************/ +#ifndef _NETCONF_LIB_H_ +#define _NETCONF_LIB_H_ + +/* + * Types + */ +enum target_type{ /* netconf */ + RUNNING, + CANDIDATE +}; +enum transport_type{ + NETCONF_SSH, /* RFC 4742 */ + NETCONF_SOAP, /* RFC 4743 */ +}; + +enum test_option{ /* edit-config */ + SET, + TEST_THEN_SET, + TEST_ONLY +}; + +enum error_option{ /* edit-config */ + STOP_ON_ERROR, + CONTINUE_ON_ERROR +}; + +enum filter_option{ /* get-config/filter */ + FILTER_SUBTREE, + FILTER_XPATH +}; + +/* + * Variables + */ +extern enum transport_type transport; +extern int cc_closed; + +/* + * Prototypes + */ +void netconf_ok_set(int ok); +int netconf_ok_get(void); + +int add_preamble(cbuf *xf); +int add_postamble(cbuf *xf); +int add_error_preamble(cbuf *xf, char *reason); +int detect_endtag(char *tag, char ch, int *state); +char *netconf_get_target(clicon_handle h, cxobj *xn, char *path); +int add_error_postamble(cbuf *xf); +int netconf_output(int s, cbuf *xf, char *msg); + +#endif /* _NETCONF_LIB_H_ */ diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c new file mode 100644 index 000000000..9b08eb9ad --- /dev/null +++ b/apps/netconf/netconf_main.c @@ -0,0 +1,425 @@ +/* + * + 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 + . + + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_netconf.h" +#include "netconf_lib.h" +#include "netconf_hello.h" +#include "netconf_plugin.h" +#include "netconf_rpc.h" + +/* Command line options to be passed to getopt(3) */ +#define NETCONF_OPTS "hDqf:d:S" + +/*! Process incoming packet + * @param[in] h Clicon handle + * @param[in] xf Packet buffer + */ +static int +process_incoming_packet(clicon_handle h, + cbuf *xf) +{ + char *str; + char *str0; + cxobj *xml_req = NULL; /* Request (in) */ + int isrpc = 0; /* either hello or rpc */ + cbuf *xf_out; + cbuf *xf_err; + cbuf *xf1; + + clicon_debug(1, "RECV"); + clicon_debug(2, "%s: RCV: \"%s\"", __FUNCTION__, cbuf_get(xf)); + if ((str0 = strdup(cbuf_get(xf))) == NULL){ + clicon_log(LOG_ERR, "%s: strdup: %s", __FUNCTION__, strerror(errno)); + return -1; + } + str = str0; + /* Parse incoming XML message */ + if (clicon_xml_parse_string(&str, &xml_req) < 0){ + if ((xf = cbuf_new()) == NULL){ + netconf_create_rpc_error(xf, NULL, + "operation-failed", + "rpc", "error", + NULL, + NULL); + + netconf_output(1, xf, "rpc-error"); + cbuf_free(xf); + } + else + clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__); + free(str0); + goto done; + } + free(str0); + if (xpath_first(xml_req, "//rpc") != NULL){ + isrpc++; + } + else + if (xpath_first(xml_req, "//hello") != NULL) + ; + else{ + clicon_log(LOG_WARNING, "Invalid netconf msg: neither rpc or hello: dropp\ +ed"); + goto done; + } + /* Initialize response buffers */ + if ((xf_out = cbuf_new()) == NULL){ + clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__); + goto done; + } + + /* Create error buf */ + if ((xf_err = cbuf_new()) == NULL){ + clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__); + goto done; + } + netconf_ok_set(0); + if (isrpc){ + if (netconf_rpc_dispatch(h, + xml_req, + xpath_first(xml_req, "//rpc"), + xf_out, xf_err) < 0){ + assert(cbuf_len(xf_err)); + clicon_debug(1, "%s", cbuf_get(xf_err)); + if (isrpc){ + if (netconf_output(1, xf_err, "rpc-error") < 0) + goto done; + } + } + else{ + if ((xf1 = cbuf_new()) != NULL){ + if (netconf_create_rpc_reply(xf1, xml_req, cbuf_get(xf_out), netconf_ok_get()) < 0){ + cbuf_free(xf_out); + cbuf_free(xf_err); + cbuf_free(xf1); + goto done; + } + if (netconf_output(1, xf1, "rpc-reply") < 0){ + cbuf_reset(xf1); + netconf_create_rpc_error(xf1, xml_req, "operation-failed", + "protocol", "error", + NULL, cbuf_get(xf_err)); + netconf_output(1, xf1, "rpc-error"); + cbuf_free(xf_out); + cbuf_free(xf_err); + cbuf_free(xf1); + goto done; + } + cbuf_free(xf1); + } + } + } + else{ + netconf_hello_dispatch(xml_req); /* XXX: return-value */ + } + cbuf_free(xf_out); + cbuf_free(xf_err); + done: + if (xml_req) + xml_free(xml_req); + return 0; +} + +/*! Get netconf message: detect end-of-msg + * @param[in] s Socket where input arrived. read from this. + * @param[in] arg Clicon handle. + */ +static int +netconf_input_cb(int s, + void *arg) +{ + clicon_handle h = arg; + unsigned char buf[BUFSIZ]; + int i; + int len; + static cbuf *xf; /* XXX: should use ce state? */ + int xml_state = 0; + int retval = -1; + + if (xf == NULL) + if ((xf = cbuf_new()) == NULL){ + clicon_err(OE_XML, errno, "%s: cbuf_new", __FUNCTION__); + return retval; + } + memset(buf, 0, sizeof(buf)); + if ((len = read(s, buf, sizeof(buf))) < 0){ + if (errno == ECONNRESET) + len = 0; /* emulate EOF */ + else{ + clicon_log(LOG_ERR, "%s: read: %s", __FUNCTION__, strerror(errno)); + goto done; + } + } /* read */ + if (len == 0){ /* EOF */ + cc_closed++; + close(s); + retval = 0; + goto done; + } + + for (i=0; i]]>", + buf[i], + &xml_state)) { + /* OK, we have an xml string from a client */ + if (process_incoming_packet(h, xf) < 0){ + goto done; + } + if (cc_closed) + break; + cbuf_reset(xf); + } + } + retval = 0; + done: + // cbuf_free(xf); + if (cc_closed) + retval = -1; + return retval; +} + +/* + * send_hello + * args: s file descriptor to write on (eg 1 - stdout) + */ +static int +send_hello(int s) +{ + cbuf *xf; + int retval = -1; + + if ((xf = cbuf_new()) == NULL){ + clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__); + goto done; + } + if (netconf_create_hello(xf, getpid()) < 0) + goto done; + if (netconf_output(s, xf, "hello") < 0) + goto done; + retval = 0; + done: + if (xf) + cbuf_free(xf); + return retval; +} + +/* from init_candidate_db() and clicon_rpc_copy() */ +static int +init_candidate_db(clicon_handle h, char *running_db, char *candidate_db) +{ + struct stat sb; + int retval = -1; + + /* init shared candidate */ + if (lstat(candidate_db, &sb) < 0){ + if (clicon_rpc_copy(h, running_db, candidate_db) < 0) + goto done; + } + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +static int +terminate(clicon_handle h) +{ + yang_spec *yspec; + + if ((yspec = clicon_dbspec_yang(h)) != NULL) + yspec_free(yspec); + clicon_handle_exit(h); + return 0; +} + + +/* + * usage + */ +static void +usage(char *argv0, clicon_handle h) +{ + char *netconfdir = clicon_netconf_dir(h); + + fprintf(stderr, "usage:%s\n" + "where options are\n" + "\t-h\t\tHelp\n" + "\t-D\t\tDebug\n" + "\t-q\t\tQuiet: dont send hello prompt\n" + "\t-f \tConfiguration file (mandatory)\n" + "\t-d \tSpecify netconf plugin directory dir (default: %s)\n" + "\t-S\t\tLog on syslog\n", + argv0, + netconfdir + ); + exit(0); +} + +int +main(int argc, char **argv) +{ + char c; + char *tmp; + char *argv0 = argv[0]; + int quiet = 0; + clicon_handle h; + int use_syslog; + char *running_db; + char *candidate_db; + + /* Defaults */ + use_syslog = 0; + + /* In the startup, logs to stderr & debug flag set later */ + clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR); + /* Create handle */ + if ((h = clicon_handle_init()) == NULL) + return -1; + + while ((c = getopt(argc, argv, NETCONF_OPTS)) != -1) + switch (c) { + case 'h' : /* help */ + usage(argv[0], h); + break; + case 'D' : /* debug */ + debug = 1; + break; + case 'f': /* override config file */ + if (!strlen(optarg)) + usage(argv[0], h); + clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg); + break; + case 'S': /* Log on syslog */ + use_syslog = 1; + break; + } + + /* + * Logs, error and debug to stderr or syslog, set debug level + */ + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, + use_syslog?CLICON_LOG_SYSLOG:CLICON_LOG_STDERR); + clicon_debug_init(debug, NULL); + + /* Find and read configfile */ + if (clicon_options_main(h) < 0) + return -1; + + /* Now rest of options */ + optind = 1; + opterr = 0; + while ((c = getopt(argc, argv, NETCONF_OPTS)) != -1) + switch (c) { + case 'h' : /* help */ + case 'D' : /* debug */ + case 'f': /* config file */ + case 'S': /* Log on syslog */ + break; /* see above */ + case 'q': /* quiet: dont write hello */ + quiet++; + break; + case 'd': /* Plugin directory */ + if (!strlen(optarg)) + usage(argv[0], h); + clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg); + break; + default: + usage(argv[0], h); + break; + } + argc -= optind; + argv += optind; + + /* Parse db spec file */ + if (yang_spec_main(h, stdout, 0) < 0) + goto done; + + /* Initialize plugins group */ + if (netconf_plugin_load(h) < 0) + return -1; + + if ((running_db = clicon_running_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "running db not set"); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + clicon_err(OE_FATAL, 0, "candidate db not set"); + goto done; + } + if (init_candidate_db(h, running_db, candidate_db) < 0) + return -1; + /* Call start function is all plugins before we go interactive */ + tmp = *(argv-1); + *(argv-1) = argv0; + netconf_plugin_start(h, argc+1, argv-1); + *(argv-1) = tmp; + + if (!quiet) + send_hello(1); + if (event_reg_fd(0, netconf_input_cb, h, "netconf socket") < 0) + goto done; + if (debug) + clicon_option_dump(h, debug); + + if (event_loop() < 0) + goto done; + done: + + netconf_plugin_unload(h); + terminate(h); + clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */ + clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid()); + return 0; +} diff --git a/apps/netconf/netconf_plugin.c b/apps/netconf/netconf_plugin.c new file mode 100644 index 000000000..cd9770e3a --- /dev/null +++ b/apps/netconf/netconf_plugin.c @@ -0,0 +1,277 @@ +/* + * + 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 + . + + * + * handling netconf plugins + */ + +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +/* clicon netconf*/ +#include "clicon_netconf.h" +#include "netconf_lib.h" +#include "netconf_plugin.h" + +/* + * Unload a plugin + */ +static int +plugin_unload(clicon_handle h, void *handle) +{ + int retval = 0; + char *error; + plgexit_t *exitfn; + + /* Call exit function is it exists */ + exitfn = dlsym(handle, PLUGIN_EXIT); + if (dlerror() == NULL) + exitfn(h); + + dlerror(); /* Clear any existing error */ + if (dlclose(handle) != 0) { + error = (char*)dlerror(); + clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error"); + /* Just report */ + } + return retval; +} + + + +/* + * Load a dynamic plugin object and call it's init-function + * Note 'file' may be destructively modified + */ +static plghndl_t +plugin_load (clicon_handle h, char *file, int dlflags, const char *cnklbl) +{ + char *error; + void *handle = NULL; + plginit_t *initfn; + + dlerror(); /* Clear any existing error */ + if ((handle = dlopen (file, dlflags)) == NULL) { + error = (char*)dlerror(); + clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error"); + goto quit; + } + /* call plugin_init() if defined */ + if ((initfn = dlsym(handle, PLUGIN_INIT)) != NULL) { + if (initfn(h) != 0) { + clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file); + goto quit; + } + } +quit: + + return handle; +} + +static int nplugins = 0; +static plghndl_t *plugins = NULL; +static netconf_reg_t *deps = NULL; + +/* + * netconf_plugin_load + * Load allplugins you can find in CLICON_NETCONF_DIR + */ +int +netconf_plugin_load(clicon_handle h) +{ + int retval = -1; + char *dir; + int ndp; + struct dirent *dp; + int i; + char *filename; + plghndl_t *handle; + + if ((dir = clicon_netconf_dir(h)) == NULL){ + clicon_err(OE_PLUGIN, 0, "clicon_netconf_dir not defined"); + goto quit; + } + + /* Get plugin objects names from plugin directory */ + if((ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG, __FUNCTION__))<0) + goto quit; + + /* Load all plugins */ + for (i = 0; i < ndp; i++) { + filename = chunk_sprintf(__FUNCTION__, "%s/%s", dir, dp[i].d_name); + clicon_debug(1, "DEBUG: Loading plugin '%.*s' ...", + (int)strlen(filename), filename); + if (filename == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + goto quit; + } + if ((handle = plugin_load (h, filename, RTLD_NOW, __FUNCTION__)) == NULL) + goto quit; + if ((plugins = rechunk(plugins, (nplugins+1) * sizeof (*plugins), NULL)) == NULL) { + clicon_err(OE_UNIX, errno, "chunk"); + goto quit; + } + plugins[nplugins++] = handle; + unchunk (filename); + } + retval = 0; +quit: + unchunk_group(__FUNCTION__); + return retval; +} + +int +netconf_plugin_unload(clicon_handle h) +{ + int i; + netconf_reg_t *nr; + + while((nr = deps) != NULL) { + DELQ(nr, deps, netconf_reg_t *); + if (nr->nr_tag) + free(nr->nr_tag); + free(nr); + } + for (i = 0; i < nplugins; i++) + plugin_unload(h, plugins[i]); + if (plugins) + unchunk(plugins); + nplugins = 0; + return 0; +} + +/* + * Call plugin_start in all plugins + */ +int +netconf_plugin_start(clicon_handle h, int argc, char **argv) +{ + int i; + plgstart_t *startfn; + + for (i = 0; i < nplugins; i++) { + /* Call exit function is it exists */ + if ((startfn = dlsym(plugins[i], PLUGIN_START)) == NULL) + break; + optind = 0; + if (startfn(h, argc, argv) < 0) { + clicon_debug(1, "plugin_start() failed\n"); + return -1; + } + } + return 0; +} + + +/* + * netconf_register_callback + * Called from plugin to register a callback for a specific netconf XML tag. + */ +int +netconf_register_callback(clicon_handle h, + netconf_cb_t cb, /* Callback called */ + void *arg, /* Arg to send to callback */ + char *tag) /* Xml tag when callback is made */ +{ + netconf_reg_t *nr; + + if ((nr = malloc(sizeof(netconf_reg_t))) == NULL) { + clicon_err(OE_DB, errno, "malloc: %s", strerror(errno)); + goto catch; + } + memset (nr, 0, sizeof (*nr)); + nr->nr_callback = cb; + nr->nr_arg = arg; + nr->nr_tag = strdup(tag); /* strdup */ + INSQ(nr, deps); + return 0; +catch: + if (nr){ + if (nr->nr_tag) + free(nr->nr_tag); + free(nr); + } + return -1; +} + +/*! See if there is any callback registered for this tag + * + * @param xn Sub-tree (under xorig) at child of rpc: . + * @param xf Output xml stream. For reply + * @param xf_err Error xml stream. For error reply + * @param xorig Original request. + * + * @retval -1 Error + * @retval 0 OK, not found handler. + * @retval 1 OK, handler called + */ +int +netconf_plugin_callbacks(clicon_handle h, + cxobj *xn, + cbuf *xf, + cbuf *xf_err, + cxobj *xorig) +{ + netconf_reg_t *nr; + int retval; + + if (deps == NULL) + return 0; + nr = deps; + do { + if (strcmp(nr->nr_tag, xml_name(xn)) == 0){ + if ((retval = nr->nr_callback(h, + xorig, + xn, + xf, + xf_err, + nr->nr_arg)) < 0) + return -1; + else + return 1; /* handled */ + } + nr = NEXTQ(netconf_reg_t *, nr); + } while (nr != deps); + return 0; +} + diff --git a/apps/netconf/netconf_plugin.h b/apps/netconf/netconf_plugin.h new file mode 100644 index 000000000..272e7f143 --- /dev/null +++ b/apps/netconf/netconf_plugin.h @@ -0,0 +1,57 @@ +/* + * + 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 + . + + * + * handling netconf plugins + *****************************************************************************/ +#ifndef _NETCONF_PLUGIN_H_ +#define _NETCONF_PLUGIN_H_ + +/* + * Types + */ + +/* Database dependency description */ +struct netconf_reg { + qelem_t nr_qelem; /* List header */ + netconf_cb_t nr_callback; /* Validation/Commit Callback */ + void *nr_arg; /* Application specific argument to cb */ + char *nr_tag; /* Xml tag when matched, callback called */ +}; +typedef struct netconf_reg netconf_reg_t; + +/* + * Prototypes + */ +int netconf_plugin_load(clicon_handle h); + +int netconf_plugin_start(clicon_handle h, int argc, char **argv); + +int netconf_plugin_unload(clicon_handle h); + + +int netconf_plugin_callbacks(clicon_handle h, +// dbspec_key *dbspec, + cxobj *xn, + cbuf *xf, + cbuf *xf_err, + cxobj *xt); + +#endif /* _NETCONF_PLUGIN_H_ */ diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c new file mode 100644 index 000000000..b00be129f --- /dev/null +++ b/apps/netconf/netconf_rpc.c @@ -0,0 +1,1258 @@ +/* + * + 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 + . + + * + * Code for handling netconf rpc messages + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "clicon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include + +#include "clicon_netconf.h" +#include "netconf_lib.h" +#include "netconf_filter.h" +#include "netconf_plugin.h" +#include "netconf_rpc.h" + +/* + * + + + */ + +/* get-config help function + * xfilter is a filter expression starting with + * only supported + * needs refactoring: move the lower part (after xfilter) up to get-config or + * sub-function., focus on xfilter part here. + * @param[in] h Clicon handle + * @param[in] xfilter Parsed xpath expression + * @param[out] cb Output xml stream. For reply + * @param[out] cb_err Error xml stream. For error reply + * @param[in] xorig Original request as xml tree. + * @param[in] target Database name + * @see netconf_get_config + * Variants of the functions where x-axis is the variants of the clause + * and y-axis is whether a or is present. + * | no filter | filter subnet | filter xpath | + * -----------------+-----------+---------------+--------------+ + * no config | | | | + * -----------------+-----------+---------------+--------------+ + * config/select | - | | | + * -----------------+-----------+---------------+--------------+ + * Example requests of each: + * no filter + no config + ]]>]]> + * filter subnet + no config: + ]]>]]> + * filter xpath + no select: + ]]>]]> + * filter subnet + config: + ]]>]]> + * filter xpath + select: + ]]>]]> + */ + +/*! Variant for xmldb */ +static int +netconf_filter_xmldb(clicon_handle h, + cxobj *xfilter, + enum filter_option foption, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig, + char *source) +{ + cxobj *xdb = NULL; + cxobj *xc; + cxobj *xfilterconf = NULL; + int retval = -1; + yang_spec *ys = clicon_dbspec_yang(h); + char *selector; + + /* Default subtree filter */ + switch (foption){ + case FILTER_SUBTREE: + /* Get the whole database as xml */ + if (xmldb_get(source, NULL, ys, &xdb) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "read-registry"); + goto done; + } + + /* Add under as reply */ + if ((xc = xml_insert(xdb, "configuration")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "filtering"); + goto done; + } + if (xfilter) + xfilterconf = xpath_first(xfilter, "//configuration"); + /* xml_filter removes parts of xml tree not matching */ + if (xfilterconf != NULL){ + if (xml_filter(xfilterconf, xc) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "filtering"); + goto done; + } + } + if (xml_child_nr(xc)) + clicon_xml2cbuf(cb, xc, 0, 1); + break; + case FILTER_XPATH: + selector = xml_find_value(xfilter, "select"); + if (xmldb_get(source, selector, ys, &xdb) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "read-registry"); + goto done; + } + if ((xc = xml_insert(xdb, "configuration")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "filtering"); + goto done; + } + if (xml_child_nr(xc)) + clicon_xml2cbuf(cb, xc, 0, 1); + break; + default: + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + "filter type not supported", + "type"); + goto done; + } + retval = 0; + done: + if (xdb) + xml_free(xdb); + return retval; +} + + +/*! Get configuration + * @param[in] h Clicon handle + * @param[in] xorig Sub-tree (under xorig) at ... level. + * @param[out] cb Output xml stream. For reply + * @param[out] cb_err Error xml stream. For error reply + * @param[in] xorig Original request as xml tree. + * @note Only filter type="xpath" is supported + + + + <( candidate | running )/> + + + + + + <( candidate | running )/> + + + + + + + + Example: + + + ]]>]]> + * Call graph, client to backend and formats + * netconf_input_cb # client + * read + * process_incoming_packet # + * clicon_xml_parse_string # + * netconf_rpc_dispatch + * netconf_get_config # + * xpath_first + * netconf_filter # + * db2xml_key # "^.*$" + * clicon_dbitems # (db) + * db_regexp # (lvec) + * lvec2cvec # (cvec) + * cvec2xml # (xml) + * clicon_xml2cbuf # (xml->char*) + * wanted: + * netconf_get_config + * xpath(db, filter) + */ +int +netconf_get_config(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + cxobj *xfilter; /* filter */ + int retval = -1; + char *source; + enum filter_option foption = FILTER_SUBTREE; + char *ftype = NULL; + + if ((source = netconf_get_target(h, xn, "source")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "source"); + goto done; + } + /* ie ... */ + if ((xfilter = xpath_first(xn, "filter")) != NULL) { + if ((ftype = xml_find_value(xfilter, "type")) != NULL) + if (strcmp(ftype, "xpath")==0) + foption = FILTER_XPATH; + } + if (netconf_filter_xmldb(h, xfilter, foption, cb, cb_err, xorig, source) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Get options from netconf edit-config + * + * XXX + * (merge | none | replace) + * (stop-on-error | continue-on-error ) + * (set | test-then-set | test-only) + * + * + * + */ +static int +get_edit_opts(cxobj *xn, + enum operation_type *op, + enum test_option *testopt, + enum error_option *erropt, + cbuf *cb_err, + cxobj *xorig) +{ + int retval = -1; + cxobj *x; + char *optstr; + + if ((x = xpath_first(xn, "default-operation")) != NULL){ + if ((optstr = xml_body(x)) != NULL){ + if (strcmp(optstr, "replace") == 0) + *op = OP_REPLACE; + else + if (strcmp(optstr, "merge") == 0) + *op = OP_MERGE; + else + if (strcmp(optstr, "none") == 0) + *op = OP_NONE; + else{ + netconf_create_rpc_error(cb_err, xorig, + "invalid-value", + "protocol", + "error", + NULL, + NULL); + goto done; + } + } + } + if ((x = xpath_first(xn, "test-option")) != NULL){ + if ((optstr = xml_body(x)) != NULL){ + if (strcmp(optstr, "test-then-set") == 0) + *testopt = TEST_THEN_SET; + else + if (strcmp(optstr, "set") == 0) + *testopt = SET; + else + if (strcmp(optstr, "test-only") == 0) + *testopt = TEST_ONLY; + else{ + netconf_create_rpc_error(cb_err, xorig, + "invalid-value", + "protocol", + "error", + NULL, + NULL); + goto done; + } + } + } + if ((x = xpath_first(xn, "error-option")) != NULL){ + if ((optstr = xml_body(x)) != NULL){ + if (strcmp(optstr, "stop-on-error") == 0) + *erropt = STOP_ON_ERROR; + else + if (strcmp(optstr, "continue-on-error") == 0) + *erropt = CONTINUE_ON_ERROR; + else{ + netconf_create_rpc_error(cb_err, xorig, + "invalid-value", + "protocol", + "error", + NULL, + NULL); + goto done; + } + } + } + retval = 0; + done: + return retval; +} + + +/*! Netconf edit configuration + Write the change on a tmp file, then load that into candidate configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + (merge | none | replace) + (stop-on-error | continue-on-error ) + (set | test-then-set | test-only) + + * + * only 'config' supported + * error-option: only stop-on-error supported + * test-option: not supported + * + * @note delete/remove not implemented + * + * Call graph, client to backend and formats + * netconf_input_cb # client + * read + * process_incoming_packet # (char*) + * clicon_xml_parse_string # (xml) + * netconf_rpc_dispatch + * netconf_edit_config # client + * clicon_xml2file # (file) + * clicon_rpc_load + * from_client # backend + * from_client_load + * db_init # replace? + * load_xml_to_db + * clicon_xml_parse_file #(xml) + * xml2db + * xml2cvec_key #(cvec) + * clicon_dbput + * cvec2lvec #(lvec) + * db_set + * dpopen + * dpput #(db) + * dpclose + * Which means that for a single edit, the following format conversions are made: + * char*->xml->file->xml->cvec->lvec->db + * + */ +int +netconf_edit_config(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + int retval = -1; + int ret; + enum operation_type operation = OP_MERGE; + enum test_option testopt = TEST_THEN_SET; + enum error_option erropt = STOP_ON_ERROR; + cxobj *xc; /* config */ + cxobj *xcc; /* child of config */ + char *target; /* db */ + char *candidate_db; + cbuf *cbxml = NULL; + char *xmlstr; + + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + /* must have target, and it should be candidate */ + if ((target = netconf_get_target(h, xn, "target")) == NULL || + strcmp(target, candidate_db)){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "target"); + goto done; + } + if (get_edit_opts(xn, &operation, &testopt, &erropt, cb_err, xorig) < 0) + goto done; + /* operation is OP_REPLACE, OP_MERGE, or OP_NONE pass all to backend */ + if ((xc = xpath_first(xn, "config")) != NULL){ + /* application-specific code registers 'config' */ + if ((ret = netconf_plugin_callbacks(h, xc, cb, cb_err, xorig)) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Validation"); + goto done; + } + if ((cbxml = cbuf_new()) == NULL) + goto done; + if ((xcc = xml_child_i(xc, 0)) != NULL) + if (clicon_xml2cbuf(cbxml, xcc, 0, 0) < 0) + goto done; + xmlstr = cbuf_get(cbxml); + if (clicon_rpc_xmlput(h, target, + operation, + xmlstr) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "access-denied", + "protocol", + "error", + NULL, + "edit_config"); + goto done; + } + } + netconf_ok_set(1); + retval = 0; + done: + if (cbxml) + cbuf_free(cbxml); + unchunk_group(__FUNCTION__); + return retval; +} + +/* + + + + + + + + + + + */ +int +netconf_copy_config(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + char *source, *target; /* filenames */ + int retval = -1; + + if ((source = netconf_get_target(h, xn, "source")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "source"); + goto done; + } + if ((target = netconf_get_target(h, xn, "target")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "source"); + goto done; + } + +#ifdef notyet + /* If target is locked and not by this client, then return an error */ + if (target_locked(&client) > 0 && client != ce_nr){ + netconf_create_rpc_error(cb_err, xorig, + "access-denied", + "protocol", + "error", + NULL, + "lock"); + goto done; + } +#endif + if (clicon_rpc_copy(h, source, target) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + netconf_ok_set(1); + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +/* + + + + + + Delete a configuration datastore. The + configuration datastore cannot be deleted. + */ +int +netconf_delete_config(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + char *target; /* filenames */ + int retval = -1; + char *candidate_db; + + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + + if ((target = netconf_get_target(h, xn, "target")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "target"); + goto done; + } + if (strcmp(target, candidate_db)){ + netconf_create_rpc_error(cb_err, xorig, + "bad-element", + "protocol", + "error", + NULL, + "target"); + goto done; + } + if (clicon_rpc_rm(h, target) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + if (clicon_rpc_initdb(h, target) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + netconf_ok_set(1); + retval = 0; + done: + return retval; +} + +/* + +*/ +int +netconf_close_session(cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + cc_closed++; + netconf_ok_set(1); + return 0; +} + +/* + + + + + + */ +int +netconf_lock(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + char *target; + int retval = -1; + + if ((target = netconf_get_target(h, xn, "target")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "source"); + goto done; + } +#ifdef notyet + if (target_locked(&client) > 0){ + snprintf(info, 64, "%d", client); + netconf_create_rpc_error(cb_err, xorig, + "lock-denied", + "protocol", + "error", + "Lock failed, lock is already held", + info); + return -1; + } + + if (lock_target(target) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "lock-denied", + "protocol", + "error", + "Lock failed, lock is already held", + NULL); + return -1; + } +#endif + netconf_ok_set(1); + retval = 0; + done: + return retval; +} + +/* + + + + + + */ +int +netconf_unlock(clicon_handle h, + cxobj *xn, + cbuf *cb, cbuf *cb_err, + cxobj *xorig) +{ + char *target; + int retval = -1; + + if ((target = netconf_get_target(h, xn, "target")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "target"); + goto done; + } +#ifdef notyet + if (target_locked(&client) == 0){ + netconf_create_rpc_error(cb_err, xorig, + "lock-denied", + "protocol", + "error", + "Unlock failed, lock is not held", + NULL); + return -1; + } + + if (client != ce_nr){ + snprintf(info, 64, "%d", client); + netconf_create_rpc_error(cb_err, xorig, + "lock-denied", + "protocol", + "error", + "Unlock failed, lock is held by other entity", + info); + return -1; + } + if (unlock_target(target) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "lock-denied", + "protocol", + "error", + "Unlock failed, unkown reason", + NULL); + return -1; + } +#endif /* notyet */ + netconf_ok_set(1); + retval = 0; + done: + return retval; +} + +/* + + PID + + */ +int +netconf_kill_session(cxobj *xn, cbuf *cb, cbuf *cb_err, cxobj *xorig) +{ +#ifdef notyet + cxobj *xsessionid; + char *str, *ep; + long i; + + if ((xsessionid = xpath_first(xn, "//session-id")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "session-id"); + return -1; + } + if (xml_find_value(xsessionid, "body") == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "session-id"); + return -1; + } + if ((str = xml_find_value(xsessionid, "body")) != NULL){ + i = strtol(str, &ep, 0); + if ((i == LONG_MIN || i == LONG_MAX) && errno) + return -1; + if ((ce = find_ce_bynr(i)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", + "error", + NULL, + "No such client"); + return -1; + } + } +// ce_change_state(ce, CS_CLOSED, "Received close-session msg"); + netconf_ok_set(1); +#endif + return 0; +} + +/* + + :candidate + */ +int +netconf_commit(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + int retval = -1; + char *candidate_db; + char *running_db; + + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error: candidate not set"); + goto done; + } + if ((running_db = clicon_running_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error: running not set"); + goto done; + } + if (clicon_rpc_commit(h, candidate_db, + running_db, + 1, 1) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + netconf_ok_set(1); + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +/* + + :candidate + */ +int +netconf_discard_changes(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + int retval = -1; + char *running_db; + char *candidate_db; + + if ((running_db = clicon_running_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error: running not set"); + goto done; + } + if ((candidate_db = clicon_candidate_db(h)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + if (clicon_rpc_copy(h, running_db, candidate_db) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "protocol", "error", + NULL, "Internal error"); + goto done; + } + netconf_ok_set(1); + retval = 0; + done: + unchunk_group(__FUNCTION__); + return retval; +} + +/* + + :validate + */ +int +netconf_validate(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + char *target; + int retval = -1; + + if ((target = netconf_get_target(h, xn, "source")) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "missing-element", + "protocol", + "error", + NULL, + "target"); + goto done; + } + /* Do validation */ + netconf_ok_set(1); + retval = 0; + done: + return retval; +} + +/* + * netconf_notification_cb + * Called when a notification has happened on backend + * and this session has registered for that event. + * Filter it and forward it. + + 2007-07-08T00:01:00Z + + fault + + Ethernet0 + + major + + + */ +static int +netconf_notification_cb(int s, + void *arg) +{ + cxobj *xfilter = (cxobj *)arg; + char *selector; + struct clicon_msg *reply; + int eof; + char *event = NULL; + int level; + int retval = -1; + cbuf *cb; + cxobj *xe = NULL; /* event xml */ + enum clicon_msg_type type; + + if (0){ + fprintf(stderr, "%s\n", __FUNCTION__); /* debug */ + clicon_xml2file(stderr, xfilter, 0, 1); /* debug */ + } + /* get msg (this is the reason this function is called) */ + if (clicon_msg_rcv(s, &reply, &eof, __FUNCTION__) < 0) + goto done; + /* handle close from remote end: this will exit the client */ + if (eof){ + clicon_err(OE_PROTO, ESHUTDOWN, "%s: Socket unexpected close", __FUNCTION__); + close(s); + errno = ESHUTDOWN; + event_unreg_fd(s, netconf_notification_cb); + if (xfilter) + xml_free(xfilter); + goto done; + } + /* multiplex on message type: we only expect notify */ + type = ntohs(reply->op_type); + switch (type){ + case CLICON_MSG_NOTIFY: + if (clicon_msg_notify_decode(reply, &level, &event, __FUNCTION__) < 0) + goto done; + /* parse event */ + if (0){ /* XXX CLICON events are not xml */ + if (clicon_xml_parse_string(&event, &xe) < 0) + goto done; + /* find and apply filter */ + if ((selector = xml_find_value(xfilter, "select")) == NULL) + goto done; + if (xpath_first(xe, selector) == NULL) { + fprintf(stderr, "%s no match\n", __FUNCTION__); /* debug */ + break; + } + } + /* create netconf message */ + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_PLUGIN, errno, "%s: cbuf_new", __FUNCTION__); + goto done; + } + add_preamble(cb); /* Make it well-formed netconf xml */ + cprintf(cb, ""); + cprintf(cb, ""); + cprintf(cb, "%s", event); + cprintf(cb, ""); + cprintf(cb, ""); + add_postamble(cb); + /* Send it to listening client on stdout */ + if (netconf_output(1, cb, "notification") < 0){ + cbuf_free(cb); + goto done; + } + cbuf_free(cb); + break; + default: + clicon_err(OE_PROTO, 0, "%s: unexpected reply: %d", + __FUNCTION__, type); + goto done; + break; + } + retval = 0; + done: + if (xe != NULL) + xml_free(xe); +// if (event) +// free(event); + unchunk_group(__FUNCTION__); + return retval; +} + +/* + + + RESULT # If not present, events in the default NETCONF stream will be sent. + XPATH-EXPR<(filter> + # only for replay (NYI) + # only for replay (NYI) + + Dont support replay + */ +static int +netconf_create_subscription(clicon_handle h, + cxobj *xn, + cbuf *cb, + cbuf *cb_err, + cxobj *xorig) +{ + cxobj *xstream; + cxobj *xfilter; + cxobj *xfilter2 = NULL; + char *stream = NULL; + int s; + char *ftype; + int retval = -1; + + if ((xstream = xpath_first(xn, "//stream")) != NULL) + stream = xml_find_value(xstream, "body"); + if (stream == NULL) + stream = "NETCONF"; + if ((xfilter = xpath_first(xn, "//filter")) != NULL){ + if ((ftype = xml_find_value(xfilter, "type")) != NULL){ + if (strcmp(ftype, "xpath") != 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + "only xpath filter type supported", + "type"); + goto done; + } + } + /* xfilter2 is applied to netconf_notification_cb below + and is only freed on exit since no unreg is made. + */ + if ((xfilter2 = xml_dup(xfilter)) == NULL){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "Internal server error"); + goto done; + } + + } + + if (clicon_rpc_subscription(h, 1, stream, MSG_NOTIFY_XML, "", &s) < 0){ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "application", + "error", + NULL, + "Internal protocol error"); + goto done; + } + if (event_reg_fd(s, netconf_notification_cb, xfilter2, "notification socket") < 0) + goto done; + netconf_ok_set(1); + retval = 0; + done: + return retval; +} + + +/*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions. + * Call plugin handler if tag not found. If not handled by any handler, return + * error. + * @param[in] h clicon handle + * @param[in] xorig Original request as xml tree. + * @param[in] xn Sub-tree (under xorig) at ... level. + * @param[out] cb Output xml stream. For reply + * @param[out] cb_err Error xml stream. For error reply + */ +int +netconf_rpc_dispatch(clicon_handle h, + cxobj *xorig, + cxobj *xn, + cbuf *cb, + cbuf *cb_err) +{ + cxobj *xe; + int ret = 0; + + xe = NULL; + while ((xe = xml_child_each(xn, xe, CX_ELMNT)) != NULL) { + if (strcmp(xml_name(xe), "close-session") == 0) + return netconf_close_session(xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "get-config") == 0) + return netconf_get_config(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "edit-config") == 0) + return netconf_edit_config(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "copy-config") == 0) + return netconf_copy_config(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "delete-config") == 0) + return netconf_delete_config(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "kill-session") == 0) /* TBD */ + return netconf_kill_session(xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "lock") == 0) /* TBD */ + return netconf_lock(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "unlock") == 0) /* TBD */ + return netconf_unlock(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "commit") == 0) + return netconf_commit(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "discard-changes") == 0) + return netconf_discard_changes(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "validate") == 0) + return netconf_validate(h, xe, cb, cb_err, xorig); + else + if (strcmp(xml_name(xe), "create-subscription") == 0) + return netconf_create_subscription(h, + xe, cb, cb_err, xorig); + else{ + if ((ret = netconf_plugin_callbacks(h, + xe, cb, cb_err, xorig)) < 0) + return -1; + if (ret == 0){ /* not handled by callback */ + netconf_create_rpc_error(cb_err, xorig, + "operation-failed", + "rpc", "error", + xml_name(xe), "Not recognized"); + ret = -1; + } + + } + } + return ret; +} + +/* + * netconf_create_rpc_reply + * Create an rpc reply msg in cb + * Then send it using send_msg_to_client() + */ +int +netconf_create_rpc_reply(cbuf *cb, /* msg buffer */ + cxobj *xr, /* orig request */ + char *body, + int ok + ) +{ + cxobj *xn, *xa; + + add_preamble(cb); + cprintf(cb, ""); + if (ok) /* Just _maybe_ we should send data instead of ok if (if there is any) + even if ok is set? */ + cprintf(cb, ""); + else{ + cprintf(cb, ""); + cprintf(cb, "%s", body); + cprintf(cb, ""); + } + cprintf(cb, ""); + add_postamble(cb); + return 0; +} + + +/* + * netconf_create_rpc_error + * Create an rpc error msg in cb + * (Then it should be sent at a later stage using send_msg_to_client() ) + * Arguments: + * cb msg buffer to construct netconf message in + * xr original request including an "rpc" tag + * ... arguments to rpc-error reply message + */ +int +netconf_create_rpc_error(cbuf *cb, /* msg buffer */ + cxobj *xr, /* orig request */ + char *tag, + char *type, + char *severity, + char *message, + char *info) +{ + add_error_preamble(cb, tag); + cprintf(cb, ""); + cprintf(cb, ""); + if (tag) + cprintf(cb, "%s", tag); + cprintf(cb, "%s", type); + cprintf(cb, "%s", severity); + if (message) + cprintf(cb, "%s", message); + if (info) + cprintf(cb, "%s", info); + cprintf(cb, ""); + cprintf(cb, ""); + add_error_postamble(cb); + return 0; +} + diff --git a/apps/netconf/netconf_rpc.h b/apps/netconf/netconf_rpc.h new file mode 100644 index 000000000..53a5b796e --- /dev/null +++ b/apps/netconf/netconf_rpc.h @@ -0,0 +1,48 @@ +/* + * + 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 + . + + * + * Code for handling netconf rpc messages + *****************************************************************************/ +#ifndef _NETCONF_RPC_H_ +#define _NETCONF_RPC_H_ + +/* + * Prototypes + */ +int +netconf_rpc_dispatch(clicon_handle h, + cxobj *xorig, + cxobj *xn, + cbuf *xf, + cbuf *xf_err); + +int netconf_create_rpc_reply(cbuf *xf, /* msg buffer */ + cxobj *xr, /* orig request */ + char *body, int ok); +int netconf_create_rpc_error(cbuf *xf, /* msg buffer */ + cxobj *xr, /* orig request */ + char *tag, + char *type, + char *severity, + char *message, + char *info); + +#endif /* _NETCONF_RPC_H_ */ diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 new file mode 100644 index 000000000..a4d6361f5 --- /dev/null +++ b/autom4te.cache/output.0 @@ -0,0 +1,5482 @@ +@%:@! /bin/sh +@%:@ Guess values for system-dependent variables and create Makefiles. +@%:@ Generated by GNU Autoconf 2.69. +@%:@ +@%:@ +@%:@ Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +@%:@ +@%:@ +@%:@ This configure script is free software; the Free Software Foundation +@%:@ gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in @%:@( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in @%:@(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in @%:@ (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in @%:@( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in @%:@ (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +@%:@ as_fn_unset VAR +@%:@ --------------- +@%:@ Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +@%:@ as_fn_set_status STATUS +@%:@ ----------------------- +@%:@ Set @S|@? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} @%:@ as_fn_set_status + +@%:@ as_fn_exit STATUS +@%:@ ----------------- +@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} @%:@ as_fn_exit + +@%:@ as_fn_mkdir_p +@%:@ ------------- +@%:@ Create "@S|@as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} @%:@ as_fn_mkdir_p + +@%:@ as_fn_executable_p FILE +@%:@ ----------------------- +@%:@ Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} @%:@ as_fn_executable_p +@%:@ as_fn_append VAR VALUE +@%:@ ---------------------- +@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take +@%:@ advantage of any shell optimizations that allow amortized linear growth over +@%:@ repeated appends, instead of the typical quadratic growth present in naive +@%:@ implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +@%:@ as_fn_arith ARG... +@%:@ ------------------ +@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the +@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments +@%:@ must be portable across @S|@(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD] +@%:@ ---------------------------------------- +@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are +@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the +@%:@ script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} @%:@ as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in @%:@((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIB@&t@OBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="lib/clicon/clicon.h.in" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIB@&t@OBJS +EGREP +GREP +LEXLIB +LEX_OUTPUT_ROOT +LEX +YFLAGS +YACC +CPP +OBJEXT +EXEEXT +ac_ct_CC +CLICON__LIBDIR +RANLIB +AR +EXE_SUFFIX +SH_SUFFIX +AR_SUFFIX +OBJ_SUFFIX +CPPFLAGS +INCLUDES +LDFLAGS +CFLAGS +CC +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +CLIGEN_VERSION +CLICON_VERSION_MINOR +CLICON_VERSION_MAJOR +CLICON_VERSION_STRING +CLICON_VERSION +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_keycontent +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +YACC +YFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + @<:@@S|@ac_default_prefix@:>@ + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + @<:@PREFIX@:>@ + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root @<:@DATAROOTDIR/doc/PACKAGE@:>@ + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-keycontent Disable reverse lookup content keys + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to @S|@YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +@%:@ ac_fn_c_try_compile LINENO +@%:@ -------------------------- +@%:@ Try to compile conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_compile + +@%:@ ac_fn_c_try_cpp LINENO +@%:@ ---------------------- +@%:@ Try to preprocess conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_cpp + +@%:@ ac_fn_c_try_link LINENO +@%:@ ----------------------- +@%:@ Try to link conftest.@S|@ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_link + +@%:@ ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +@%:@ ------------------------------------------------------- +@%:@ Tests whether HEADER exists, giving a warning if it cannot be compiled using +@%:@ the include files in INCLUDES and setting the cache variable VAR +@%:@ accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +@%:@include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_header_mongrel + +@%:@ ac_fn_c_try_run LINENO +@%:@ ---------------------- +@%:@ Try to link conftest.@S|@ac_ext, and return whether this succeeded. Assumes +@%:@ that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} @%:@ ac_fn_c_try_run + +@%:@ ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +@%:@ ------------------------------------------------------- +@%:@ Tests whether HEADER exists and can be compiled using the include files in +@%:@ INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +@%:@include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_header_compile + +@%:@ ac_fn_c_check_func LINENO FUNC VAR +@%:@ ---------------------------------- +@%:@ Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} @%:@ ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in @%:@(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Default CFLAGS unless set by environment. +: ${CFLAGS="-O2"} + +CLICON_VERSION_MAJOR="3" +CLICON_VERSION_MINOR="2" +CLICON_VERSION_PATCH="0" +CLICON_VERSION="\"${CLICON_VERSION_MAJOR}.${CLICON_VERSION_MINOR}.${CLICON_VERSION_PATCH}\"" +# Fix to specific version (eg 3.5) or head (3) +CLIGEN_VERSION="3.5" + +ac_config_headers="$ac_config_headers include/clicon_config.h lib/clicon/clicon.h" + + +cat >>confdefs.h <<_ACEOF +@%:@define CLICON_VERSION_STRING $CLICON_VERSION +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define CLICON_VERSION_MAJOR $CLICON_VERSION_MAJOR +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define CLICON_VERSION_MINOR $CLICON_VERSION_MINOR +_ACEOF + +cat >>confdefs.h <<_ACEOF +@%:@define CLICON_VERSION_PATCH $CLICON_VERSION_PATCH +_ACEOF + + +# clicon versions spread to Makefile's (.so files) and variable in build.c + + + + + # Bind to specific CLIgen version + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CLICON version is ${CLICON_VERSION}_PRE1" >&5 +$as_echo "CLICON version is ${CLICON_VERSION}_PRE1" >&6; } + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# 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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + + + + + + + + + + + + # Clicon application director. Eg /hello. + +# Some stuff installed in /usr/local/. Such as qdbm +LIBS="-L /usr/local/lib" + +# +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $@%:@ != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +@%:@include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler is $CC" >&5 +$as_echo "compiler is $CC" >&6; } + +CFLAGS="${CFLAGS} -Wall" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS is $CPPFLAGS" >&5 +$as_echo "CPPFLAGS is $CPPFLAGS" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS is $CFLAGS" >&5 +$as_echo "CFLAGS is $CFLAGS" >&6; } + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 +$as_echo "$LEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ + yyless ((input () != 0)); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ { ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 +$as_echo_n "checking lex output file root... " >&6; } +if ${ac_cv_prog_lex_root+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 +$as_echo "$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 +$as_echo_n "checking lex library... " >&6; } +if ${ac_cv_lib_lex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lex=$ac_lib +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 +$as_echo "$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 +$as_echo_n "checking whether yytext is a pointer... " >&6; } +if ${ac_cv_prog_lex_yytext_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_prog_lex_yytext_pointer=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 +$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +$as_echo "@%:@define YYTEXT_POINTER 1" >>confdefs.h + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi +if test "$LEX" = ":"; then + as_fn_error $? "CLICON does not find lex or flex." "$LINENO" 5 +fi +if test "$YACC" != "bison -y"; then + as_fn_error $? "CLICON does not find bison. There are several problems with yacc and byacc. Please install bison." "$LINENO" 5 +fi + +if test "$prefix" = "NONE"; then + CPPFLAGS="-I${ac_default_prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${ac_default_prefix}/lib ${LDFLAGS}" +else + CPPFLAGS="-I${prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${prefix}/lib ${LDFLAGS}" +fi + +LDFLAGS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 +$as_echo_n "checking for main in -lm... " >&6; } +if ${ac_cv_lib_m_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_main=yes +else + ac_cv_lib_m_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 +$as_echo "$ac_cv_lib_m_main" >&6; } +if test "x$ac_cv_lib_m_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +EXE_SUFFIX="" +OBJ_SUFFIX=".o" +AR_SUFFIX=".a" +SH_SUFFIX=".so" +AR="ar" + +# This is for cligen + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "@%:@define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in cligen/cligen.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "cligen/cligen.h" "ac_cv_header_cligen_cligen_h" "$ac_includes_default" +if test "x$ac_cv_header_cligen_cligen_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_CLIGEN_CLIGEN_H 1 +_ACEOF + +else + as_fn_error $? "cligen missing. Try: git clone https://github.com/olofhagsand/cligen.git" "$LINENO" 5 +fi + +done + + +as_ac_Lib=`$as_echo "ac_cv_lib_:libcligen.so.${CLIGEN_VERSION}''_cligen_init" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cligen_init in -l:libcligen.so.${CLIGEN_VERSION}" >&5 +$as_echo_n "checking for cligen_init in -l:libcligen.so.${CLIGEN_VERSION}... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l:libcligen.so.${CLIGEN_VERSION} $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cligen_init (); +int +main () +{ +return cligen_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +@%:@define `$as_echo "HAVE_LIB:libcligen.so.${CLIGEN_VERSION}" | $as_tr_cpp` 1 +_ACEOF + + LIBS="-l:libcligen.so.${CLIGEN_VERSION} $LIBS" + +else + as_fn_error $? "CLIgen${CLIGEN_VERSION} missing. Try: git clone https://github.com/olofhagsand/cligen.git" "$LINENO" 5 +fi + + +# This is for qdbm. +# Problem: depot.h may be in qdbm/depot.h. +for ac_header in depot.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "depot.h" "ac_cv_header_depot_h" "$ac_includes_default" +if test "x$ac_cv_header_depot_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_DEPOT_H 1 +_ACEOF + +else + for ac_header in qdbm/depot.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "qdbm/depot.h" "ac_cv_header_qdbm_depot_h" "$ac_includes_default" +if test "x$ac_cv_header_qdbm_depot_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_QDBM_DEPOT_H 1 +_ACEOF + +else + as_fn_error $? "libqdbm-dev required" "$LINENO" 5 +fi + +done + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dpopen in -lqdbm" >&5 +$as_echo_n "checking for dpopen in -lqdbm... " >&6; } +if ${ac_cv_lib_qdbm_dpopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lqdbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dpopen (); +int +main () +{ +return dpopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_qdbm_dpopen=yes +else + ac_cv_lib_qdbm_dpopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_dpopen" >&5 +$as_echo "$ac_cv_lib_qdbm_dpopen" >&6; } +if test "x$ac_cv_lib_qdbm_dpopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBQDBM 1 +_ACEOF + + LIBS="-lqdbm $LIBS" + +else + as_fn_error $? "libqdbm-dev required" "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5 +$as_echo_n "checking for crypt in -lcrypt... " >&6; } +if ${ac_cv_lib_crypt_crypt+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypt_crypt=yes +else + ac_cv_lib_crypt_crypt=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5 +$as_echo "$ac_cv_lib_crypt_crypt" >&6; } +if test "x$ac_cv_lib_crypt_crypt" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBCRYPT 1 +_ACEOF + + LIBS="-lcrypt $LIBS" + +fi + +for ac_header in crypt.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "crypt.h" "ac_cv_header_crypt_h" "$ac_includes_default" +if test "x$ac_cv_header_crypt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_CRYPT_H 1 +_ACEOF + +fi + +done + + +# user credentials for unix sockets +for ac_header in sys/ucred.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/ucred.h" "ac_cv_header_sys_ucred_h" "# include + +" +if test "x$ac_cv_header_sys_ucred_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_SYS_UCRED_H 1 +_ACEOF + +fi + +done + + +# This is for Linux vlan code +for ac_header in linux/if_vlan.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linux/if_vlan.h" "ac_cv_header_linux_if_vlan_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_if_vlan_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LINUX_IF_VLAN_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +$as_echo_n "checking for socket in -lsocket... " >&6; } +if ${ac_cv_lib_socket_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_socket=yes +else + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +$as_echo "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for xdr_char in -lnsl" >&5 +$as_echo_n "checking for xdr_char in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_xdr_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xdr_char (); +int +main () +{ +return xdr_char (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_xdr_char=yes +else + ac_cv_lib_nsl_xdr_char=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_xdr_char" >&5 +$as_echo "$ac_cv_lib_nsl_xdr_char" >&6; } +if test "x$ac_cv_lib_nsl_xdr_char" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + + +for ac_func in inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +@%:@define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Check if extra keys inserted for database lists containing content. Eg A.n.foo = 3 +# means A.3 $!a=foo exists + +@%:@ Check whether --enable-keycontent was given. +if test "${enable_keycontent+set}" = set; then : + enableval=$enable_keycontent; + if test "$enableval" = no; then + ac_enable_keycontent=no + else + ac_enable_keycontent=yes + fi + +else + ac_enable_keycontent=yes +fi + + + +if test "$ac_enable_keycontent" = "yes"; then + $as_echo "@%:@define DB_KEYCONTENT 1" >>confdefs.h + +fi + + + +ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clicon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/dbctrl/Makefile include/Makefile etc/Makefile etc/cliconrc example/Makefile doc/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIB@&t@OBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIB@&t@OBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in @%:@( + *posix*) : + set -o posix ;; @%:@( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in @%:@( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in @%:@(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD] +@%:@ ---------------------------------------- +@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are +@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the +@%:@ script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} @%:@ as_fn_error + + +@%:@ as_fn_set_status STATUS +@%:@ ----------------------- +@%:@ Set @S|@? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} @%:@ as_fn_set_status + +@%:@ as_fn_exit STATUS +@%:@ ----------------- +@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} @%:@ as_fn_exit + +@%:@ as_fn_unset VAR +@%:@ --------------- +@%:@ Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +@%:@ as_fn_append VAR VALUE +@%:@ ---------------------- +@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take +@%:@ advantage of any shell optimizations that allow amortized linear growth over +@%:@ repeated appends, instead of the typical quadratic growth present in naive +@%:@ implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +@%:@ as_fn_arith ARG... +@%:@ ------------------ +@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the +@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments +@%:@ must be portable across @S|@(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in @%:@((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +@%:@ as_fn_mkdir_p +@%:@ ------------- +@%:@ Create "@S|@as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} @%:@ as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +@%:@ as_fn_executable_p FILE +@%:@ ----------------------- +@%:@ Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} @%:@ as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX +@%:@@%:@ Running $as_me. @%:@@%:@ +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/clicon_config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/clicon_config.h" ;; + "lib/clicon/clicon.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/clicon/clicon.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "lib/src/Makefile") CONFIG_FILES="$CONFIG_FILES lib/src/Makefile" ;; + "lib/clicon/Makefile") CONFIG_FILES="$CONFIG_FILES lib/clicon/Makefile" ;; + "apps/Makefile") CONFIG_FILES="$CONFIG_FILES apps/Makefile" ;; + "apps/cli/Makefile") CONFIG_FILES="$CONFIG_FILES apps/cli/Makefile" ;; + "apps/backend/Makefile") CONFIG_FILES="$CONFIG_FILES apps/backend/Makefile" ;; + "apps/netconf/Makefile") CONFIG_FILES="$CONFIG_FILES apps/netconf/Makefile" ;; + "apps/dbctrl/Makefile") CONFIG_FILES="$CONFIG_FILES apps/dbctrl/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "etc/Makefile") CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;; + "etc/cliconrc") CONFIG_FILES="$CONFIG_FILES etc/cliconrc" ;; + "example/Makefile") CONFIG_FILES="$CONFIG_FILES example/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/autom4te.cache/requests b/autom4te.cache/requests new file mode 100644 index 000000000..8da21f8c7 --- /dev/null +++ b/autom4te.cache/requests @@ -0,0 +1,77 @@ +# This file was generated by Autom4te Thu Apr 10 10:06:43 UTC 2014. +# It contains the lists of macros which have been traced. +# It can be safely removed. + +@request = ( + bless( [ + '0', + 1, + [ + '/usr/share/autoconf' + ], + [ + '/usr/share/autoconf/autoconf/autoconf.m4f', + 'configure.ac' + ], + { + 'AC_REQUIRE_AUX_FILE' => 1, + 'AC_DEFINE_TRACE_LITERAL' => 1, + 'AC_SUBST_TRACE' => 1, + 'AC_CONFIG_FILES' => 1, + 'AC_SUBST' => 1, + 'LT_INIT' => 1, + 'AC_FC_PP_SRCEXT' => 1, + '_LT_AC_TAGCONFIG' => 1, + 'm4_sinclude' => 1, + 'AC_FC_FREEFORM' => 1, + 'sinclude' => 1, + 'AM_PATH_GUILE' => 1, + 'AC_CONFIG_LIBOBJ_DIR' => 1, + 'AC_INIT' => 1, + '_AM_COND_ENDIF' => 1, + 'AM_PROG_CXX_C_O' => 1, + 'm4_pattern_allow' => 1, + 'AM_SILENT_RULES' => 1, + 'm4_include' => 1, + '_m4_warn' => 1, + 'AC_CONFIG_LINKS' => 1, + 'AM_AUTOMAKE_VERSION' => 1, + 'AM_NLS' => 1, + 'AC_FC_SRCEXT' => 1, + 'AM_CONDITIONAL' => 1, + '_AM_SUBST_NOTMAKE' => 1, + '_AM_COND_ELSE' => 1, + 'AC_CONFIG_AUX_DIR' => 1, + 'AC_CONFIG_HEADERS' => 1, + 'AM_GNU_GETTEXT' => 1, + 'AM_INIT_AUTOMAKE' => 1, + 'include' => 1, + 'LT_CONFIG_LTDL_DIR' => 1, + '_AM_COND_IF' => 1, + 'AM_PROG_F77_C_O' => 1, + 'AC_CANONICAL_SYSTEM' => 1, + 'AC_CONFIG_SUBDIRS' => 1, + 'AC_LIBSOURCE' => 1, + 'AM_PROG_MOC' => 1, + 'AC_FC_PP_DEFINE' => 1, + '_AM_MAKEFILE_INCLUDE' => 1, + 'AM_ENABLE_MULTILIB' => 1, + 'AC_PROG_LIBTOOL' => 1, + 'AM_PROG_FC_C_O' => 1, + 'AM_XGETTEXT_OPTION' => 1, + 'AM_GNU_GETTEXT_INTL_SUBDIR' => 1, + 'AM_POT_TOOLS' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AM_PROG_AR' => 1, + 'AM_MAKEFILE_INCLUDE' => 1, + 'AC_CANONICAL_TARGET' => 1, + 'AM_PROG_CC_C_O' => 1, + 'LT_SUPPORTED_TAG' => 1, + 'm4_pattern_forbid' => 1, + 'AH_OUTPUT' => 1, + 'AC_CANONICAL_BUILD' => 1 + } + ], 'Autom4te::Request' ) + ); + diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0 new file mode 100644 index 000000000..942fb32fb --- /dev/null +++ b/autom4te.cache/traces.0 @@ -0,0 +1,452 @@ +m4trace:configure.ac:26: -1- AC_INIT([lib/clicon/clicon.h.in]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([^_?A[CHUM]_]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([_AC_]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) +m4trace:configure.ac:26: -1- m4_pattern_allow([^AS_FLAGS$]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([^_?m4_]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([^dnl$]) +m4trace:configure.ac:26: -1- m4_pattern_forbid([^_?AS_]) +m4trace:configure.ac:26: -1- AC_SUBST([SHELL]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([SHELL]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^SHELL$]) +m4trace:configure.ac:26: -1- AC_SUBST([PATH_SEPARATOR]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PATH_SEPARATOR]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PATH_SEPARATOR$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_NAME]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_NAME$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_TARNAME]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_VERSION]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_VERSION$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_STRING]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_STRING$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) +m4trace:configure.ac:26: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL], ['AC_PACKAGE_URL'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([PACKAGE_URL]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_URL$]) +m4trace:configure.ac:26: -1- AC_SUBST([exec_prefix], [NONE]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([exec_prefix]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^exec_prefix$]) +m4trace:configure.ac:26: -1- AC_SUBST([prefix], [NONE]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([prefix]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^prefix$]) +m4trace:configure.ac:26: -1- AC_SUBST([program_transform_name], [s,x,x,]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([program_transform_name]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^program_transform_name$]) +m4trace:configure.ac:26: -1- AC_SUBST([bindir], ['${exec_prefix}/bin']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([bindir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^bindir$]) +m4trace:configure.ac:26: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([sbindir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^sbindir$]) +m4trace:configure.ac:26: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([libexecdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^libexecdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([datarootdir], ['${prefix}/share']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([datarootdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^datarootdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([datadir], ['${datarootdir}']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([datadir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^datadir$]) +m4trace:configure.ac:26: -1- AC_SUBST([sysconfdir], ['${prefix}/etc']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([sysconfdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^sysconfdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([sharedstatedir], ['${prefix}/com']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([sharedstatedir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^sharedstatedir$]) +m4trace:configure.ac:26: -1- AC_SUBST([localstatedir], ['${prefix}/var']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([localstatedir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^localstatedir$]) +m4trace:configure.ac:26: -1- AC_SUBST([includedir], ['${prefix}/include']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([includedir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^includedir$]) +m4trace:configure.ac:26: -1- AC_SUBST([oldincludedir], ['/usr/include']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([oldincludedir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^oldincludedir$]) +m4trace:configure.ac:26: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME], + ['${datarootdir}/doc/${PACKAGE_TARNAME}'], + ['${datarootdir}/doc/${PACKAGE}'])]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([docdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^docdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([infodir], ['${datarootdir}/info']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([infodir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^infodir$]) +m4trace:configure.ac:26: -1- AC_SUBST([htmldir], ['${docdir}']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([htmldir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^htmldir$]) +m4trace:configure.ac:26: -1- AC_SUBST([dvidir], ['${docdir}']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([dvidir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^dvidir$]) +m4trace:configure.ac:26: -1- AC_SUBST([pdfdir], ['${docdir}']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([pdfdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^pdfdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([psdir], ['${docdir}']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([psdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^psdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([libdir], ['${exec_prefix}/lib']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([libdir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^libdir$]) +m4trace:configure.ac:26: -1- AC_SUBST([localedir], ['${datarootdir}/locale']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([localedir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^localedir$]) +m4trace:configure.ac:26: -1- AC_SUBST([mandir], ['${datarootdir}/man']) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([mandir]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^mandir$]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_NAME$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */ +@%:@undef PACKAGE_NAME]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */ +@%:@undef PACKAGE_TARNAME]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_VERSION$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */ +@%:@undef PACKAGE_VERSION]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_STRING$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */ +@%:@undef PACKAGE_STRING]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */ +@%:@undef PACKAGE_BUGREPORT]) +m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^PACKAGE_URL$]) +m4trace:configure.ac:26: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */ +@%:@undef PACKAGE_URL]) +m4trace:configure.ac:26: -1- AC_SUBST([DEFS]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([DEFS]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^DEFS$]) +m4trace:configure.ac:26: -1- AC_SUBST([ECHO_C]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([ECHO_C]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^ECHO_C$]) +m4trace:configure.ac:26: -1- AC_SUBST([ECHO_N]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([ECHO_N]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^ECHO_N$]) +m4trace:configure.ac:26: -1- AC_SUBST([ECHO_T]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([ECHO_T]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^ECHO_T$]) +m4trace:configure.ac:26: -1- AC_SUBST([LIBS]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([LIBS]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^LIBS$]) +m4trace:configure.ac:26: -1- AC_SUBST([build_alias]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([build_alias]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^build_alias$]) +m4trace:configure.ac:26: -1- AC_SUBST([host_alias]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([host_alias]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^host_alias$]) +m4trace:configure.ac:26: -1- AC_SUBST([target_alias]) +m4trace:configure.ac:26: -1- AC_SUBST_TRACE([target_alias]) +m4trace:configure.ac:26: -1- m4_pattern_allow([^target_alias$]) +m4trace:configure.ac:38: -1- AC_CONFIG_HEADERS([include/clicon_config.h lib/clicon/clicon.h]) +m4trace:configure.ac:40: -1- AC_DEFINE_TRACE_LITERAL([CLICON_VERSION_STRING]) +m4trace:configure.ac:40: -1- m4_pattern_allow([^CLICON_VERSION_STRING$]) +m4trace:configure.ac:41: -1- AC_DEFINE_TRACE_LITERAL([CLICON_VERSION_MAJOR]) +m4trace:configure.ac:41: -1- m4_pattern_allow([^CLICON_VERSION_MAJOR$]) +m4trace:configure.ac:42: -1- AC_DEFINE_TRACE_LITERAL([CLICON_VERSION_MINOR]) +m4trace:configure.ac:42: -1- m4_pattern_allow([^CLICON_VERSION_MINOR$]) +m4trace:configure.ac:43: -1- AC_DEFINE_TRACE_LITERAL([CLICON_VERSION_PATCH]) +m4trace:configure.ac:43: -1- m4_pattern_allow([^CLICON_VERSION_PATCH$]) +m4trace:configure.ac:46: -1- AC_SUBST([CLICON_VERSION]) +m4trace:configure.ac:46: -1- AC_SUBST_TRACE([CLICON_VERSION]) +m4trace:configure.ac:46: -1- m4_pattern_allow([^CLICON_VERSION$]) +m4trace:configure.ac:47: -1- AC_SUBST([CLICON_VERSION_STRING]) +m4trace:configure.ac:47: -1- AC_SUBST_TRACE([CLICON_VERSION_STRING]) +m4trace:configure.ac:47: -1- m4_pattern_allow([^CLICON_VERSION_STRING$]) +m4trace:configure.ac:48: -1- AC_SUBST([CLICON_VERSION_MAJOR]) +m4trace:configure.ac:48: -1- AC_SUBST_TRACE([CLICON_VERSION_MAJOR]) +m4trace:configure.ac:48: -1- m4_pattern_allow([^CLICON_VERSION_MAJOR$]) +m4trace:configure.ac:49: -1- AC_SUBST([CLICON_VERSION_MINOR]) +m4trace:configure.ac:49: -1- AC_SUBST_TRACE([CLICON_VERSION_MINOR]) +m4trace:configure.ac:49: -1- m4_pattern_allow([^CLICON_VERSION_MINOR$]) +m4trace:configure.ac:50: -1- AC_SUBST([CLIGEN_VERSION]) +m4trace:configure.ac:50: -1- AC_SUBST_TRACE([CLIGEN_VERSION]) +m4trace:configure.ac:50: -1- m4_pattern_allow([^CLIGEN_VERSION$]) +m4trace:configure.ac:55: -1- AC_CANONICAL_TARGET +m4trace:configure.ac:55: -1- AC_CANONICAL_HOST +m4trace:configure.ac:55: -1- AC_CANONICAL_BUILD +m4trace:configure.ac:55: -1- AC_REQUIRE_AUX_FILE([config.sub]) +m4trace:configure.ac:55: -1- AC_REQUIRE_AUX_FILE([config.guess]) +m4trace:configure.ac:55: -1- AC_SUBST([build], [$ac_cv_build]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([build]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^build$]) +m4trace:configure.ac:55: -1- AC_SUBST([build_cpu], [$[1]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([build_cpu]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^build_cpu$]) +m4trace:configure.ac:55: -1- AC_SUBST([build_vendor], [$[2]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([build_vendor]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^build_vendor$]) +m4trace:configure.ac:55: -1- AC_SUBST([build_os]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([build_os]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^build_os$]) +m4trace:configure.ac:55: -1- AC_SUBST([host], [$ac_cv_host]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([host]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^host$]) +m4trace:configure.ac:55: -1- AC_SUBST([host_cpu], [$[1]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([host_cpu]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^host_cpu$]) +m4trace:configure.ac:55: -1- AC_SUBST([host_vendor], [$[2]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([host_vendor]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^host_vendor$]) +m4trace:configure.ac:55: -1- AC_SUBST([host_os]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([host_os]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^host_os$]) +m4trace:configure.ac:55: -1- AC_SUBST([target], [$ac_cv_target]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([target]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^target$]) +m4trace:configure.ac:55: -1- AC_SUBST([target_cpu], [$[1]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([target_cpu]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^target_cpu$]) +m4trace:configure.ac:55: -1- AC_SUBST([target_vendor], [$[2]]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([target_vendor]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^target_vendor$]) +m4trace:configure.ac:55: -1- AC_SUBST([target_os]) +m4trace:configure.ac:55: -1- AC_SUBST_TRACE([target_os]) +m4trace:configure.ac:55: -1- m4_pattern_allow([^target_os$]) +m4trace:configure.ac:56: -1- AC_SUBST([CC]) +m4trace:configure.ac:56: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:56: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:57: -1- AC_SUBST([CFLAGS]) +m4trace:configure.ac:57: -1- AC_SUBST_TRACE([CFLAGS]) +m4trace:configure.ac:57: -1- m4_pattern_allow([^CFLAGS$]) +m4trace:configure.ac:58: -1- AC_SUBST([LDFLAGS]) +m4trace:configure.ac:58: -1- AC_SUBST_TRACE([LDFLAGS]) +m4trace:configure.ac:58: -1- m4_pattern_allow([^LDFLAGS$]) +m4trace:configure.ac:59: -1- AC_SUBST([INCLUDES]) +m4trace:configure.ac:59: -1- AC_SUBST_TRACE([INCLUDES]) +m4trace:configure.ac:59: -1- m4_pattern_allow([^INCLUDES$]) +m4trace:configure.ac:60: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:60: -1- AC_SUBST_TRACE([CPPFLAGS]) +m4trace:configure.ac:60: -1- m4_pattern_allow([^CPPFLAGS$]) +m4trace:configure.ac:61: -1- AC_SUBST([LIBS]) +m4trace:configure.ac:61: -1- AC_SUBST_TRACE([LIBS]) +m4trace:configure.ac:61: -1- m4_pattern_allow([^LIBS$]) +m4trace:configure.ac:62: -1- AC_SUBST([OBJ_SUFFIX]) +m4trace:configure.ac:62: -1- AC_SUBST_TRACE([OBJ_SUFFIX]) +m4trace:configure.ac:62: -1- m4_pattern_allow([^OBJ_SUFFIX$]) +m4trace:configure.ac:63: -1- AC_SUBST([AR_SUFFIX]) +m4trace:configure.ac:63: -1- AC_SUBST_TRACE([AR_SUFFIX]) +m4trace:configure.ac:63: -1- m4_pattern_allow([^AR_SUFFIX$]) +m4trace:configure.ac:64: -1- AC_SUBST([SH_SUFFIX]) +m4trace:configure.ac:64: -1- AC_SUBST_TRACE([SH_SUFFIX]) +m4trace:configure.ac:64: -1- m4_pattern_allow([^SH_SUFFIX$]) +m4trace:configure.ac:65: -1- AC_SUBST([EXE_SUFFIX]) +m4trace:configure.ac:65: -1- AC_SUBST_TRACE([EXE_SUFFIX]) +m4trace:configure.ac:65: -1- m4_pattern_allow([^EXE_SUFFIX$]) +m4trace:configure.ac:66: -1- AC_SUBST([AR]) +m4trace:configure.ac:66: -1- AC_SUBST_TRACE([AR]) +m4trace:configure.ac:66: -1- m4_pattern_allow([^AR$]) +m4trace:configure.ac:67: -1- AC_SUBST([RANLIB]) +m4trace:configure.ac:67: -1- AC_SUBST_TRACE([RANLIB]) +m4trace:configure.ac:67: -1- m4_pattern_allow([^RANLIB$]) +m4trace:configure.ac:68: -1- AC_SUBST([CLICON__LIBDIR]) +m4trace:configure.ac:68: -1- AC_SUBST_TRACE([CLICON__LIBDIR]) +m4trace:configure.ac:68: -1- m4_pattern_allow([^CLICON__LIBDIR$]) +m4trace:configure.ac:74: -1- AC_SUBST([CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([CFLAGS]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CFLAGS]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CFLAGS$]) +m4trace:configure.ac:74: -1- AC_SUBST([LDFLAGS]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([LDFLAGS]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^LDFLAGS$]) +m4trace:configure.ac:74: -1- AC_SUBST([LIBS]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([LIBS]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^LIBS$]) +m4trace:configure.ac:74: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CPPFLAGS]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CPPFLAGS$]) +m4trace:configure.ac:74: -1- AC_SUBST([CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([ac_ct_CC]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([ac_ct_CC]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^ac_ct_CC$]) +m4trace:configure.ac:74: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([EXEEXT]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^EXEEXT$]) +m4trace:configure.ac:74: -1- AC_SUBST([OBJEXT], [$ac_cv_objext]) +m4trace:configure.ac:74: -1- AC_SUBST_TRACE([OBJEXT]) +m4trace:configure.ac:74: -1- m4_pattern_allow([^OBJEXT$]) +m4trace:configure.ac:75: -1- AC_SUBST([CPP]) +m4trace:configure.ac:75: -1- AC_SUBST_TRACE([CPP]) +m4trace:configure.ac:75: -1- m4_pattern_allow([^CPP$]) +m4trace:configure.ac:75: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:75: -1- AC_SUBST_TRACE([CPPFLAGS]) +m4trace:configure.ac:75: -1- m4_pattern_allow([^CPPFLAGS$]) +m4trace:configure.ac:75: -1- AC_SUBST([CPP]) +m4trace:configure.ac:75: -1- AC_SUBST_TRACE([CPP]) +m4trace:configure.ac:75: -1- m4_pattern_allow([^CPP$]) +m4trace:configure.ac:86: -1- AC_SUBST([YACC]) +m4trace:configure.ac:86: -1- AC_SUBST_TRACE([YACC]) +m4trace:configure.ac:86: -1- m4_pattern_allow([^YACC$]) +m4trace:configure.ac:86: -1- AC_SUBST([YACC]) +m4trace:configure.ac:86: -1- AC_SUBST_TRACE([YACC]) +m4trace:configure.ac:86: -1- m4_pattern_allow([^YACC$]) +m4trace:configure.ac:86: -1- AC_SUBST([YFLAGS]) +m4trace:configure.ac:86: -1- AC_SUBST_TRACE([YFLAGS]) +m4trace:configure.ac:86: -1- m4_pattern_allow([^YFLAGS$]) +m4trace:configure.ac:87: -1- AC_SUBST([LEX]) +m4trace:configure.ac:87: -1- AC_SUBST_TRACE([LEX]) +m4trace:configure.ac:87: -1- m4_pattern_allow([^LEX$]) +m4trace:configure.ac:87: -1- AC_SUBST([LEX_OUTPUT_ROOT], [$ac_cv_prog_lex_root]) +m4trace:configure.ac:87: -1- AC_SUBST_TRACE([LEX_OUTPUT_ROOT]) +m4trace:configure.ac:87: -1- m4_pattern_allow([^LEX_OUTPUT_ROOT$]) +m4trace:configure.ac:87: -1- AC_SUBST([LEXLIB]) +m4trace:configure.ac:87: -1- AC_SUBST_TRACE([LEXLIB]) +m4trace:configure.ac:87: -1- m4_pattern_allow([^LEXLIB$]) +m4trace:configure.ac:87: -1- AC_DEFINE_TRACE_LITERAL([YYTEXT_POINTER]) +m4trace:configure.ac:87: -1- m4_pattern_allow([^YYTEXT_POINTER$]) +m4trace:configure.ac:87: -1- AH_OUTPUT([YYTEXT_POINTER], [/* Define to 1 if `lex\' declares `yytext\' as a `char *\' by default, not a + `char@<:@@:>@\'. */ +@%:@undef YYTEXT_POINTER]) +m4trace:configure.ac:104: -1- AH_OUTPUT([HAVE_LIBM], [/* Define to 1 if you have the `m\' library (-lm). */ +@%:@undef HAVE_LIBM]) +m4trace:configure.ac:104: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBM]) +m4trace:configure.ac:104: -1- m4_pattern_allow([^HAVE_LIBM$]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_CLIGEN_CLIGEN_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_CLIGEN_CLIGEN_H]) +m4trace:configure.ac:112: -1- AC_SUBST([GREP]) +m4trace:configure.ac:112: -1- AC_SUBST_TRACE([GREP]) +m4trace:configure.ac:112: -1- m4_pattern_allow([^GREP$]) +m4trace:configure.ac:112: -1- AC_SUBST([EGREP]) +m4trace:configure.ac:112: -1- AC_SUBST_TRACE([EGREP]) +m4trace:configure.ac:112: -1- m4_pattern_allow([^EGREP$]) +m4trace:configure.ac:112: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS]) +m4trace:configure.ac:112: -1- m4_pattern_allow([^STDC_HEADERS$]) +m4trace:configure.ac:112: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */ +@%:@undef STDC_HEADERS]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_SYS_TYPES_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_SYS_STAT_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STDLIB_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STRING_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_MEMORY_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STRINGS_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_INTTYPES_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_STDINT_H]) +m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_UNISTD_H]) +m4trace:configure.ac:112: -1- AC_DEFINE_TRACE_LITERAL([HAVE_CLIGEN_CLIGEN_H]) +m4trace:configure.ac:112: -1- m4_pattern_allow([^HAVE_CLIGEN_CLIGEN_H$]) +m4trace:configure.ac:118: -1- AH_OUTPUT([HAVE_DEPOT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_DEPOT_H]) +m4trace:configure.ac:118: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEPOT_H]) +m4trace:configure.ac:118: -1- m4_pattern_allow([^HAVE_DEPOT_H$]) +m4trace:configure.ac:118: -1- AH_OUTPUT([HAVE_QDBM_DEPOT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_QDBM_DEPOT_H]) +m4trace:configure.ac:118: -1- AC_DEFINE_TRACE_LITERAL([HAVE_QDBM_DEPOT_H]) +m4trace:configure.ac:118: -1- m4_pattern_allow([^HAVE_QDBM_DEPOT_H$]) +m4trace:configure.ac:119: -1- AH_OUTPUT([HAVE_LIBQDBM], [/* Define to 1 if you have the `qdbm\' library (-lqdbm). */ +@%:@undef HAVE_LIBQDBM]) +m4trace:configure.ac:119: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBQDBM]) +m4trace:configure.ac:119: -1- m4_pattern_allow([^HAVE_LIBQDBM$]) +m4trace:configure.ac:121: -1- AH_OUTPUT([HAVE_LIBCRYPT], [/* Define to 1 if you have the `crypt\' library (-lcrypt). */ +@%:@undef HAVE_LIBCRYPT]) +m4trace:configure.ac:121: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBCRYPT]) +m4trace:configure.ac:121: -1- m4_pattern_allow([^HAVE_LIBCRYPT$]) +m4trace:configure.ac:122: -1- AH_OUTPUT([HAVE_CRYPT_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_CRYPT_H]) +m4trace:configure.ac:122: -1- AC_DEFINE_TRACE_LITERAL([HAVE_CRYPT_H]) +m4trace:configure.ac:122: -1- m4_pattern_allow([^HAVE_CRYPT_H$]) +m4trace:configure.ac:125: -1- AH_OUTPUT([HAVE_SYS_UCRED_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_SYS_UCRED_H]) +m4trace:configure.ac:125: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SYS_UCRED_H]) +m4trace:configure.ac:125: -1- m4_pattern_allow([^HAVE_SYS_UCRED_H$]) +m4trace:configure.ac:130: -1- AH_OUTPUT([HAVE_LINUX_IF_VLAN_H], [/* Define to 1 if you have the header file. */ +@%:@undef HAVE_LINUX_IF_VLAN_H]) +m4trace:configure.ac:130: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LINUX_IF_VLAN_H]) +m4trace:configure.ac:130: -1- m4_pattern_allow([^HAVE_LINUX_IF_VLAN_H$]) +m4trace:configure.ac:132: -1- AH_OUTPUT([HAVE_LIBSOCKET], [/* Define to 1 if you have the `socket\' library (-lsocket). */ +@%:@undef HAVE_LIBSOCKET]) +m4trace:configure.ac:132: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSOCKET]) +m4trace:configure.ac:132: -1- m4_pattern_allow([^HAVE_LIBSOCKET$]) +m4trace:configure.ac:133: -1- AH_OUTPUT([HAVE_LIBNSL], [/* Define to 1 if you have the `nsl\' library (-lnsl). */ +@%:@undef HAVE_LIBNSL]) +m4trace:configure.ac:133: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBNSL]) +m4trace:configure.ac:133: -1- m4_pattern_allow([^HAVE_LIBNSL$]) +m4trace:configure.ac:134: -1- AH_OUTPUT([HAVE_LIBDL], [/* Define to 1 if you have the `dl\' library (-ldl). */ +@%:@undef HAVE_LIBDL]) +m4trace:configure.ac:134: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBDL]) +m4trace:configure.ac:134: -1- m4_pattern_allow([^HAVE_LIBDL$]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_INET_ATON], [/* Define to 1 if you have the `inet_aton\' function. */ +@%:@undef HAVE_INET_ATON]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_SIGACTION], [/* Define to 1 if you have the `sigaction\' function. */ +@%:@undef HAVE_SIGACTION]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_SIGVEC], [/* Define to 1 if you have the `sigvec\' function. */ +@%:@undef HAVE_SIGVEC]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_STRLCPY], [/* Define to 1 if you have the `strlcpy\' function. */ +@%:@undef HAVE_STRLCPY]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_STRSEP], [/* Define to 1 if you have the `strsep\' function. */ +@%:@undef HAVE_STRSEP]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_STRNDUP], [/* Define to 1 if you have the `strndup\' function. */ +@%:@undef HAVE_STRNDUP]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_ALPHASORT], [/* Define to 1 if you have the `alphasort\' function. */ +@%:@undef HAVE_ALPHASORT]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_VERSIONSORT], [/* Define to 1 if you have the `versionsort\' function. */ +@%:@undef HAVE_VERSIONSORT]) +m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_STRVERSCMP], [/* Define to 1 if you have the `strverscmp\' function. */ +@%:@undef HAVE_STRVERSCMP]) +m4trace:configure.ac:149: -1- AH_OUTPUT([DB_KEYCONTENT], [/* Check if extra keys inserted for database lists containing content. Eg + A.n.foo = 3 means A.3 @S|@!a=foo exists */ +@%:@undef DB_KEYCONTENT]) +m4trace:configure.ac:153: -1- AC_DEFINE_TRACE_LITERAL([DB_KEYCONTENT]) +m4trace:configure.ac:153: -1- m4_pattern_allow([^DB_KEYCONTENT$]) +m4trace:configure.ac:156: -1- AH_OUTPUT([zzzz1], [#include ]) +m4trace:configure.ac:158: -1- AC_CONFIG_FILES([Makefile + lib/Makefile + lib/src/Makefile + lib/clicon/Makefile + apps/Makefile + apps/cli/Makefile + apps/backend/Makefile + apps/netconf/Makefile + apps/dbctrl/Makefile + include/Makefile + etc/Makefile + etc/cliconrc + example/Makefile + doc/Makefile +]) +m4trace:configure.ac:158: -1- _m4_warn([obsolete], [AC_OUTPUT should be used without arguments. +You should run autoupdate.], []) +m4trace:configure.ac:158: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([LIB@&t@OBJS]) +m4trace:configure.ac:158: -1- m4_pattern_allow([^LIB@&t@OBJS$]) +m4trace:configure.ac:158: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([LTLIBOBJS]) +m4trace:configure.ac:158: -1- m4_pattern_allow([^LTLIBOBJS$]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([top_builddir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([top_build_prefix]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([srcdir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([abs_srcdir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([top_srcdir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([abs_top_srcdir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([builddir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([abs_builddir]) +m4trace:configure.ac:158: -1- AC_SUBST_TRACE([abs_top_builddir]) diff --git a/clicon.conf.cpp.cpp b/clicon.conf.cpp.cpp new file mode 100644 index 000000000..7afbf3f02 --- /dev/null +++ b/clicon.conf.cpp.cpp @@ -0,0 +1,124 @@ +# 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 +# . +# +# CLICON options - Default values +# The origin of this file is run a _first_ time through a pre-processor at +# clicon make install time causing autoconf constants (such as "prefix" and +# "localstatedir") to be replaced with their installed values. +# It should be run a _second_ time as a part of installation of the application, +# in case clicon.mk is included in the application include file, and +# "$(APPNAME).conf" rule is accessed. +# +# See clicon_tutorial for more documentation + +# Location of configuration-file for default values (this file) +CLICON_CONFIGFILE sysconfdir/APPNAME.conf + +# Database (yang) specification file. +CLICON_DBSPEC_FILE prefix/share/APPNAME/datamodel.spec + +# Location of YANG module and submodule files. Only if CLICON_DBSPEC_TYPE is YANG +CLICON_YANG_DIR prefix/share/APPNAME/yang + +# Option used to construct initial yang file: +# [@] +# This option is only relevant if CLICON_DBSPEC_TYPE is YANG +# CLICON_YANG_MODULE_MAIN clicon + +# Option used to construct initial yang file: +# [@] +# This option is only relevant if CLICON_DBSPEC_TYPE is YANG +CLICON_YANG_MODULE_REVISION + +# Candidate qdbm database +CLICON_CANDIDATE_DB localstatedir/APPNAME/candidate_db + +# Running qdbm database +CLICON_RUNNING_DB localstatedir/APPNAME/running_db + +# Location of backend .so plugins +CLICON_BACKEND_DIR libdir/APPNAME/backend + +# Location of netconf (frontend) .so plugins +CLICON_NETCONF_DIR libdir/APPNAME/netconf + +# Location of cli frontend .so plugins +CLICON_CLI_DIR libdir/APPNAME/cli + +# Location of frontend .cli cligen spec files +CLICON_CLISPEC_DIR libdir/APPNAME/clispec + +# Directory where to save configuration commit history (in XML). Snapshots +# are saved chronologically +CLICON_ARCHIVE_DIR localstatedir/APPNAME/archive + +# XXX Name of startup configuration file (in XML) +CLICON_STARTUP_CONFIG localstatedir/APPNAME/startup-config + +# Address family for communicating with clicon_backend (UNIX|IPv4|IPv6) +CLICON_SOCK_FAMILY UNIX + +# If family above is AF_UNIX: Unix socket for communicating with clicon_backend +# If family above is AF_INET: IPv4 address +CLICON_SOCK localstatedir/APPNAME/APPNAME.sock + +# Inet socket port for communicating with clicon_backend (only IPv4|IPv6) +CLICON_SOCK_PORT 4535 + +# Process-id file +CLICON_BACKEND_PIDFILE localstatedir/APPNAME/APPNAME.pidfile + +# Group membership to access clicon_config unix socket +# CLICON_SOCK_GROUP clicon + +# Set if all configuration changes are committed directly, commit command unnecessary +# CLICON_AUTOCOMMIT 0 + +# Clicon backend callback order. There are two dimensions: operation (del/add/change) +# and priority +# 0: all callbacks in (rising) priority order +# 1: first delete operations in declining prio order; then add/change in prio order +# 2: like (1) but CHANGE is replaced by (DEL;ADD) +# XXX OBSOLETE? +# CLICON_COMMIT_ORDER 0 + +# Name of master plugin (both frontend and backend). Master plugin has special +# callbacks for frontends. See clicon user manual for more info. +# CLICON_MASTER_PLUGIN master + +# Startup CLI mode. This should match the CLICON_MODE in your startup clispec file +# CLICON_CLI_MODE base + +# Generate code for CLI completion of existing db symbols. Add name="myspec" in +# datamodel spec and reference as @myspec. +# CLICON_CLI_GENMODEL 1 + +# Generate code for CLI completion of existing db symbols +# CLICON_CLI_GENMODEL_COMPLETION 0 + +# How to generate and show CLI syntax: VARS|ALL +# CLICON_CLI_GENMODEL_TYPE VARS + +# Comment character in CLI +# CLICON_CLI_COMMENT # + +# Dont include keys in cvec in cli vars callbacks, ie a & k in 'a k ' ignored +# CLICON_CLI_VARONLY 1 + + + diff --git a/clicon.mk.cpp b/clicon.mk.cpp new file mode 100644 index 000000000..c4a4ffff3 --- /dev/null +++ b/clicon.mk.cpp @@ -0,0 +1,44 @@ +# 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 +# . +# +# Include this file in your application Makefile using eg: +# -include $(datarootdir)/clicon/clicon.mk +# then you can use the DIRS below in your install rules. +# You also get rules for the application configure file. +# NOTE: APPNAME must be defined in the local Makefile + +clicon_DBSPECDIR=prefix/share/$(APPNAME) +clicon_SYSCONFDIR=sysconfdir +clicon_LOCALSTATEDIR=localstatedir/$(APPNAME) +clicon_LIBDIR=libdir/$(APPNAME) +clicon_DATADIR=datadir/clicon + +# Rules for the clicon application configuration file. +# The clicon applications should be started with this fileas its -f argument. +# Typically installed in sysconfdir +# Example: APPNAME=myapp --> clicon_cli -f /usr/local/etc/myapp.conf +# The two variants are if there is a .conf.local file or not +.PHONY: $(APPNAME).conf +ifneq (,$(wildcard ${APPNAME}.conf.local)) +${APPNAME}.conf: ${clicon_DATADIR}/clicon.conf.cpp ${APPNAME}.conf.local + $(CPP) -P -x assembler-with-cpp -DAPPNAME=$(APPNAME) $< > $@ + cat ${APPNAME}.conf.local >> $@ +else +${APPNAME}.conf: ${clicon_DATADIR}/clicon.conf.cpp + $(CPP) -P -x assembler-with-cpp -DAPPNAME=$(APPNAME) $< > $@ +endif diff --git a/config.guess b/config.guess new file mode 100644 index 000000000..2cee42819 --- /dev/null +++ b/config.guess @@ -0,0 +1,1550 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-08-14' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Detect uclibc systems. + +LIBC="gnu" +if [ -f /usr/include/bits/uClibc_config.h ] +then + LIBC=uclibc + if [ -n `grep "#define __UCLIBC_CONFIG_VERSION__" /usr/include/bits/uClibc_config.h` ] + then + UCLIBC_SUBVER=`sed -n "/#define __UCLIBC_CONFIG_VERSION__ /s///p" /usr/include/bits/uClibc_config.h` + LIBC=$LIBC$UCLIBC_SUBVER + fi +fi + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100644 index 000000000..b15df5751 --- /dev/null +++ b/config.sub @@ -0,0 +1,1786 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-07-31' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 000000000..60dc71bc5 --- /dev/null +++ b/configure @@ -0,0 +1,5482 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="lib/clicon/clicon.h.in" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +EGREP +GREP +LEXLIB +LEX_OUTPUT_ROOT +LEX +YFLAGS +YACC +CPP +OBJEXT +EXEEXT +ac_ct_CC +CLICON__LIBDIR +RANLIB +AR +EXE_SUFFIX +SH_SUFFIX +AR_SUFFIX +OBJ_SUFFIX +CPPFLAGS +INCLUDES +LDFLAGS +CFLAGS +CC +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +CLIGEN_VERSION +CLICON_VERSION_MINOR +CLICON_VERSION_MAJOR +CLICON_VERSION_STRING +CLICON_VERSION +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_keycontent +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +YACC +YFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-keycontent Disable reverse lookup content keys + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Default CFLAGS unless set by environment. +: ${CFLAGS="-O2"} + +CLICON_VERSION_MAJOR="3" +CLICON_VERSION_MINOR="2" +CLICON_VERSION_PATCH="0" +CLICON_VERSION="\"${CLICON_VERSION_MAJOR}.${CLICON_VERSION_MINOR}.${CLICON_VERSION_PATCH}\"" +# Fix to specific version (eg 3.5) or head (3) +CLIGEN_VERSION="3.5" + +ac_config_headers="$ac_config_headers include/clicon_config.h lib/clicon/clicon.h" + + +cat >>confdefs.h <<_ACEOF +#define CLICON_VERSION_STRING $CLICON_VERSION +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define CLICON_VERSION_MAJOR $CLICON_VERSION_MAJOR +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define CLICON_VERSION_MINOR $CLICON_VERSION_MINOR +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define CLICON_VERSION_PATCH $CLICON_VERSION_PATCH +_ACEOF + + +# clicon versions spread to Makefile's (.so files) and variable in build.c + + + + + # Bind to specific CLIgen version + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CLICON version is ${CLICON_VERSION}_PRE1" >&5 +$as_echo "CLICON version is ${CLICON_VERSION}_PRE1" >&6; } + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# 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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + + + + + + + + + + + + # Clicon application director. Eg /hello. + +# Some stuff installed in /usr/local/. Such as qdbm +LIBS="-L /usr/local/lib" + +# +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiler is $CC" >&5 +$as_echo "compiler is $CC" >&6; } + +CFLAGS="${CFLAGS} -Wall" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS is $CPPFLAGS" >&5 +$as_echo "CPPFLAGS is $CPPFLAGS" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS is $CFLAGS" >&5 +$as_echo "CFLAGS is $CFLAGS" >&6; } + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 +$as_echo "$LEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ + yyless ((input () != 0)); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ { ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 +$as_echo_n "checking lex output file root... " >&6; } +if ${ac_cv_prog_lex_root+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 +$as_echo "$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 +$as_echo_n "checking lex library... " >&6; } +if ${ac_cv_lib_lex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lex=$ac_lib +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 +$as_echo "$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 +$as_echo_n "checking whether yytext is a pointer... " >&6; } +if ${ac_cv_prog_lex_yytext_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_prog_lex_yytext_pointer=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 +$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi +if test "$LEX" = ":"; then + as_fn_error $? "CLICON does not find lex or flex." "$LINENO" 5 +fi +if test "$YACC" != "bison -y"; then + as_fn_error $? "CLICON does not find bison. There are several problems with yacc and byacc. Please install bison." "$LINENO" 5 +fi + +if test "$prefix" = "NONE"; then + CPPFLAGS="-I${ac_default_prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${ac_default_prefix}/lib ${LDFLAGS}" +else + CPPFLAGS="-I${prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${prefix}/lib ${LDFLAGS}" +fi + +LDFLAGS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 +$as_echo_n "checking for main in -lm... " >&6; } +if ${ac_cv_lib_m_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_main=yes +else + ac_cv_lib_m_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 +$as_echo "$ac_cv_lib_m_main" >&6; } +if test "x$ac_cv_lib_m_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +EXE_SUFFIX="" +OBJ_SUFFIX=".o" +AR_SUFFIX=".a" +SH_SUFFIX=".so" +AR="ar" + +# This is for cligen + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in cligen/cligen.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "cligen/cligen.h" "ac_cv_header_cligen_cligen_h" "$ac_includes_default" +if test "x$ac_cv_header_cligen_cligen_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLIGEN_CLIGEN_H 1 +_ACEOF + +else + as_fn_error $? "cligen missing. Try: git clone https://github.com/olofhagsand/cligen.git" "$LINENO" 5 +fi + +done + + +as_ac_Lib=`$as_echo "ac_cv_lib_:libcligen.so.${CLIGEN_VERSION}''_cligen_init" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cligen_init in -l:libcligen.so.${CLIGEN_VERSION}" >&5 +$as_echo_n "checking for cligen_init in -l:libcligen.so.${CLIGEN_VERSION}... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l:libcligen.so.${CLIGEN_VERSION} $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cligen_init (); +int +main () +{ +return cligen_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_LIB:libcligen.so.${CLIGEN_VERSION}" | $as_tr_cpp` 1 +_ACEOF + + LIBS="-l:libcligen.so.${CLIGEN_VERSION} $LIBS" + +else + as_fn_error $? "CLIgen${CLIGEN_VERSION} missing. Try: git clone https://github.com/olofhagsand/cligen.git" "$LINENO" 5 +fi + + +# This is for qdbm. +# Problem: depot.h may be in qdbm/depot.h. +for ac_header in depot.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "depot.h" "ac_cv_header_depot_h" "$ac_includes_default" +if test "x$ac_cv_header_depot_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DEPOT_H 1 +_ACEOF + +else + for ac_header in qdbm/depot.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "qdbm/depot.h" "ac_cv_header_qdbm_depot_h" "$ac_includes_default" +if test "x$ac_cv_header_qdbm_depot_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_QDBM_DEPOT_H 1 +_ACEOF + +else + as_fn_error $? "libqdbm-dev required" "$LINENO" 5 +fi + +done + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dpopen in -lqdbm" >&5 +$as_echo_n "checking for dpopen in -lqdbm... " >&6; } +if ${ac_cv_lib_qdbm_dpopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lqdbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dpopen (); +int +main () +{ +return dpopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_qdbm_dpopen=yes +else + ac_cv_lib_qdbm_dpopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_dpopen" >&5 +$as_echo "$ac_cv_lib_qdbm_dpopen" >&6; } +if test "x$ac_cv_lib_qdbm_dpopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBQDBM 1 +_ACEOF + + LIBS="-lqdbm $LIBS" + +else + as_fn_error $? "libqdbm-dev required" "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5 +$as_echo_n "checking for crypt in -lcrypt... " >&6; } +if ${ac_cv_lib_crypt_crypt+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypt_crypt=yes +else + ac_cv_lib_crypt_crypt=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5 +$as_echo "$ac_cv_lib_crypt_crypt" >&6; } +if test "x$ac_cv_lib_crypt_crypt" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPT 1 +_ACEOF + + LIBS="-lcrypt $LIBS" + +fi + +for ac_header in crypt.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "crypt.h" "ac_cv_header_crypt_h" "$ac_includes_default" +if test "x$ac_cv_header_crypt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CRYPT_H 1 +_ACEOF + +fi + +done + + +# user credentials for unix sockets +for ac_header in sys/ucred.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/ucred.h" "ac_cv_header_sys_ucred_h" "# include + +" +if test "x$ac_cv_header_sys_ucred_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UCRED_H 1 +_ACEOF + +fi + +done + + +# This is for Linux vlan code +for ac_header in linux/if_vlan.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linux/if_vlan.h" "ac_cv_header_linux_if_vlan_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_if_vlan_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_IF_VLAN_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +$as_echo_n "checking for socket in -lsocket... " >&6; } +if ${ac_cv_lib_socket_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_socket=yes +else + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +$as_echo "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for xdr_char in -lnsl" >&5 +$as_echo_n "checking for xdr_char in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_xdr_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xdr_char (); +int +main () +{ +return xdr_char (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_xdr_char=yes +else + ac_cv_lib_nsl_xdr_char=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_xdr_char" >&5 +$as_echo "$ac_cv_lib_nsl_xdr_char" >&6; } +if test "x$ac_cv_lib_nsl_xdr_char" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + + +for ac_func in inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Check if extra keys inserted for database lists containing content. Eg A.n.foo = 3 +# means A.3 $!a=foo exists + +# Check whether --enable-keycontent was given. +if test "${enable_keycontent+set}" = set; then : + enableval=$enable_keycontent; + if test "$enableval" = no; then + ac_enable_keycontent=no + else + ac_enable_keycontent=yes + fi + +else + ac_enable_keycontent=yes +fi + + + +if test "$ac_enable_keycontent" = "yes"; then + $as_echo "#define DB_KEYCONTENT 1" >>confdefs.h + +fi + + + +ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clicon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/dbctrl/Makefile include/Makefile etc/Makefile etc/cliconrc example/Makefile doc/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/clicon_config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/clicon_config.h" ;; + "lib/clicon/clicon.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/clicon/clicon.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "lib/src/Makefile") CONFIG_FILES="$CONFIG_FILES lib/src/Makefile" ;; + "lib/clicon/Makefile") CONFIG_FILES="$CONFIG_FILES lib/clicon/Makefile" ;; + "apps/Makefile") CONFIG_FILES="$CONFIG_FILES apps/Makefile" ;; + "apps/cli/Makefile") CONFIG_FILES="$CONFIG_FILES apps/cli/Makefile" ;; + "apps/backend/Makefile") CONFIG_FILES="$CONFIG_FILES apps/backend/Makefile" ;; + "apps/netconf/Makefile") CONFIG_FILES="$CONFIG_FILES apps/netconf/Makefile" ;; + "apps/dbctrl/Makefile") CONFIG_FILES="$CONFIG_FILES apps/dbctrl/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "etc/Makefile") CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;; + "etc/cliconrc") CONFIG_FILES="$CONFIG_FILES etc/cliconrc" ;; + "example/Makefile") CONFIG_FILES="$CONFIG_FILES example/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..d4ebcea65 --- /dev/null +++ b/configure.ac @@ -0,0 +1,173 @@ +# To rebuild the `configure' script from this, execute the command +# autoconf +# in the directory containing this script. +# +# +# 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 +# . +# +# + +AC_INIT(lib/clicon/clicon.h.in) + +# Default CFLAGS unless set by environment. +: ${CFLAGS="-O2"} + +CLICON_VERSION_MAJOR="3" +CLICON_VERSION_MINOR="2" +CLICON_VERSION_PATCH="0" +CLICON_VERSION="\"${CLICON_VERSION_MAJOR}.${CLICON_VERSION_MINOR}.${CLICON_VERSION_PATCH}\"" +# Fix to specific version (eg 3.5) or head (3) +CLIGEN_VERSION="3.5" + +AC_CONFIG_HEADERS([include/clicon_config.h lib/clicon/clicon.h]) + +AC_DEFINE_UNQUOTED(CLICON_VERSION_STRING, $CLICON_VERSION) +AC_DEFINE_UNQUOTED(CLICON_VERSION_MAJOR, $CLICON_VERSION_MAJOR) +AC_DEFINE_UNQUOTED(CLICON_VERSION_MINOR, $CLICON_VERSION_MINOR) +AC_DEFINE_UNQUOTED(CLICON_VERSION_PATCH, $CLICON_VERSION_PATCH) + +# clicon versions spread to Makefile's (.so files) and variable in build.c +AC_SUBST(CLICON_VERSION) +AC_SUBST(CLICON_VERSION_STRING) +AC_SUBST(CLICON_VERSION_MAJOR) +AC_SUBST(CLICON_VERSION_MINOR) +AC_SUBST(CLIGEN_VERSION) # Bind to specific CLIgen version + + +AC_MSG_RESULT(CLICON version is ${CLICON_VERSION}_PRE1) + +AC_CANONICAL_TARGET +AC_SUBST(CC) +AC_SUBST(CFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(INCLUDES) +AC_SUBST(CPPFLAGS) +AC_SUBST(LIBS) +AC_SUBST(OBJ_SUFFIX) +AC_SUBST(AR_SUFFIX) +AC_SUBST(SH_SUFFIX) +AC_SUBST(EXE_SUFFIX) +AC_SUBST(AR) +AC_SUBST(RANLIB) +AC_SUBST(CLICON__LIBDIR) # Clicon application director. Eg /hello. + +# Some stuff installed in /usr/local/. Such as qdbm +LIBS="-L /usr/local/lib" + +# +AC_PROG_CC() +AC_PROG_CPP + +CPPFLAGS="-DHAVE_CONFIG_H ${CPPFLAGS}" + +AC_MSG_RESULT(compiler is $CC) + +CFLAGS="${CFLAGS} -Wall" + +AC_MSG_RESULT(CPPFLAGS is $CPPFLAGS) +AC_MSG_RESULT(CFLAGS is $CFLAGS) + +AC_PROG_YACC +AC_PROG_LEX +if test "$LEX" = ":"; then + AC_MSG_ERROR(CLICON does not find lex or flex.) +fi +if test "$YACC" != "bison -y"; then + AC_MSG_ERROR(CLICON does not find bison. There are several problems with yacc and byacc. Please install bison.) +fi + +if test "$prefix" = "NONE"; then + CPPFLAGS="-I${ac_default_prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${ac_default_prefix}/lib ${LDFLAGS}" +else + CPPFLAGS="-I${prefix}/include ${CPPFLAGS}" + LDFLAGS="-L${prefix}/lib ${LDFLAGS}" +fi + +LDFLAGS="" +AC_CHECK_LIB(m, main) +EXE_SUFFIX="" +OBJ_SUFFIX=".o" +AR_SUFFIX=".a" +SH_SUFFIX=".so" +AR="ar" + +# This is for cligen +AC_CHECK_HEADERS(cligen/cligen.h,, AC_MSG_ERROR(cligen missing. Try: git clone https://github.com/olofhagsand/cligen.git)) + +AC_CHECK_LIB(:libcligen.so.${CLIGEN_VERSION}, cligen_init,, AC_MSG_ERROR([CLIgen${CLIGEN_VERSION} missing. Try: git clone https://github.com/olofhagsand/cligen.git])) + +# This is for qdbm. +# Problem: depot.h may be in qdbm/depot.h. +AC_CHECK_HEADERS(depot.h,,[AC_CHECK_HEADERS(qdbm/depot.h,,AC_MSG_ERROR(libqdbm-dev required))]) +AC_CHECK_LIB(qdbm, dpopen,, AC_MSG_ERROR(libqdbm-dev required)) + +AC_CHECK_LIB(crypt, crypt) +AC_CHECK_HEADERS(crypt.h) + +# user credentials for unix sockets +AC_CHECK_HEADERS([sys/ucred.h],[],[], + [[# include ]] +) + +# This is for Linux vlan code +AC_CHECK_HEADERS(linux/if_vlan.h) + +AC_CHECK_LIB(socket, socket) +AC_CHECK_LIB(nsl, xdr_char) +AC_CHECK_LIB(dl, dlopen) + +AC_CHECK_FUNCS(inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp) + +# Check if extra keys inserted for database lists containing content. Eg A.n.foo = 3 +# means A.3 $!a=foo exists + +AC_ARG_ENABLE(keycontent, [ --disable-keycontent Disable reverse lookup content keys],[ + if test "$enableval" = no; then + ac_enable_keycontent=no + else + ac_enable_keycontent=yes + fi + ],[ ac_enable_keycontent=yes]) + +AH_TEMPLATE([DB_KEYCONTENT], +[ Check if extra keys inserted for database lists containing content. + Eg A.n.foo = 3 means A.3 $!a=foo exists]) +if test "$ac_enable_keycontent" = "yes"; then + AC_DEFINE(DB_KEYCONTENT) +fi + +AH_BOTTOM([#include ]) + +AC_OUTPUT(Makefile + lib/Makefile + lib/src/Makefile + lib/clicon/Makefile + apps/Makefile + apps/cli/Makefile + apps/backend/Makefile + apps/netconf/Makefile + apps/dbctrl/Makefile + include/Makefile + etc/Makefile + etc/cliconrc + example/Makefile + doc/Makefile +) + diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 000000000..bb9f98ca2 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,2303 @@ +# Doxyfile 1.8.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "CLICON" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../lib/src/ ../lib/clicon/ ../apps/cli/ ../apps/config/ ../apps/netconf ../apps/dbctrl + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c *.y *.l *.h + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /