diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..e9121e26 --- /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 00000000..ae47ce6c --- /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 00000000..c4c6ac72 --- /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 00000000..86a25e7b --- /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 00000000..16593630 --- /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 00000000..9ad563b4 --- /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 00000000..472628ef --- /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 00000000..c33d0b20 --- /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 00000000..aea109d1 --- /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 00000000..4eada539 --- /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 00000000..4a6ca209 --- /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 00000000..d8b0524d --- /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 00000000..1e7ffe25 --- /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 00000000..bee87133 --- /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 00000000..8a33bbb4 --- /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 00000000..fa5c604f --- /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 00000000..a399ceec --- /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 00000000..e06743a3 --- /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 00000000..f7707b4b --- /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 00000000..5de10cbd --- /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 00000000..1af58ba8 --- /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 00000000..c49f1532 --- /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 00000000..c12f86f5 --- /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 00000000..f760d50f --- /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 00000000..7f2461a3 --- /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 00000000..1466662a --- /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 00000000..3075b019 Binary files /dev/null and b/apps/backend/clicon_transaction_api.o differ diff --git a/apps/cli/Makefile.in b/apps/cli/Makefile.in new file mode 100644 index 00000000..4e54b7c7 --- /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 00000000..fc72b346 --- /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 00000000..f047b1c2 --- /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 00000000..245b9563 --- /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 00000000..64665fe7 --- /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 00000000..f89a3b44 --- /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 00000000..be485acb --- /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 00000000..241385d4 --- /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 00000000..0a57b69f --- /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 00000000..9517bfca --- /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 00000000..39e10ec8 --- /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 00000000..d7600415 --- /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 00000000..25d264a5 --- /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 00000000..a88a322f --- /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 00000000..dfa1f189 --- /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 00000000..d24d3455 --- /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 00000000..5f129e04 --- /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 00000000..8cc8f0d5 --- /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 00000000..f6a0275e --- /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 00000000..e26296f0 --- /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 00000000..0059c316 --- /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 00000000..61640d4c --- /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 00000000..9b08eb9a --- /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 00000000..cd9770e3 --- /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 00000000..272e7f14 --- /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 00000000..b00be129 --- /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 00000000..53a5b796 --- /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 00000000..a4d6361f --- /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 00000000..8da21f8c --- /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 00000000..942fb32f --- /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 00000000..7afbf3f0 --- /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 00000000..c4a4ffff --- /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 00000000..2cee4281 --- /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 00000000..b15df575 --- /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 00000000..60dc71bc --- /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 00000000..d4ebcea6 --- /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 00000000..bb9f98ca --- /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 +# , /