]> granicus.if.org Git - pdns/commitdiff
Initial revision
authorBert Hubert <bert.hubert@netherlabs.nl>
Wed, 27 Nov 2002 15:18:23 +0000 (15:18 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Wed, 27 Nov 2002 15:18:23 +0000 (15:18 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2 d19b8d6e-7fed-0310-83ef-9ca221ded41b

139 files changed:
pdns/COPYING [new file with mode: 0644]
pdns/ChangeLog [new file with mode: 0644]
pdns/INSTALL [new file with mode: 0644]
pdns/LICENSE [new file with mode: 0644]
pdns/Makefile.am [new file with mode: 0644]
pdns/Makefile.in [new file with mode: 0644]
pdns/README [new file with mode: 0644]
pdns/TODO [new file with mode: 0644]
pdns/acconfig.h [new file with mode: 0644]
pdns/aclocal.m4 [new file with mode: 0644]
pdns/ahuexception.hh [new file with mode: 0644]
pdns/arguments.cc [new file with mode: 0644]
pdns/arguments.hh [new file with mode: 0644]
pdns/backends/Makefile.am [new file with mode: 0644]
pdns/backends/Makefile.in [new file with mode: 0644]
pdns/backends/bind/Makefile.am [new file with mode: 0644]
pdns/backends/bind/Makefile.in [new file with mode: 0644]
pdns/backends/bind/TODO [new file with mode: 0644]
pdns/backends/bind/bindbackend.cc [new file with mode: 0644]
pdns/backends/bind/bindbackend.hh [new file with mode: 0644]
pdns/backends/bind/bindlexer.c [new file with mode: 0644]
pdns/backends/bind/bindlexer.l [new file with mode: 0644]
pdns/backends/bind/bindparser.cc [new file with mode: 0644]
pdns/backends/bind/bindparser.h [new file with mode: 0644]
pdns/backends/bind/bindparser.hh [new file with mode: 0644]
pdns/backends/bind/bindparser.yy [new file with mode: 0644]
pdns/backends/bind/huffman.cc [new file with mode: 0644]
pdns/backends/bind/huffman.hh [new file with mode: 0644]
pdns/backends/bind/ylwrap [new file with mode: 0755]
pdns/backends/bind/zone2sql.cc [new file with mode: 0644]
pdns/backends/bind/zoneparser.hh [new file with mode: 0644]
pdns/backends/bind/zoneparser2.cc [new file with mode: 0644]
pdns/binpatch.cc [new file with mode: 0644]
pdns/bootstrap [new file with mode: 0755]
pdns/buildroot.sh.in [new file with mode: 0755]
pdns/choosepaths [new file with mode: 0755]
pdns/codedocs/Makefile [new file with mode: 0644]
pdns/codedocs/Makefile.am [new file with mode: 0644]
pdns/codedocs/Makefile.in [new file with mode: 0644]
pdns/codedocs/doxygen.conf [new file with mode: 0644]
pdns/common_startup.cc [new file with mode: 0644]
pdns/common_startup.hh [new file with mode: 0644]
pdns/communicator.cc [new file with mode: 0644]
pdns/communicator.hh [new file with mode: 0644]
pdns/config.guess [new file with mode: 0755]
pdns/config.h.in [new file with mode: 0644]
pdns/config.sub [new file with mode: 0755]
pdns/configure [new file with mode: 0755]
pdns/configure.in [new file with mode: 0644]
pdns/debian/changelog [new file with mode: 0644]
pdns/debian/conffiles [new file with mode: 0644]
pdns/debian/control [new file with mode: 0644]
pdns/debian/postinst [new file with mode: 0644]
pdns/debian/postrm [new file with mode: 0644]
pdns/debian/preinst [new file with mode: 0644]
pdns/debian/prerm [new file with mode: 0644]
pdns/debian/rules [new file with mode: 0755]
pdns/depcomp [new file with mode: 0755]
pdns/distributor.hh [new file with mode: 0644]
pdns/dns.hh [new file with mode: 0644]
pdns/dnsbackend.cc [new file with mode: 0644]
pdns/dnsbackend.hh [new file with mode: 0644]
pdns/dnspacket.cc [new file with mode: 0644]
pdns/dnspacket.hh [new file with mode: 0644]
pdns/dnsproxy.cc [new file with mode: 0644]
pdns/dnsproxy.hh [new file with mode: 0644]
pdns/docs/Makefile [new file with mode: 0644]
pdns/docs/gslb-operations.sgml [new file with mode: 0644]
pdns/docs/pdns.sgml [new file with mode: 0644]
pdns/docs/powerdns-case.sgml [new file with mode: 0644]
pdns/docs/powerdns-install.sgml [new file with mode: 0644]
pdns/docs/powerdns-overview.sgml [new file with mode: 0644]
pdns/docs/powerdns-technical.sgml [new file with mode: 0644]
pdns/dynhandler.cc [new file with mode: 0644]
pdns/dynhandler.hh [new file with mode: 0644]
pdns/dynlistener.cc [new file with mode: 0644]
pdns/dynlistener.hh [new file with mode: 0644]
pdns/dynloader.cc [new file with mode: 0644]
pdns/dynmessenger.cc [new file with mode: 0644]
pdns/dynmessenger.hh [new file with mode: 0644]
pdns/extra/Makefile [new file with mode: 0644]
pdns/extra/null.c [new file with mode: 0644]
pdns/install-sh [new file with mode: 0755]
pdns/installer [new file with mode: 0755]
pdns/iputils.hh [new file with mode: 0644]
pdns/lock.hh [new file with mode: 0644]
pdns/logger.cc [new file with mode: 0644]
pdns/logger.hh [new file with mode: 0644]
pdns/ltmain.sh [new file with mode: 0644]
pdns/misc.cc [new file with mode: 0644]
pdns/misc.hh [new file with mode: 0644]
pdns/missing [new file with mode: 0755]
pdns/mkbindist.in [new file with mode: 0755]
pdns/mkinstalldirs [new file with mode: 0755]
pdns/mtasker.cc [new file with mode: 0644]
pdns/nameserver.cc [new file with mode: 0644]
pdns/nameserver.hh [new file with mode: 0644]
pdns/packetcache.cc [new file with mode: 0644]
pdns/packetcache.hh [new file with mode: 0644]
pdns/packethandler.cc [new file with mode: 0644]
pdns/packethandler.hh [new file with mode: 0644]
pdns/pathconfig [new file with mode: 0644]
pdns/pathconfig.bsd [new file with mode: 0644]
pdns/pathconfig.debian [new file with mode: 0644]
pdns/pathconfig.redhat [new file with mode: 0644]
pdns/pdns.conf-dist [new file with mode: 0644]
pdns/pdns.conf-dist.in [new file with mode: 0644]
pdns/pdns.in [new file with mode: 0755]
pdns/pdns.spec [new file with mode: 0644]
pdns/qtype.cc [new file with mode: 0644]
pdns/qtype.hh [new file with mode: 0644]
pdns/randombackend.cc [new file with mode: 0644]
pdns/receiver.cc [new file with mode: 0644]
pdns/release-scripts/ld [new file with mode: 0644]
pdns/release-scripts/make-freebsd-static [new file with mode: 0644]
pdns/release-scripts/make-linux-dynamics [new file with mode: 0755]
pdns/release-scripts/make-linux-oracle-static [new file with mode: 0644]
pdns/release-scripts/make-linux-static [new file with mode: 0644]
pdns/release-scripts/make-linux-statics [new file with mode: 0755]
pdns/release-scripts/make-linux-statics-3.2 [new file with mode: 0755]
pdns/resolver.cc [new file with mode: 0644]
pdns/resolver.hh [new file with mode: 0644]
pdns/session.cc [new file with mode: 0644]
pdns/session.hh [new file with mode: 0644]
pdns/showvar.in [new file with mode: 0755]
pdns/stamp-h.in [new file with mode: 0644]
pdns/statbag.cc [new file with mode: 0644]
pdns/statbag.hh [new file with mode: 0644]
pdns/tcpreceiver.cc [new file with mode: 0644]
pdns/tcpreceiver.hh [new file with mode: 0644]
pdns/ueberbackend.cc [new file with mode: 0644]
pdns/ueberbackend.hh [new file with mode: 0644]
pdns/unix_utility.cc [new file with mode: 0644]
pdns/utility.hh [new file with mode: 0644]
pdns/webserver.cc [new file with mode: 0644]
pdns/webserver.hh [new file with mode: 0644]
pdns/ws.cc [new file with mode: 0644]
pdns/ws.hh [new file with mode: 0644]
pdns/ylwrap [new file with mode: 0755]

diff --git a/pdns/COPYING b/pdns/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  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.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/pdns/ChangeLog b/pdns/ChangeLog
new file mode 100644 (file)
index 0000000..617f554
--- /dev/null
@@ -0,0 +1,355 @@
+Changes sinds 2.8:
+       - license
+       - cleanups from Erik Bos @ xs4all
+       - build improvements from Wichert Akkerman
+       - open sourcing 
+
+changes since 2.7.1:
+       - pipe backend now has 'pipe-regex'
+       - pipe backend honours query-logging
+       - axfr timeout could cause crashes when transferring  zone from
+         master
+       - improved pipebackend documentation
+
+changes since 2.6.1:
+       - controlsocket now owned by the setgid gid
+       - SOA could have the wrong TTL leading to double 
+         records on ANY queries ("Jonas Daugaard" <jonas@cube.dk>)
+       - compression could suddenly be off Jonas Daugaard" <jonas@cube.dk>
+       - added --mysql-table (Ian Newlands)
+       - ranges work again (in allow-axfr-ips) (florus both)
+       - pipebackend now has pipe-timeout feature (Steve Bromwich)
+       - killed backends should respawn again (Steve Bromwich)
+       - backtrace feature under Linux
+       - corrupt packet error during axfr with secondary should not take
+          down pdns (Mike+Simon)
+       - >256 bytes compressed packet offsets did not function (Mike+Simon)
+
+
+changes since 2.6:
+       - repaired packetcache
+
+Changes since 2.5.1:
+       - removed 'unknown' packets from PacketCache
+       - improved packet accounting so counters match up better
+       - created ability to run with cache-ttl=0 and query-cache-ttl=0 
+         and negquery-cache-ttl=0
+       - fixed silly bug with SOA cache with escaped dots
+       - performance increases
+       - @ hack in NS records for additional processing
+       - only-soa feature
+       - fixed very bad latency calculation error
+       - now start out with an ANY query to catch CNAMEs and possibly first-level-NS
+       - added 'cricket' to init.d script
+       - made cache quicker
+       - zone2sql now again can read Verisign generated COM/NET/ORG zones
+         $TTL in the middle of a record
+       - fixed bug with \ escaping in records that were cached
+       
+Changes since 2.5:
+       - added RFC optional negative caching
+       - small speedup in non-packet-cached queries
+       - fixed huge memory leak in query cache
+       - added cache counts
+
+Changes since 2.4:
+enhance        - packetcache is now case-insensitive
+               but does give correct case answers
+enhance        - packetcache is now way more memory efficient
+               reengineered dnspacket
+               just stores a string
+bug    - packetcache could change the 'rd' bit of queries
+bug    - resolver would waste heaps of fd's
+bug    - resolver would not log tcp allocation error
+bug    - resolver would try to bind to priviliged ports
+bug    - AXFR from masters had case sensitivity issues
+enhance        - further improved some AXFR error wording
+               (all AXFR errors now contain the word AXFR)
+feature        - flags can now also be specified as 'off' to turn them off, instead
+         of only as 'no'
+enhance        - packetcache is now less lock-happy and a lot more complicated
+feature        - database queries with no or one response are now also cached 
+         in the packet cache
+enhance        - log-dns-details
+         turn off for more performance
+       
+Changes since 2.3:
+       - improved logging in DNS recursing proxy
+       - fixed crasher bug in compressed label parser
+       - added query-logging flag
+       - added ability to change some runtime flags
+       - added unified gmysql/gpgsql2 driver
+       - packetcache now also caches recursive queries
+               live in separate namespace
+       - added 'peak queries/second'
+       - more graceful death in case of master/slave communicator
+               database lack
+
+Changes since 2.2:
+       - improved error messages in master/slave communicator
+       - added slave-cycle-interval setting
+       - fixed SIGPIPE errors in communicator
+       - added additional check for SOA in ANY query (DENIC)
+       - pdns_control purge was broken badly
+       - master/slave communicator could get confused by delayed answers
+          from slow masters when operating as a slave.
+
+Changes since 2.1:
+       - wildcard CNAMEs!
+       - tcpreceiver sometimes would fall over a recursing packet that was
+          too short or malformed :-( (signal6)
+       - tcpreceived could wait far too long for response from remote
+          recursor
+       - cache-purge purged too much (Simon Kirby)
+       - cache-purge can now purge suffixes (Mike Benoit)
+       - some exceptions may not have been caught (tcp receiver connection
+         thread, dnsproxy)
+       - EOF on talking to TCP recursing backend would cause signal 6
+       - added soa-serial-offset to placate DENIC (again)
+
+Changes since 2.0.1:
+       - added --transactions to zone2sql
+       - there is now an option for wildcard fancy urls
+       - --lazy-recursion
+bug    - configuration files aren't overwritten by the rpm
+bug    - embarrassing bug in tcp recursion proxy (byteorder related)
+bug    - tcp proxy neglected to honor port setting
+       - added 'pdns_control purge'
+       - improved Oracle backend documentation and support
+
+Changes since 2.0:
+       - fixed PDNS ignoring logging-facility in commandline, thanks to
+               Karl from WebMachine
+       - added --slave to zone2sql
+       - improved @ escaping in SOA hostmaster
+
+Changes since 2.0rc2:
+       - fixed zone2sql hang
+       - fixed pointer arithmetic problem in packetparser
+       
+Changes since 2.0rc1:
+  - (WIN32) added a NTLog urgency to the logging class to avoid spamming the NT log.
+  - (WIN32) ported zone2sql and added it to the installation.
+  - (WIN32) ditched the Utility::Signal class.
+  - fixed chroot 
+  - fixed setuid/setgid
+  - fixed >256 MX prios Jeff Crowe
+  - fixed ipv6 recursor forwarding (handy ipv6 enabler too!)
+  - fixed bogus notification reception code
+  - fixed AXFR code bug for 'many packets' format with no question in later
+    packets
+
+Changes since 1.99.12:
+       - now lowercase $ORIGIN too for postgresql
+       - strip trailing dot on $ORIGIN
+       - relative paths in named.conf include statements now work as in bind (Jeff Miller)
+       - relative paths in zone $include statements now work as in bind (Jeff Miller)
+       - fixed nasty crasher bug in mysqlbackend with . zone serving
+       
+  - (WIN32) now reads the pdns.conf file if available.
+  - (WIN32) when running as a regular console app you can now shut it down using ctrl+c etc.
+  - (WIN32) installer now creates a default pdns.conf if none available.
+  - (WIN32) bug fixed where uninstaller wouldn't remove all files that had to be removed.
+  - (WIN32) dll's are now installed locally (in the same dir as the pdns executable).
+  - (WIN32) pdns_control is now added to the distribution.
+  - (WIN32) pdns responds to pdns_control commands correctly.
+  - (WIN32) added experimental master/slave support to the ODBC backend.
+  - (WIN32) fixed a bug in the database structure of the example zone.
+  - (WIN32) inserted a new (smaller) example zone.
+  - (WIN32) lots of small cleanups and fixes.
+
+Changes since 1.99.11:
+       - start of w2k merge
+       - zone2sql now understands $INCLUDE
+       - added --soa-minimum-ttl for DENIC compliance
+       - fixed bug in init.d scripts when virtual hosting
+       - added limit on number of simultaneous TCP connections
+       - added db2 backend
+       - case sensitivity issues fixed
+       - zone2sql now lowercases postgresql
+       - pdns_control now puts local socket in /tmp
+       
+       
+Changes since 1.99.10:
+       - now understand postfix ttl multipliers in zones outside of SOA
+       - no longer get confused by whitespace only lines after regular lines
+       - getRemote() method added for open source backend development kit
+
+Changes since 1.99.9:
+features:
+        - log-failed-updates
+       - facility logging
+       - work on master
+               now drills a hole for AXFR
+       - can now launch without ipv4 
+       - also-notify support in backend
+       - added TCPv6, which works too
+       - more bsd-like default directories for freebsd
+       - zone2sql now groks 'domains' table
+       
+bugs:
+       - fixed wildcard 'no data' error bug
+       - only not cache rd packets if doing recursion
+       - if a backend falls over, properly launch a new one
+       - ipv6 now actually works :-)
+       
+
+
+Changes since 1.99.8:
+features:
+       - added IPv6 parsing for slave AXFR
+       - added IPv6 listener
+       - made AXFR pull reject out of zone data 
+       - supermaster
+       - recursor can also live on another port now
+       - improved slave transferring semantics (scales better)
+       
+bugs:
+       - pdns sometimes sent a duplicate answer when operating with a
+         recursing backend
+       - don't send out servfail on out of bailiwick CNAME traversal
+       - made zone2sql/bindparser resilient for ^Z
+       - pgsqlbackend no longer prints out connect string
+       - pgsqlbackend depended on wrong .so in debian unstable link (thanks Wojas)
+       - fix respawn of database connection in case of fatal error
+       
+internal:
+       - changed SOA generation infrastructure
+       - improved internal backend API
+       - bindbackend passes regression test
+
+       
+Changes since 1.99.7:
+       - simplified bindbackend, potentially resolving crashes observed
+       - fixed SOA data
+       - fixed SOA chopping for finding recursion
+       - added NAPTR
+       - documented all records encoded
+       - duplicate delete call in magical SOA id calculation
+       - servfail on question for unknown domain
+       - allow-axfr-ips now also does netmasks
+       - disabled rapid additional spawning of new backends on launch
+       - slight delay between spawning of processes to prevent overload in backends (mysql)
+
+       - added slave support
+       - added recursion
+         + acl
+          no longer caching recursive queries
+
+       - fixed potential tcp and AXFR segmentation fault
+       
+Changes since 1.99.6:
+features:
+       - improved error reporting when parsing named.confs
+               (better line number counting)
+       - added --no-config
+       - added --bare to zone2sql
+       - added --gpgsql to zone2sql
+       - documented zone2sql
+
+bugs:
+       - many more named.confs can now be parsed - we now allow _ in
+          filenames
+       - freebsd version now stops/starts as it should
+       - wildcards were off by default
+       - --oracle did not function in zone2sql
+
+Changes since 1.99.5:
+features:
+       - added --webserver-print-arguments (defaults to no)
+       - added gpgsqlbackend
+       - fixed bind example zones
+bugs:
+       - fixed webserver listing of log messages
+       - fixed bad tcp question counting
+       - fixed bad tcp answer counter name
+       - fixed packetcache to detect clock skew
+       - improved flex error message
+       - accept : as part of filenames
+       
+Changes since 1.99.4:
+bugs:
+       - zone2sql no longer crashes on named.confs with less than 100 domains
+       - in case of huffman encoding error, print offending character
+       - fixed memory leaks big enough to drive a truck through
+       - removed yet more fd leaks in guardian
+       - made pipebackend less chatty
+       - daemon now closes filedescriptors 0, 1 & 2
+       
+performance:
+       - improved TCP dns code 
+               now only creates backend connection for AXFR
+               has timeouts
+
+features:
+       - made it possible to disable checks on ctime in bindbackend
+       - added --list-modules
+       
+Changes since 1.99.3:
+bugs:
+       - make sure zone compression is ON by default (heisenbug)
+       - fixed lack of exception catching in tcpreceiver
+       - made sure mysqlbackend closes its database connection
+       - learned bindparser about ip addresses which are not filenames
+       - fix truncation bug (don't truncate stuff in the cache)
+
+features:
+       - learned zone2sql about $GENERATE
+       - added --on-error-resume-next to zone2sql
+       - grok '@' in RHS of zonestatements
+       - catch dns updates & dns notifies, send out NOTIMP
+       - give zone2sql a default ttl
+       
+performance:
+       - don't search for fancy records on ANY if not wanted
+
+Changes since 1.99.2:
+       - made bindparser case insensitive
+       - fixed AXFR rcodes for disallowed or unauth zones
+       - fixed fd leak when relaunching a child
+       - fixed zone2sql lack of fclose() 
+       - make --help accept a prefix parameter
+       - added --zone-name to zone2sql
+       - added --disable-axfr (untested!)
+       - added --alow-axfr-ips
+       - rewrote zonefile parser
+       - enabled direct zoneparsing by pdns
+               9500 zones in 3.5 seconds
+       - fixed zonetransfers bugs (we died on axfr connection reset by peer)
+       - implemented rfc-breaking axfr dump speedup
+       - fixed webserver crash
+
+Changes since 1.99.1:
+
+       - fixed uid/gid confusal
+       - fixed module backend restarting code 
+       - bummed off 3 syscalls 
+       - removed lot of unnecessary gettimeofday calls
+       - fixed buffer overrun in local socket binding
+       - do not parse configuration when outputting configuration 
+               (when reinstalling)
+       
+
+
+1.4.1
+       - added a webserver
+       - integrated safe_ahudns functionality
+       - improved ahudns.init.d, added to default install
+       - made socketdir configurable
+       - Fixed smtpredir 'black hole' forwarding behaviour in case of
+         unknown recipients
+       - Properly report temporary errors now as 4xx
+       - ANY queries now include MBOXFW data
+       - NS records now have precedence over wildcard records
+       - some more logging behind DLOG() so it only appears in
+         verbose-logging builds
+
+Changes since 1.1:
+
+       - Resolved memory leak in TCP server
+       - We did not reset the AA bit on a NS referral
+       - distribution tar did not include documentation directory
+       - improved database recycling in case of database server failure and
+               restoration
+
+
diff --git a/pdns/INSTALL b/pdns/INSTALL
new file mode 100644 (file)
index 0000000..93ed08c
--- /dev/null
@@ -0,0 +1,3 @@
+Read http://doc.powerdns.com/compiling-powerdns.html
+
+./configure ; make; ./installer should do the trick
diff --git a/pdns/LICENSE b/pdns/LICENSE
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  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.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/pdns/Makefile.am b/pdns/Makefile.am
new file mode 100644 (file)
index 0000000..d2ff9e8
--- /dev/null
@@ -0,0 +1,57 @@
+AM_CXXFLAGS=-D_GNU_SOURCE -DSYSCONFDIR=\"@sysconfdir@\" -DBINDIR=\"@bindir@\" -DLOCALSTATEDIR=\"@localstatedir@\" -Ibackends/bind
+AM_CPPFLAGS=-Ibackends/bind
+
+EXTRA_DIST = codedocs/Makefile codedocs/doxygen.conf sample docs/Makefile \
+docs/gslb-operations.sgml docs/powerdns-case.sgml docs/powerdns-install.sgml \
+docs/powerdns-overview.sgml docs/powerdns-technical.sgml extra/Makefile \
+extra/null.c pdns.spec release-scripts/ debian/changelog debian/conffiles \
+debian/control debian/postinst debian/postrm debian/preinst \
+debian/prerm debian/rules installer \
+pathconfig.redhat pathconfig pathconfig.bsd pathconfig.debian docs/pdns.sgml \
+LICENSE choosepaths mtasker.cc COPYING 
+
+bin_SCRIPTS = pdns
+sysconf_DATA = pdns.conf-dist smtpredir.conf-dist 
+
+bin_PROGRAMS = pdns_server pdns_control binpatch # syncres #   resolver syncres # smtpredir
+
+
+pdns_server_SOURCES=dnspacket.cc nameserver.cc tcpreceiver.hh \
+qtype.cc logger.cc arguments.cc packethandler.cc tcpreceiver.cc \
+packetcache.cc statbag.cc ahuexception.hh arguments.hh distributor.hh \
+dns.hh dnsbackend.hh dnsbackend.cc dnspacket.hh dynmessenger.hh lock.hh logger.hh \
+nameserver.hh packetcache.hh packethandler.hh qtype.hh statbag.hh \
+ueberbackend.hh pdns.conf-dist ws.hh ws.cc webserver.cc webserver.hh \
+session.cc session.hh misc.cc misc.hh receiver.cc ueberbackend.cc \
+dynlistener.cc dynlistener.hh  dynhandler.cc dynhandler.hh  \
+resolver.hh resolver.cc communicator.cc communicator.hh dnsproxy.cc \
+dnsproxy.hh randombackend.cc unix_utility.cc common_startup.cc \
+utility.hh iputils.hh common_startup.hh \
+backends/bind/bindbackend.cc backends/bind/zoneparser2.cc \
+backends/bind/bindparser.cc backends/bind/bindlexer.c \
+backends/bind/huffman.cc
+
+#
+pdns_server_LDFLAGS=-rdynamic @LIBDL@ extra/*.o `cat extra/ld`  -ldl
+pdns_server_INCLUDES=
+
+
+#resolver_SOURCES=resolver.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
+#logger.cc statbag.cc dnspacket.cc arguments.cc  tres.cc
+
+#syncres_SOURCES=syncres.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
+#logger.cc statbag.cc dnspacket.cc arguments.cc  lwres.cc recns.cc lwres.hh \
+#mtasker.hh 
+
+pdns_control_SOURCES=dynloader.cc dynmessenger.cc  arguments.cc logger.cc statbag.cc misc.cc unix_utility.cc
+pdns_control_INCLUDES=path.hh
+pdns_control_LDFLAGS=
+
+binpatch_SOURCES=binpatch.cc 
+
+SUBDIRS= codedocs backends extra .
+
+deb: ../ahudns_1.1-1_i386.deb
+
+../ahudns_1.1-1_i386.deb:
+       ./debian/rules binary-arch
diff --git a/pdns/Makefile.in b/pdns/Makefile.in
new file mode 100644 (file)
index 0000000..3f39fa2
--- /dev/null
@@ -0,0 +1,823 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LEX = @LEX@
+LIBDL = @LIBDL@
+LIBRESOLV = @LIBRESOLV@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+AM_CXXFLAGS = -D_GNU_SOURCE -DSYSCONFDIR=\"@sysconfdir@\" -DBINDIR=\"@bindir@\" -DLOCALSTATEDIR=\"@localstatedir@\" -Ibackends/bind
+AM_CPPFLAGS = -Ibackends/bind
+
+EXTRA_DIST = codedocs/Makefile codedocs/doxygen.conf sample docs/Makefile \
+docs/gslb-operations.sgml docs/powerdns-case.sgml docs/powerdns-install.sgml \
+docs/powerdns-overview.sgml docs/powerdns-technical.sgml extra/Makefile \
+extra/null.c pdns.spec release-scripts/ debian/changelog debian/conffiles \
+debian/control debian/postinst debian/postrm debian/preinst \
+debian/prerm debian/rules installer \
+pathconfig.redhat pathconfig pathconfig.bsd pathconfig.debian docs/pdns.sgml \
+LICENSE choosepaths mtasker.cc COPYING 
+
+
+bin_SCRIPTS = pdns
+sysconf_DATA = pdns.conf-dist smtpredir.conf-dist 
+
+bin_PROGRAMS = pdns_server pdns_control binpatch # syncres #   resolver syncres # smtpredir
+
+pdns_server_SOURCES = dnspacket.cc nameserver.cc tcpreceiver.hh \
+qtype.cc logger.cc arguments.cc packethandler.cc tcpreceiver.cc \
+packetcache.cc statbag.cc ahuexception.hh arguments.hh distributor.hh \
+dns.hh dnsbackend.hh dnsbackend.cc dnspacket.hh dynmessenger.hh lock.hh logger.hh \
+nameserver.hh packetcache.hh packethandler.hh qtype.hh statbag.hh \
+ueberbackend.hh pdns.conf-dist ws.hh ws.cc webserver.cc webserver.hh \
+session.cc session.hh misc.cc misc.hh receiver.cc ueberbackend.cc \
+dynlistener.cc dynlistener.hh  dynhandler.cc dynhandler.hh  \
+resolver.hh resolver.cc communicator.cc communicator.hh dnsproxy.cc \
+dnsproxy.hh randombackend.cc unix_utility.cc common_startup.cc \
+utility.hh iputils.hh common_startup.hh \
+backends/bind/bindbackend.cc backends/bind/zoneparser2.cc \
+backends/bind/bindparser.cc backends/bind/bindlexer.c \
+backends/bind/huffman.cc
+
+
+#
+pdns_server_LDFLAGS = -rdynamic @LIBDL@ extra/*.o `cat extra/ld`  -ldl
+pdns_server_INCLUDES = 
+
+
+#resolver_SOURCES=resolver.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
+#logger.cc statbag.cc dnspacket.cc arguments.cc  tres.cc
+
+#syncres_SOURCES=syncres.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
+#logger.cc statbag.cc dnspacket.cc arguments.cc  lwres.cc recns.cc lwres.hh \
+#mtasker.hh 
+pdns_control_SOURCES = dynloader.cc dynmessenger.cc  arguments.cc logger.cc statbag.cc misc.cc unix_utility.cc
+pdns_control_INCLUDES = path.hh
+pdns_control_LDFLAGS = 
+
+binpatch_SOURCES = binpatch.cc 
+
+SUBDIRS = codedocs backends extra .
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = pdns.conf-dist buildroot.sh showvar pdns mkbindist
+bin_PROGRAMS = pdns_server$(EXEEXT) pdns_control$(EXEEXT) \
+       binpatch$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS)
+
+am_binpatch_OBJECTS = binpatch.$(OBJEXT)
+binpatch_OBJECTS = $(am_binpatch_OBJECTS)
+binpatch_LDADD = $(LDADD)
+binpatch_DEPENDENCIES =
+binpatch_LDFLAGS =
+am_pdns_control_OBJECTS = dynloader.$(OBJEXT) dynmessenger.$(OBJEXT) \
+       arguments.$(OBJEXT) logger.$(OBJEXT) statbag.$(OBJEXT) \
+       misc.$(OBJEXT) unix_utility.$(OBJEXT)
+pdns_control_OBJECTS = $(am_pdns_control_OBJECTS)
+pdns_control_LDADD = $(LDADD)
+pdns_control_DEPENDENCIES =
+am_pdns_server_OBJECTS = dnspacket.$(OBJEXT) nameserver.$(OBJEXT) \
+       qtype.$(OBJEXT) logger.$(OBJEXT) arguments.$(OBJEXT) \
+       packethandler.$(OBJEXT) tcpreceiver.$(OBJEXT) \
+       packetcache.$(OBJEXT) statbag.$(OBJEXT) dnsbackend.$(OBJEXT) \
+       ws.$(OBJEXT) webserver.$(OBJEXT) session.$(OBJEXT) \
+       misc.$(OBJEXT) receiver.$(OBJEXT) ueberbackend.$(OBJEXT) \
+       dynlistener.$(OBJEXT) dynhandler.$(OBJEXT) resolver.$(OBJEXT) \
+       communicator.$(OBJEXT) dnsproxy.$(OBJEXT) \
+       randombackend.$(OBJEXT) unix_utility.$(OBJEXT) \
+       common_startup.$(OBJEXT) bindbackend.$(OBJEXT) \
+       zoneparser2.$(OBJEXT) bindparser.$(OBJEXT) bindlexer.$(OBJEXT) \
+       huffman.$(OBJEXT)
+pdns_server_OBJECTS = $(am_pdns_server_OBJECTS)
+pdns_server_LDADD = $(LDADD)
+pdns_server_DEPENDENCIES =
+SCRIPTS = $(bin_SCRIPTS)
+
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I.
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/arguments.Po $(DEPDIR)/bindbackend.Po \
+@AMDEP_TRUE@   $(DEPDIR)/bindlexer.Po $(DEPDIR)/bindparser.Po \
+@AMDEP_TRUE@   $(DEPDIR)/binpatch.Po $(DEPDIR)/common_startup.Po \
+@AMDEP_TRUE@   $(DEPDIR)/communicator.Po $(DEPDIR)/dnsbackend.Po \
+@AMDEP_TRUE@   $(DEPDIR)/dnspacket.Po $(DEPDIR)/dnsproxy.Po \
+@AMDEP_TRUE@   $(DEPDIR)/dynhandler.Po $(DEPDIR)/dynlistener.Po \
+@AMDEP_TRUE@   $(DEPDIR)/dynloader.Po $(DEPDIR)/dynmessenger.Po \
+@AMDEP_TRUE@   $(DEPDIR)/huffman.Po $(DEPDIR)/logger.Po \
+@AMDEP_TRUE@   $(DEPDIR)/misc.Po $(DEPDIR)/nameserver.Po \
+@AMDEP_TRUE@   $(DEPDIR)/packetcache.Po $(DEPDIR)/packethandler.Po \
+@AMDEP_TRUE@   $(DEPDIR)/qtype.Po $(DEPDIR)/randombackend.Po \
+@AMDEP_TRUE@   $(DEPDIR)/receiver.Po $(DEPDIR)/resolver.Po \
+@AMDEP_TRUE@   $(DEPDIR)/session.Po $(DEPDIR)/statbag.Po \
+@AMDEP_TRUE@   $(DEPDIR)/tcpreceiver.Po $(DEPDIR)/ueberbackend.Po \
+@AMDEP_TRUE@   $(DEPDIR)/unix_utility.Po $(DEPDIR)/webserver.Po \
+@AMDEP_TRUE@   $(DEPDIR)/ws.Po $(DEPDIR)/zoneparser2.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXFLAGS = @CXXFLAGS@
+DIST_SOURCES = $(binpatch_SOURCES) $(pdns_control_SOURCES) \
+       $(pdns_server_SOURCES)
+DATA = $(sysconf_DATA)
+
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
+       uninstall-info-recursive all-recursive install-data-recursive \
+       install-exec-recursive installdirs-recursive install-recursive \
+       uninstall-recursive check-recursive installcheck-recursive
+DIST_COMMON = README ./stamp-h.in COPYING ChangeLog INSTALL Makefile.am \
+       Makefile.in TODO acconfig.h aclocal.m4 buildroot.sh.in \
+       config.guess config.h.in config.sub configure configure.in \
+       depcomp install-sh ltmain.sh missing mkbindist.in mkinstalldirs \
+       pdns.conf-dist.in pdns.in showvar.in ylwrap
+DIST_SUBDIRS = $(SUBDIRS)
+SOURCES = $(binpatch_SOURCES) $(pdns_control_SOURCES) $(pdns_server_SOURCES)
+
+all: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$@ $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+$(srcdir)/configure:  $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+       cd $(srcdir) && $(AUTOCONF)
+
+$(ACLOCAL_M4):  configure.in 
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+config.h: stamp-h
+       @if test ! -f $@; then \
+               rm -f stamp-h; \
+               $(MAKE) stamp-h; \
+       else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+       @rm -f stamp-h stamp-hT
+       @echo timestamp > stamp-hT 2> /dev/null
+       cd $(top_builddir) \
+         && CONFIG_FILES= CONFIG_HEADERS=config.h \
+            $(SHELL) ./config.status
+       @mv stamp-hT stamp-h
+$(srcdir)/config.h.in:  $(srcdir)/./stamp-h.in
+       @if test ! -f $@; then \
+               rm -f $(srcdir)/./stamp-h.in; \
+               $(MAKE) $(srcdir)/./stamp-h.in; \
+       else :; fi
+$(srcdir)/./stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/acconfig.h
+       @rm -f $(srcdir)/./stamp-h.in $(srcdir)/./stamp-h.inT
+       @echo timestamp > $(srcdir)/./stamp-h.inT 2> /dev/null
+       cd $(top_srcdir) && $(AUTOHEADER)
+       @mv $(srcdir)/./stamp-h.inT $(srcdir)/./stamp-h.in
+
+distclean-hdr:
+       -rm -f config.h
+pdns.conf-dist: $(top_builddir)/config.status pdns.conf-dist.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+buildroot.sh: $(top_builddir)/config.status buildroot.sh.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+showvar: $(top_builddir)/config.status showvar.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+pdns: $(top_builddir)/config.status pdns.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+mkbindist: $(top_builddir)/config.status mkbindist.in
+       cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+         rm -f $(DESTDIR)$(bindir)/$$f; \
+       done
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+binpatch$(EXEEXT): $(binpatch_OBJECTS) $(binpatch_DEPENDENCIES) 
+       @rm -f binpatch$(EXEEXT)
+       $(CXXLINK) $(binpatch_LDFLAGS) $(binpatch_OBJECTS) $(binpatch_LDADD) $(LIBS)
+pdns_control$(EXEEXT): $(pdns_control_OBJECTS) $(pdns_control_DEPENDENCIES) 
+       @rm -f pdns_control$(EXEEXT)
+       $(CXXLINK) $(pdns_control_LDFLAGS) $(pdns_control_OBJECTS) $(pdns_control_LDADD) $(LIBS)
+bindbackend.$(OBJEXT): backends/bind/bindbackend.cc
+zoneparser2.$(OBJEXT): backends/bind/zoneparser2.cc
+bindparser.$(OBJEXT): backends/bind/bindparser.cc
+bindlexer.$(OBJEXT): backends/bind/bindlexer.c
+huffman.$(OBJEXT): backends/bind/huffman.cc
+pdns_server$(EXEEXT): $(pdns_server_OBJECTS) $(pdns_server_DEPENDENCIES) 
+       @rm -f pdns_server$(EXEEXT)
+       $(CXXLINK) $(pdns_server_LDFLAGS) $(pdns_server_OBJECTS) $(pdns_server_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_SCRIPTS)'; for p in $$list; do \
+         f="`echo $$p|sed '$(transform)'`"; \
+         if test -f $$p; then \
+           echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/$$f"; \
+           $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/$$f; \
+         elif test -f $(srcdir)/$$p; then \
+           echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/$$f"; \
+           $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/$$f; \
+         else :; fi; \
+       done
+
+uninstall-binSCRIPTS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_SCRIPTS)'; for p in $$list; do \
+         f="`echo $$p|sed '$(transform)'`"; \
+         echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+         rm -f $(DESTDIR)$(bindir)/$$f; \
+       done
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/arguments.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindbackend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindlexer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/binpatch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/common_startup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/communicator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dnsbackend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dnspacket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dnsproxy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dynhandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dynlistener.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dynloader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dynmessenger.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/huffman.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/logger.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/nameserver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/packetcache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/packethandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/qtype.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/randombackend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/receiver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/resolver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/session.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/statbag.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/tcpreceiver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ueberbackend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/unix_utility.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/webserver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ws.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/zoneparser2.Po@am__quote@
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+bindlexer.o: backends/bind/bindlexer.c
+@AMDEP_TRUE@   source='backends/bind/bindlexer.c' object='bindlexer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindlexer.Po' tmpdepfile='$(DEPDIR)/bindlexer.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bindlexer.o `test -f backends/bind/bindlexer.c || echo '$(srcdir)/'`backends/bind/bindlexer.c
+
+bindlexer.obj: backends/bind/bindlexer.c
+@AMDEP_TRUE@   source='backends/bind/bindlexer.c' object='bindlexer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindlexer.Po' tmpdepfile='$(DEPDIR)/bindlexer.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bindlexer.obj `cygpath -w backends/bind/bindlexer.c`
+
+bindlexer.lo: backends/bind/bindlexer.c
+@AMDEP_TRUE@   source='backends/bind/bindlexer.c' object='bindlexer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindlexer.Plo' tmpdepfile='$(DEPDIR)/bindlexer.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bindlexer.lo `test -f backends/bind/bindlexer.c || echo '$(srcdir)/'`backends/bind/bindlexer.c
+CCDEPMODE = @CCDEPMODE@
+
+.cc.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+.cc.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
+
+.cc.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+bindbackend.o: backends/bind/bindbackend.cc
+@AMDEP_TRUE@   source='backends/bind/bindbackend.cc' object='bindbackend.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindbackend.Po' tmpdepfile='$(DEPDIR)/bindbackend.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindbackend.o `test -f backends/bind/bindbackend.cc || echo '$(srcdir)/'`backends/bind/bindbackend.cc
+
+bindbackend.obj: backends/bind/bindbackend.cc
+@AMDEP_TRUE@   source='backends/bind/bindbackend.cc' object='bindbackend.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindbackend.Po' tmpdepfile='$(DEPDIR)/bindbackend.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindbackend.obj `cygpath -w backends/bind/bindbackend.cc`
+
+bindbackend.lo: backends/bind/bindbackend.cc
+@AMDEP_TRUE@   source='backends/bind/bindbackend.cc' object='bindbackend.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindbackend.Plo' tmpdepfile='$(DEPDIR)/bindbackend.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindbackend.lo `test -f backends/bind/bindbackend.cc || echo '$(srcdir)/'`backends/bind/bindbackend.cc
+
+zoneparser2.o: backends/bind/zoneparser2.cc
+@AMDEP_TRUE@   source='backends/bind/zoneparser2.cc' object='zoneparser2.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/zoneparser2.Po' tmpdepfile='$(DEPDIR)/zoneparser2.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoneparser2.o `test -f backends/bind/zoneparser2.cc || echo '$(srcdir)/'`backends/bind/zoneparser2.cc
+
+zoneparser2.obj: backends/bind/zoneparser2.cc
+@AMDEP_TRUE@   source='backends/bind/zoneparser2.cc' object='zoneparser2.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/zoneparser2.Po' tmpdepfile='$(DEPDIR)/zoneparser2.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoneparser2.obj `cygpath -w backends/bind/zoneparser2.cc`
+
+zoneparser2.lo: backends/bind/zoneparser2.cc
+@AMDEP_TRUE@   source='backends/bind/zoneparser2.cc' object='zoneparser2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/zoneparser2.Plo' tmpdepfile='$(DEPDIR)/zoneparser2.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoneparser2.lo `test -f backends/bind/zoneparser2.cc || echo '$(srcdir)/'`backends/bind/zoneparser2.cc
+
+bindparser.o: backends/bind/bindparser.cc
+@AMDEP_TRUE@   source='backends/bind/bindparser.cc' object='bindparser.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindparser.Po' tmpdepfile='$(DEPDIR)/bindparser.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindparser.o `test -f backends/bind/bindparser.cc || echo '$(srcdir)/'`backends/bind/bindparser.cc
+
+bindparser.obj: backends/bind/bindparser.cc
+@AMDEP_TRUE@   source='backends/bind/bindparser.cc' object='bindparser.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindparser.Po' tmpdepfile='$(DEPDIR)/bindparser.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindparser.obj `cygpath -w backends/bind/bindparser.cc`
+
+bindparser.lo: backends/bind/bindparser.cc
+@AMDEP_TRUE@   source='backends/bind/bindparser.cc' object='bindparser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/bindparser.Plo' tmpdepfile='$(DEPDIR)/bindparser.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bindparser.lo `test -f backends/bind/bindparser.cc || echo '$(srcdir)/'`backends/bind/bindparser.cc
+
+huffman.o: backends/bind/huffman.cc
+@AMDEP_TRUE@   source='backends/bind/huffman.cc' object='huffman.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/huffman.Po' tmpdepfile='$(DEPDIR)/huffman.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o huffman.o `test -f backends/bind/huffman.cc || echo '$(srcdir)/'`backends/bind/huffman.cc
+
+huffman.obj: backends/bind/huffman.cc
+@AMDEP_TRUE@   source='backends/bind/huffman.cc' object='huffman.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/huffman.Po' tmpdepfile='$(DEPDIR)/huffman.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o huffman.obj `cygpath -w backends/bind/huffman.cc`
+
+huffman.lo: backends/bind/huffman.cc
+@AMDEP_TRUE@   source='backends/bind/huffman.cc' object='huffman.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/huffman.Plo' tmpdepfile='$(DEPDIR)/huffman.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o huffman.lo `test -f backends/bind/huffman.cc || echo '$(srcdir)/'`backends/bind/huffman.cc
+CXXDEPMODE = @CXXDEPMODE@
+uninstall-info-am:
+install-sysconfDATA: $(sysconf_DATA)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+       @list='$(sysconf_DATA)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(sysconfdir)/$$f"; \
+         $(INSTALL_DATA) $$d$$p $(DESTDIR)$(sysconfdir)/$$f; \
+       done
+
+uninstall-sysconfDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(sysconf_DATA)'; for p in $$list; do \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " rm -f $(DESTDIR)$(sysconfdir)/$$f"; \
+         rm -f $(DESTDIR)$(sysconfdir)/$$f; \
+       done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = .
+# Avoid unsightly `./'.
+distdir = $(PACKAGE)-$(VERSION)
+
+GZIP_ENV = --best
+
+distdir: $(DISTFILES)
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+       mkdir $(distdir)
+       $(mkinstalldirs) $(distdir)/. $(distdir)/codedocs $(distdir)/debian $(distdir)/docs $(distdir)/extra
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$(top_distdir)" \
+               distdir=../$(distdir)/$$subdir \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist: distdir
+       $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf -
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       chmod a-w $(distdir)
+       dc_install_base=`CDPATH=: && cd $(distdir)/=inst && pwd` \
+         && cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_install_base \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \
+            || (echo "Error: files left after uninstall" 1>&2; \
+                exit 1) ) \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && $(MAKE) $(AM_MAKEFLAGS) distclean \
+         && rm -f $(distdir).tar.gz \
+         && (test `find . -type f -print | wc -l` -eq 0 \
+            || (echo "Error: files left after distclean" 1>&2; \
+                exit 1) )
+       -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
+       @echo "$(distdir).tar.gz is ready for distribution" | \
+         sed 'h;s/./=/g;p;x;p;x'
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+       $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(bindir) $(DESTDIR)$(sysconfdir)
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+dist-all: distdir
+       $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+distclean: distclean-recursive
+       -rm -f config.status config.cache config.log
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-hdr distclean-libtool \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS install-binSCRIPTS \
+       install-sysconfDATA
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
+       uninstall-info-am uninstall-sysconfDATA
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \
+       clean-binPROGRAMS clean-generic clean-libtool clean-recursive \
+       dist dist-all distcheck distclean distclean-compile \
+       distclean-depend distclean-generic distclean-hdr \
+       distclean-libtool distclean-recursive distclean-tags distdir \
+       dvi dvi-am dvi-recursive info info-am info-recursive install \
+       install-am install-binPROGRAMS install-binSCRIPTS install-data \
+       install-data-am install-data-recursive install-exec \
+       install-exec-am install-exec-recursive install-info \
+       install-info-am install-info-recursive install-man \
+       install-recursive install-strip install-sysconfDATA \
+       installcheck installcheck-am installdirs installdirs-am \
+       installdirs-recursive maintainer-clean maintainer-clean-generic \
+       maintainer-clean-recursive mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
+       tags tags-recursive uninstall uninstall-am \
+       uninstall-binPROGRAMS uninstall-binSCRIPTS uninstall-info-am \
+       uninstall-info-recursive uninstall-recursive \
+       uninstall-sysconfDATA
+
+
+deb: ../ahudns_1.1-1_i386.deb
+
+../ahudns_1.1-1_i386.deb:
+       ./debian/rules binary-arch
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/pdns/README b/pdns/README
new file mode 100644 (file)
index 0000000..7b1af0f
--- /dev/null
@@ -0,0 +1,25 @@
+See http://pdns.powerdns.com and especially 
+http://pdns.powerdns.com/doc & http://pdns.powerdns.com/doc/pdns.pdf
+
+For those not reading documentation, and installing from the .tar.gz:
+
+       $ ./choosepaths 
+          or
+       $ editor pathconfig
+
+       and then, as root
+
+       # ./installer
+
+If you installed the RPM or the .deb, you can skip the above.
+
+If this went ok:
+
+# /etc/init.d/pdns monitor
+
+Now add "bind-example-zones" to pds.conf, and query your nameserver:
+
+$ host www.example.com 127.0.0.1
+www.example.com                A       1.2.3.4
+
+and NOW read the documentation!
\ No newline at end of file
diff --git a/pdns/TODO b/pdns/TODO
new file mode 100644 (file)
index 0000000..60f6cce
--- /dev/null
+++ b/pdns/TODO
@@ -0,0 +1,22 @@
+
+       betere compressie (. NS records passen er niet in!)
+
+       zone includes absolute/relative paths
+
+       learn bindbackend to reload the configuration
+               'rediscover' method?
+               
+done   pdns_control notify interface
+               pdns_control mass-notify
+                       notify fucking everybody of fucking everything
+
+               pdns_control rediscover
+
+       make guardian perform pings over the controlsocket, 'heartbeat'
+
+       
+       Solaris build
+       Resurrect Windows build
+
+       autotuning number of backend threads
+
diff --git a/pdns/acconfig.h b/pdns/acconfig.h
new file mode 100644 (file)
index 0000000..5122365
--- /dev/null
@@ -0,0 +1,3 @@
+/* Define when extra posix typedefs are needed (solaris2.6) */
+#undef NEED_POSIX_TYPEDEF
+#undef VERBOSELOG
diff --git a/pdns/aclocal.m4 b/pdns/aclocal.m4
new file mode 100644 (file)
index 0000000..475c8cc
--- /dev/null
@@ -0,0 +1,4064 @@
+# aclocal.m4 generated automatically by aclocal 1.5
+
+# Copyright 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 5
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# We require 2.13 because we rely on SHELL being computed by configure.
+AC_PREREQ([2.13])
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED.
+# The purpose of this macro is to provide the user with a means to
+# check macros which are provided without letting her know how the
+# information is coded.
+# If this macro is not defined by Autoconf, define it here.
+ifdef([AC_PROVIDE_IFELSE],
+      [],
+      [define([AC_PROVIDE_IFELSE],
+              [ifdef([AC_PROVIDE_$1],
+                     [$2], [$3])])])
+
+
+# AM_INIT_AUTOMAKE(PACKAGE,VERSION, [NO-DEFINE])
+# ----------------------------------------------
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first])
+fi
+
+# Define the identity of the package.
+PACKAGE=$1
+AC_SUBST(PACKAGE)dnl
+VERSION=$2
+AC_SUBST(VERSION)dnl
+ifelse([$3],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])
+
+# Autoconf 2.50 wants to disallow AM_ names.  We explicitly allow
+# the ones we care about.
+ifdef([m4_pattern_allow],
+      [m4_pattern_allow([^AM_[A-Z]+FLAGS])])dnl
+
+# Autoconf 2.50 always computes EXEEXT.  However we need to be
+# compatible with 2.13, for now.  So we always define EXEEXT, but we
+# don't compute it.
+AC_SUBST(EXEEXT)
+# Similar for OBJEXT -- only we only use OBJEXT if the user actually
+# requests that it be used.  This is a bit dumb.
+: ${OBJEXT=o}
+AC_SUBST(OBJEXT)
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal)
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake)
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_MISSING_PROG(AMTAR, tar)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_PROVIDE_IFELSE([AC_PROG_][CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_][CC],
+                          defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_][CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_][CXX],
+                          defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+# serial 3
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+
+# serial 2
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  am_backtick='`'
+  AC_MSG_WARN([${am_backtick}missing' script is too old or missing])
+fi
+])
+
+# AM_AUX_DIR_EXPAND
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND], [
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd`
+])
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# serial 4                                             -*- Autoconf -*-
+
+
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+
+# _AM_DEPENDENCIES(NAME)
+# ---------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX" or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc']
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    echo '#include "conftest.h"' > conftest.c
+    echo 'int i;' > conftest.h
+    echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=conftest.c object=conftest.o \
+       depfile=conftest.Po tmpdepfile=conftest.TPo \
+       $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 &&
+       grep conftest.h conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      am_cv_$1_dependencies_compiler_type=$depmode
+      break
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+$1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type"
+AC_SUBST([$1DEPMODE])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[rm -f .deps 2>/dev/null
+mkdir .deps 2>/dev/null
+if test -d .deps; then
+  DEPDIR=.deps
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  DEPDIR=_deps
+fi
+rmdir .deps 2>/dev/null
+AC_SUBST(DEPDIR)
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking Speeds up one-time builds
+  --enable-dependency-tracking  Do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+pushdef([subst], defn([AC_SUBST]))
+subst(AMDEPBACKSLASH)
+popdef([subst])
+])
+
+# Generate code to set up dependency tracking.
+# This macro should only be invoked once -- use via AC_REQUIRE.
+# Usage:
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],[
+AC_OUTPUT_COMMANDS([
+test x"$AMDEP_TRUE" != x"" ||
+for mf in $CONFIG_FILES; do
+  case "$mf" in
+  Makefile) dirpart=.;;
+  */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;;
+  *) continue;;
+  esac
+  grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue
+  # Extract the definition of DEP_FILES from the Makefile without
+  # running `make'.
+  DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n -e '/^U = / s///p' < "$mf"`
+  test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
+  # We invoke sed twice because it is the simplest approach to
+  # changing $(DEPDIR) to its actual value in the expansion.
+  for file in `sed -n -e '
+    /^DEP_FILES = .*\\\\$/ {
+      s/^DEP_FILES = //
+      :loop
+       s/\\\\$//
+       p
+       n
+       /\\\\$/ b loop
+      p
+    }
+    /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`echo "$file" | sed -e 's|/[^/]*$||'`
+    $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+], [AMDEP_TRUE="$AMDEP_TRUE"
+ac_aux_dir="$ac_aux_dir"])])
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+doit:
+       @echo done
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include='#'
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote='"'
+      _am_result=BSD
+   fi
+fi
+AC_SUBST(am__include)
+AC_SUBST(am__quote)
+AC_MSG_RESULT($_am_result)
+rm -f confinc confmf
+])
+
+# serial 3
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+#
+# FIXME: Once using 2.50, use this:
+# m4_match([$1], [^TRUE\|FALSE$], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_DEFUN([AM_CONDITIONAL],
+[ifelse([$1], [TRUE],
+        [errprint(__file__:__line__: [$0: invalid condition: $1
+])dnl
+m4exit(1)])dnl
+ifelse([$1], [FALSE],
+       [errprint(__file__:__line__: [$0: invalid condition: $1
+])dnl
+m4exit(1)])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+# serial 3
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  We must strip everything past the first ":",
+# and everything past the last "/".
+
+AC_PREREQ([2.12])
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[ifdef([AC_FOREACH],dnl
+        [dnl init our file count if it isn't already
+        m4_ifndef([_AM_Config_Header_Index], m4_define([_AM_Config_Header_Index], [0]))
+        dnl prepare to store our destination file list for use in config.status
+        AC_FOREACH([_AM_File], [$1],
+                   [m4_pushdef([_AM_Dest], m4_patsubst(_AM_File, [:.*]))
+                   m4_define([_AM_Config_Header_Index], m4_incr(_AM_Config_Header_Index))
+                   dnl and add it to the list of files AC keeps track of, along
+                   dnl with our hook
+                   AC_CONFIG_HEADERS(_AM_File,
+dnl COMMANDS, [, INIT-CMDS]
+[# update the timestamp
+echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h]_AM_Config_Header_Index["
+][$2]m4_ifval([$3], [, [$3]]))dnl AC_CONFIG_HEADERS
+                   m4_popdef([_AM_Dest])])],dnl
+[AC_CONFIG_HEADER([$1])
+  AC_OUTPUT_COMMANDS(
+   ifelse(patsubst([$1], [[^ ]], []),
+         [],
+         [test -z "$CONFIG_HEADERS" || echo timestamp >dnl
+          patsubst([$1], [^\([^:]*/\)?.*], [\1])stamp-h]),dnl
+[am_indx=1
+for am_file in $1; do
+  case " \$CONFIG_HEADERS " in
+  *" \$am_file "*)
+    am_dir=\`echo \$am_file |sed 's%:.*%%;s%[^/]*\$%%'\`
+    if test -n "\$am_dir"; then
+      am_tmpdir=\`echo \$am_dir |sed 's%^\(/*\).*\$%\1%'\`
+      for am_subdir in \`echo \$am_dir |sed 's%/% %'\`; do
+        am_tmpdir=\$am_tmpdir\$am_subdir/
+        if test ! -d \$am_tmpdir; then
+          mkdir \$am_tmpdir
+        fi
+      done
+    fi
+    echo timestamp > "\$am_dir"stamp-h\$am_indx
+    ;;
+  esac
+  am_indx=\`expr \$am_indx + 1\`
+done])
+])]) # AM_CONFIG_HEADER
+
+# _AM_DIRNAME(PATH)
+# -----------------
+# Like AS_DIRNAME, only do it during macro expansion
+AC_DEFUN([_AM_DIRNAME],
+       [m4_if(m4_regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1,
+             m4_if(m4_regexp([$1], [^//\([^/]\|$\)]), -1,
+                   m4_if(m4_regexp([$1], [^/.*]), -1,
+                         [.],
+                         m4_patsubst([$1], [^\(/\).*], [\1])),
+                   m4_patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])),
+             m4_patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl
+]) # _AM_DIRNAME
+
+
+# AM_PROG_LEX
+# Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+AC_DEFUN([AM_PROG_LEX],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+AC_CHECK_PROGS(LEX, flex lex, [${am_missing_run}flex])
+AC_PROG_LEX
+AC_DECL_YYTEXT])
+
+# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
+
+# serial 46 AC_PROG_LIBTOOL
+
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])
+
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+_LT_AC_PROG_ECHO_BACKSLASH
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
+  ;;
+esac
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE(libtool-lock,
+  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_SAVE
+     AC_LANG_C
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_RESTORE])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+
+  # recent cygwin and mingw systems supply a stub DllMain which the user
+  # can override, but on older systems we have to supply one
+  AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain,
+    [AC_TRY_LINK([],
+      [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
+      DllMain (0, 0, 0);],
+      [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])])
+
+  case $host/$CC in
+  *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*)
+    # old mingw systems require "-dll" to link a DLL, while more recent ones
+    # require "-mdll"
+    SAVE_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -mdll"
+    AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch,
+      [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])])
+    CFLAGS="$SAVE_CFLAGS" ;;
+  *-*-cygwin* | *-*-pw32*)
+    # cygwin systems need to pass --dll to the linker, and not link
+    # crt.o which will require a WinMain@16 definition.
+    lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;;
+  esac
+  ;;
+  ])
+esac
+
+_LT_AC_LTCONFIG_HACK
+
+])
+
+# AC_LIBTOOL_HEADER_ASSERT
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
+[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
+    [lt_cv_func_assert_works],
+    [case $host in
+    *-*-solaris*)
+      if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
+        case `$CC --version 2>/dev/null` in
+        [[12]].*) lt_cv_func_assert_works=no ;;
+        *)        lt_cv_func_assert_works=yes ;;
+        esac
+      fi
+      ;;
+    esac])
+
+if test "x$lt_cv_func_assert_works" = xyes; then
+  AC_CHECK_HEADERS(assert.h)
+fi
+])# AC_LIBTOOL_HEADER_ASSERT
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)
+])# _LT_AC_CHECK_DLFCN
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+solaris* | sysv5*)
+  symcode='[[BDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $host_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[[ABCDGISTW]]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[       ]]\($symcode$symcode*\)[[       ]][[    ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+         sed "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         save_LIBS="$LIBS"
+         save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if AC_TRY_EVAL(ac_link) && test -s conftest; then
+           pipe_works=yes
+         fi
+         LIBS="$save_LIBS"
+         CFLAGS="$save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&AC_FD_CC
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AC_FD_CC
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+    fi
+  else
+    echo "$progname: failed program was:" >&AC_FD_CC
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+  global_symbol_to_c_name_address=
+else
+  global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+  global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+fi
+if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+# ---------------------------------
+AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR],
+[# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+                             [AC_DIVERT_PUSH(NOTICE)])
+_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "[$]0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+AC_DIVERT_POP
+])# _LT_AC_PROG_ECHO_BACKSLASH
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}]
+EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_unknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+# AC_LIBTOOL_DLOPEN_SELF
+# -------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+          [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+            [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      LDFLAGS="$LDFLAGS $link_static_flag"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+AC_DEFUN([_LT_AC_LTCONFIG_HACK],
+[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+need_locks="$enable_libtool_lock"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+if test x"$host" != x"$build"; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case $host_os in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="[$]2"
+
+AC_MSG_CHECKING([for objdir])
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+AC_MSG_RESULT($objdir)
+
+
+AC_ARG_WITH(pic,
+[  --with-pic              try to use only PIC/non-PIC objects [default=use both]],
+pic_mode="$withval", pic_mode=default)
+test -z "$pic_mode" && pic_mode=default
+
+# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+# in isolation, and that seeing it set (from the cache) indicates that
+# the associated values are set (in the cache) correctly too.
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+AC_CACHE_VAL(lt_cv_prog_cc_pic,
+[ lt_cv_prog_cc_pic=
+  lt_cv_prog_cc_shlib=
+  lt_cv_prog_cc_wl=
+  lt_cv_prog_cc_static=
+  lt_cv_prog_cc_no_builtin=
+  lt_cv_prog_cc_can_build_shared=$can_build_shared
+
+  if test "$GCC" = yes; then
+    lt_cv_prog_cc_wl='-Wl,'
+    lt_cv_prog_cc_static='-static'
+
+    case $host_os in
+    aix*)
+      # Below there is a dirty hack to force normal static linking with -ldl
+      # The problem is because libdl dynamically linked with both libc and
+      # libC (AIX C++ library), which obviously doesn't included in libraries
+      # list by gcc. This cause undefined symbols with -static flags.
+      # This hack allows C programs to be linked with "-static -ldl", but
+      # not sure about C++ programs.
+      lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_cv_prog_cc_pic='-fno-common'
+      ;;
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+        lt_cv_prog_cc_pic=-Kconform_pic
+      fi
+      ;;
+    *)
+      lt_cv_prog_cc_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for PIC flags for the system compiler.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      lt_cv_prog_cc_wl='-Wl,'
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_cv_prog_cc_static='-Bstatic'
+      else
+       lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+      lt_cv_prog_cc_pic='+Z'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      # PIC (with -KPIC) is the default.
+      ;;
+
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+
+    newsos6)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      # All OSF/1 code is PIC.
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      ;;
+
+    sco3.2v5*)
+      lt_cv_prog_cc_pic='-Kpic'
+      lt_cv_prog_cc_static='-dn'
+      lt_cv_prog_cc_shlib='-belf'
+      ;;
+
+    solaris*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    sunos4*)
+      lt_cv_prog_cc_pic='-PIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Qoption ld '
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      if test "x$host_vendor" = xsni; then
+       lt_cv_prog_cc_wl='-LD'
+      else
+       lt_cv_prog_cc_wl='-Wl,'
+      fi
+      ;;
+
+    uts4*)
+      lt_cv_prog_cc_pic='-pic'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_cv_prog_cc_pic='-Kconform_pic'
+       lt_cv_prog_cc_static='-Bstatic'
+      fi
+      ;;
+
+    *)
+      lt_cv_prog_cc_can_build_shared=no
+      ;;
+    esac
+  fi
+])
+if test -z "$lt_cv_prog_cc_pic"; then
+  AC_MSG_RESULT([none])
+else
+  AC_MSG_RESULT([$lt_cv_prog_cc_pic])
+
+  # Check to make sure the pic_flag actually works.
+  AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works])
+  AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+    AC_TRY_COMPILE([], [], [dnl
+      case $host_os in
+      hpux9* | hpux10* | hpux11*)
+       # On HP-UX, both CC and GCC only warn that PIC is supported... then
+       # they create non-PIC objects.  So, if there were any warnings, we
+       # assume that PIC is not supported.
+       if test -s conftest.err; then
+         lt_cv_prog_cc_pic_works=no
+       else
+         lt_cv_prog_cc_pic_works=yes
+       fi
+       ;;
+      *)
+       lt_cv_prog_cc_pic_works=yes
+       ;;
+      esac
+    ], [dnl
+      lt_cv_prog_cc_pic_works=no
+    ])
+    CFLAGS="$save_CFLAGS"
+  ])
+
+  if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+    lt_cv_prog_cc_pic=
+    lt_cv_prog_cc_can_build_shared=no
+  else
+    lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+  fi
+
+  AC_MSG_RESULT([$lt_cv_prog_cc_pic_works])
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$lt_cv_prog_cc_shlib"; then
+  AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[[        ]]$lt_cv_prog_cc_shlib[[        ]]" >/dev/null; then :
+  else
+   AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
+    lt_cv_prog_cc_can_build_shared=no
+  fi
+fi
+
+AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works])
+AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl
+  lt_cv_prog_cc_static_works=no
+  save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+  AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes])
+  LDFLAGS="$save_LDFLAGS"
+])
+
+# Belt *and* braces to stop my trousers falling down:
+test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+AC_MSG_RESULT([$lt_cv_prog_cc_static_works])
+
+pic_flag="$lt_cv_prog_cc_pic"
+special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+wl="$lt_cv_prog_cc_wl"
+link_static_flag="$lt_cv_prog_cc_static"
+no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+can_build_shared="$lt_cv_prog_cc_can_build_shared"
+
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext])
+AC_CACHE_VAL([lt_cv_compiler_c_o], [
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+echo "int some_variable = 0;" > conftest.$ac_ext
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+compiler_c_o=no
+if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+  if test -s out/conftest.err; then
+    lt_cv_compiler_c_o=no
+  else
+    lt_cv_compiler_c_o=yes
+  fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&AC_FD_CC
+  lt_cv_compiler_c_o=no
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+])
+compiler_c_o=$lt_cv_compiler_c_o
+AC_MSG_RESULT([$compiler_c_o])
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  AC_MSG_CHECKING([if $compiler supports -c -o file.lo])
+  AC_CACHE_VAL([lt_cv_compiler_o_lo], [
+  lt_cv_compiler_o_lo=no
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  save_objext="$ac_objext"
+  ac_objext=lo
+  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      lt_cv_compiler_o_lo=no
+    else
+      lt_cv_compiler_o_lo=yes
+    fi
+  ])
+  ac_objext="$save_objext"
+  CFLAGS="$save_CFLAGS"
+  ])
+  compiler_o_lo=$lt_cv_compiler_o_lo
+  AC_MSG_RESULT([$compiler_o_lo])
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$GCC" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions])
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+  compiler_rtti_exceptions=no
+  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      compiler_rtti_exceptions=no
+    else
+      compiler_rtti_exceptions=yes
+    fi
+  ])
+  CFLAGS="$save_CFLAGS"
+  AC_MSG_RESULT([$compiler_rtti_exceptions])
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+fi
+
+# See if the linker supports building shared libraries.
+AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries])
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+old_archive_from_expsyms_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_into_libs=no
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+link_all_deplibs=unknown
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+extract_expsyms_cmds=
+
+case $host_os in
+cygwin* | mingw* | pw32*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$GCC" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+openbsd*)
+  with_gnu_ld=no
+  ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case $host_os in
+  aix3* | aix4* | aix5*)
+    # On AIX, the GNU linker is very broken
+    # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+      sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+      test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+      if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+      else $CC -o impgen impgen.c ; fi)~
+      $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+
+    old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+
+    # cygwin and mingw dlls have different entry points and sets of symbols
+    # to exclude.
+    # FIXME: what about values for MSVC?
+    dll_entry=__cygwin_dll_entry@12
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+    case $host_os in
+    mingw*)
+      # mingw values
+      dll_entry=_DllMainCRTStartup@12
+      dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+      ;;
+    esac
+
+    # mingw and cygwin differ, and it's simplest to just exclude the union
+    # of the two symbol sets.
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+
+    # recent cygwin and mingw systems supply a stub DllMain which the user
+    # can override, but on older systems we have to supply one (in ltdll.c)
+    if test "x$lt_cv_need_dllmain" = "xyes"; then
+      ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+      ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+       test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+    else
+      ltdll_obj=
+      ltdll_cmds=
+    fi
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    # Be careful not to strip the DATA tag left be newer dlltools.
+    export_symbols_cmds="$ltdll_cmds"'
+      $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+    # If the export-symbols file already is a .def file (1st line
+    # is EXPORTS), use it as is.
+    # If DATA tags from a recent dlltool are present, honour them!
+    archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname-def;
+      else
+       echo EXPORTS > $output_objdir/$soname-def;
+       _lt_hint=1;
+       cat $export_symbols | while read symbol; do
+        set dummy \$symbol;
+        case \[$]# in
+          2) echo "   \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+          *) echo "     \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
+        esac;
+        _lt_hint=`expr 1 + \$_lt_hint`;
+       done;
+      fi~
+      '"$ltdll_cmds"'
+      $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+      $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+      $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+      wlarc=
+    else
+      archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    fi
+    ;;
+
+  solaris* | sysv5*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw* | pw32*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec=
+      fi
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case $host_os in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$GCC" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+       done
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    hardcode_direct=yes
+    archive_cmds=''
+    hardcode_libdir_separator=':'
+    if test "$GCC" = yes; then
+      case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+         strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         hardcode_direct=yes
+       else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+       fi
+      esac
+
+      shared_flag='-shared'
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       shared_flag='${wl}-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall can do strange things, so it is better to
+    # generate a list of symbols to export.
+    always_export_symbols=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag='-berok'
+      hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+      archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+    else
+      if test "$host_cpu" = ia64; then
+       hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+       allow_undefined_flag="-z nodefs"
+       archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+       hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='${wl}-berok'
+       # This is a bit strange, but is similar to how AIX traditionally builds
+       # it's shared libraries.
+       archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
+      fi
+    fi
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+    fix_srcfile_path='`cygpath -w "$srcfile"`'
+    ;;
+
+  darwin* | rhapsody*)
+    case "$host_os" in
+    rhapsody* | darwin1.[[012]])
+      allow_undefined_flag='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      allow_undefined_flag='-flat_namespace -undefined suppress'
+      ;;
+    esac
+    # FIXME: Relying on posixy $() will cause problems for
+    #        cross-compilation, but unfortunately the echo tests do not
+    #        yet detect zsh echo's removal of \ escapes.  Also zsh mangles
+    #       `"' quotes if we put them in here... so don't!
+    archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
+    # We need to add '_' to the symbols in $export_symbols first
+    #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    whole_archive_flag_spec='-all_load $convenience'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case $host_os in
+    hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+                        # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6* | nonstopux*)
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    link_all_deplibs=yes
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+    fi
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  newsos6)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+    else
+      case "$host_os" in
+      openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_libdir_flag_spec='-R$libdir'
+        ;;
+      *)
+        archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+        ;;
+      esac
+    fi
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+    ;;
+
+  osf3*)
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  osf4* | osf5*)       # as osf3* with the addition of -msym flag
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+      $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+      #Both c and cxx compiler support -rpath directly
+      hardcode_libdir_flag_spec='-rpath $libdir'
+    fi
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    export_dynamic_flag_spec='${wl}-Bexport'
+    ;;
+
+  solaris*)
+    # gcc --version < 3.0 without binutils cannot create self contained
+    # shared libraries reliably, requiring libgcc.a to resolve some of
+    # the object symbols generated in some cases.  Libraries that use
+    # assert need libgcc.a to resolve __eprintf, for example.  Linking
+    # a copy of libgcc.a into every shared library to guarantee resolving
+    # such symbols causes other problems:  According to Tim Van Holder
+    # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+    # (to the application) exception stack for one thing.
+    no_undefined_flag=' -z defs'
+    if test "$GCC" = yes; then
+      case `$CC --version 2>/dev/null` in
+      [[12]].*)
+       cat <<EOF 1>&2
+
+*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+*** create self contained shared libraries on Solaris systems, without
+*** introducing a dependency on libgcc.a.  Therefore, libtool is disabling
+*** -no-undefined support, which will at least allow you to build shared
+*** libraries.  However, you may find that when you link such libraries
+*** into an application without using GCC, you have to manually add
+*** \`gcc --print-libgcc-file-name\` to the link command.  We urge you to
+*** upgrade to a newer version of GCC.  Another option is to rebuild your
+*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+
+EOF
+        no_undefined_flag=
+       ;;
+      esac
+    fi
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case $host_os in
+    solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    link_all_deplibs=yes
+    ;;
+
+  sunos4*)
+    if test "x$host_vendor" = xsequent; then
+      # Use $CC to link under sequent, because it throws in some extra .o
+      # files that make .init and .fini sections work.
+      archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+    fi
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    if test "x$host_vendor" = xsno; then
+      archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes # is this really true???
+    else
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  sysv5*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec=
+    hardcode_shlibpath_var=no
+    runpath_var='LD_RUN_PATH'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ld_shlibs=yes
+    fi
+    ;;
+
+  sysv4.2uw2*)
+    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=no
+    hardcode_shlibpath_var=no
+    hardcode_runpath_var=yes
+    runpath_var=LD_RUN_PATH
+    ;;
+
+  sysv5uw7* | unixware7*)
+    no_undefined_flag='${wl}-z ${wl}text'
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+AC_MSG_RESULT([$ld_shlibs])
+test "$ld_shlibs" = no && can_build_shared=no
+
+# Check hardcoding attributes.
+AC_MSG_CHECKING([how to hardcode library paths into programs])
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+AC_MSG_RESULT([$hardcode_action])
+
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+# PORTME Fill in your ld.so characteristics
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+            echo ' yes '
+            echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+         :
+       else
+         can_build_shared=no
+       fi
+       ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can
+    # not hardcode correct soname into executable. Probably we can
+    # add versioning support to collect2, so additional links can
+    # be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}.so$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  export_dynamic_flag_spec=-rdynamic
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  need_version=no
+  need_lib_prefix=no
+  case $GCC,$host_os in
+  yes,cygwin*)
+    library_names_spec='$libname.dll.a'
+    soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+    postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog .libs/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    ;;
+  yes,mingw*)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+    sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
+    ;;
+  yes,pw32*)
+    library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    ;;
+  *)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  # FIXME: Relying on posixy $() will cause problems for
+  #        cross-compilation, but unfortunately the echo tests do not
+  #        yet detect zsh echo's removal of \ escapes.
+  library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)'
+  soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  *)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)          version_type=irix ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case "$host_os" in
+    openbsd2.[[89]] | openbsd2.[[89]].*)
+      shlibpath_overrides_runpath=no
+      ;;
+    *)
+      shlibpath_overrides_runpath=yes
+      ;;
+    esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_version=no
+  need_lib_prefix=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+AC_LIBTOOL_DLOPEN_SELF
+
+if test "$enable_shared" = yes && test "$GCC" = yes; then
+  case $archive_cmds in
+  *'~'*)
+    # FIXME: we may have to deal with multi-command sequences.
+    ;;
+  '$CC '*)
+    # Test whether the compiler implicitly links with -lc since on some
+    # systems, -lgcc has to come before -lc. If gcc already passes -lc
+    # to ld, don't add -lc before -lgcc.
+    AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+    AC_CACHE_VAL([lt_cv_archive_cmds_need_lc],
+    [$rm conftest*
+    echo 'static int dummy;' > conftest.$ac_ext
+
+    if AC_TRY_EVAL(ac_compile); then
+      soname=conftest
+      lib=conftest
+      libobjs=conftest.$ac_objext
+      deplibs=
+      wl=$lt_cv_prog_cc_wl
+      compiler_flags=-v
+      linker_flags=-v
+      verstring=
+      output_objdir=.
+      libname=conftest
+      save_allow_undefined_flag=$allow_undefined_flag
+      allow_undefined_flag=
+      if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+      then
+       lt_cv_archive_cmds_need_lc=no
+      else
+       lt_cv_archive_cmds_need_lc=yes
+      fi
+      allow_undefined_flag=$save_allow_undefined_flag
+    else
+      cat conftest.err 1>&5
+    fi])
+    AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc])
+    ;;
+  esac
+fi
+need_lc=${lt_cv_archive_cmds_need_lc-yes}
+
+# The second clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  :
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  test -f Makefile && make "$ltmain"
+fi
+
+if test -f "$ltmain"; then
+  trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+  $rm -f "${ofile}T"
+
+  echo creating $ofile
+
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS \
+    AR AR_FLAGS CC LD LN_S NM SHELL \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+    postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+    old_striplib striplib file_magic_cmd export_symbols_cmds \
+    deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    global_symbol_to_c_name_address \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case $var in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  cat <<__EOF__ > "${ofile}T"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# 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.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$need_lc
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# The default C compiler.
+CC=$lt_CC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_pic_flag
+pic_mode=$pic_mode
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$lt_compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "${ofile}T"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | os2*)
+    cat <<'EOF' >> "${ofile}T"
+      # This is a source program that is used to create dlls on Windows
+      # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+       # This is a source program that is used to create import libraries
+       # on Windows for dlls which lack them. Don't remove nor modify the
+       # starting and closing comments
+# /* impgen.c starts here */
+# /*   Copyright (C) 1999-2000 Free Software Foundation, Inc.
+#
+#  This file is part of GNU libtool.
+#
+#  This program 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, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  */
+#
+# #include <stdio.h>           /* for printf() */
+# #include <unistd.h>          /* for open(), lseek(), read() */
+# #include <fcntl.h>           /* for O_RDONLY, O_BINARY */
+# #include <string.h>          /* for strdup() */
+#
+# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+# #ifndef O_BINARY
+# #define O_BINARY 0
+# #endif
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+#      int fd;
+#      int offset;
+# {
+#   unsigned char b[2];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 2);
+#   return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+#     int fd;
+#     int offset;
+# {
+#   unsigned char b[4];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 4);
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+#      void *ptr;
+# {
+#   unsigned char *b = ptr;
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+#     int argc;
+#     char *argv[];
+# {
+#     int dll;
+#     unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+#     unsigned long export_rva, export_size, nsections, secptr, expptr;
+#     unsigned long name_rvas, nexp;
+#     unsigned char *expdata, *erva;
+#     char *filename, *dll_name;
+#
+#     filename = argv[1];
+#
+#     dll = open(filename, O_RDONLY|O_BINARY);
+#     if (dll < 1)
+#      return 1;
+#
+#     dll_name = filename;
+#
+#     for (i=0; filename[i]; i++)
+#      if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
+#          dll_name = filename + i +1;
+#
+#     pe_header_offset = pe_get32 (dll, 0x3c);
+#     opthdr_ofs = pe_header_offset + 4 + 20;
+#     num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+#     if (num_entries < 1) /* no exports */
+#      return 1;
+#
+#     export_rva = pe_get32 (dll, opthdr_ofs + 96);
+#     export_size = pe_get32 (dll, opthdr_ofs + 100);
+#     nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+#     secptr = (pe_header_offset + 4 + 20 +
+#            pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+#     expptr = 0;
+#     for (i = 0; i < nsections; i++)
+#     {
+#      char sname[8];
+#      unsigned long secptr1 = secptr + 40 * i;
+#      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+#      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+#      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+#      lseek(dll, secptr1, SEEK_SET);
+#      read(dll, sname, 8);
+#      if (vaddr <= export_rva && vaddr+vsize > export_rva)
+#      {
+#          expptr = fptr + (export_rva - vaddr);
+#          if (export_rva + export_size > vaddr + vsize)
+#              export_size = vsize - (export_rva - vaddr);
+#          break;
+#      }
+#     }
+#
+#     expdata = (unsigned char*)malloc(export_size);
+#     lseek (dll, expptr, SEEK_SET);
+#     read (dll, expdata, export_size);
+#     erva = expdata - export_rva;
+#
+#     nexp = pe_as32 (expdata+24);
+#     name_rvas = pe_as32 (expdata+32);
+#
+#     printf ("EXPORTS\n");
+#     for (i = 0; i<nexp; i++)
+#     {
+#      unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+#      printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+#     }
+#
+#     return 0;
+# }
+# /* impgen.c ends here */
+
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+
+  mv -f "${ofile}T" "$ofile" || \
+    (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+  chmod +x "$ofile"
+fi
+
+])# _LT_AC_LTCONFIG_HACK
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_LIBTOOL_PICMODE - implement the --with-pic flag
+# Usage: AC_LIBTOOL_PICMODE[(MODE)]
+#   Where MODE is either `yes' or `no'.  If omitted, it defaults to
+#   `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)])
+
+
+# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           egrep "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])
+
+
+# AC_PATH_MAGIC - find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl
+AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])
+
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+# AC_PROG_LD_GNU -
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  lt_cv_prog_gnu_ld=yes
+else
+  lt_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])
+
+# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag,
+[lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+])
+
+# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependant libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin* | mingw* | pw32*)
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  case "$host_os" in
+  rhapsody* | darwin1.[[012]])
+    lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+    ;;
+  *) # Darwin 1.3 on
+    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+    ;;
+  esac
+  ;;
+
+freebsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20*|hpux11*)
+  lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libc.sl
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+  irix5* | nonstopux*)
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case $LD in
+    *-32|*"-32 ") libmagic=32-bit;;
+    *-n32|*"-n32 ") libmagic=N32;;
+    *-64|*"-64 ") libmagic=64-bit;;
+    *) libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+openbsd*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
+  else
+    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  # this will be overridden with pass_all, but let us keep it just in case
+  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=/lib/libc.so
+  ;;
+
+sysv5uw[[78]]* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  esac
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+])
+
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm=$ac_dir/${ac_tool_prefix}nm
+    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -B"
+       break
+      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -p"
+       break
+      else
+       lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+AC_MSG_RESULT([$NM])
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32*)
+  # These system don't have libm
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, main, LIBM="-lm")
+  ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library and LTDLINCL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments.  Note that LIBLTDL and LTDLINCL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If DIR is not
+# provided, it is assumed to be `libltdl'.  LIBLTDL will be prefixed
+# with '${top_builddir}/' and LTDLINCL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library and LTDLINCL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments.  Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called.  If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'.  LIBLTDL will
+# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!).  If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, main,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED],  [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC],  [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD],        [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
diff --git a/pdns/ahuexception.hh b/pdns/ahuexception.hh
new file mode 100644 (file)
index 0000000..daae5f6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef AHUEXCEPTION_HH
+#define AHUEXCEPTION_HH
+/* (C) 2002 POWERDNS.COM BV */
+
+#include<string>
+
+using namespace std;
+
+//! Generic Exception thrown 
+class AhuException
+{
+public:
+  AhuException(){reason="Unspecified";};
+  AhuException(string r){reason=r;};
+  
+  string reason; //! Print this to tell the user what went wrong
+};
+
+class TimeoutException : public AhuException
+{};
+
+#endif
diff --git a/pdns/arguments.cc b/pdns/arguments.cc
new file mode 100644 (file)
index 0000000..196f50a
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include <fstream>
+#include <iostream>
+#include "logger.hh"
+#include "arguments.hh"
+#include "misc.hh"
+
+#define L theL("pdns")
+extern Logger &theL(const string &prefix);
+
+const ArgvMap::param_t::const_iterator ArgvMap::begin()
+{
+  return params.begin();
+}
+
+const ArgvMap::param_t::const_iterator ArgvMap::end()
+{
+  return params.end();
+}
+
+string & ArgvMap::set(const string &var)
+{
+  return params[var];
+}
+
+bool ArgvMap::mustDo(const string &var)
+{\r
+  return ((*this)[var]!="no") && ((*this)[var]!="off");
+}
+
+vector<string>ArgvMap::list()
+{
+  vector<string> ret;
+  for(map<string,string>::const_iterator i=params.begin();i!=params.end();++i)
+    ret.push_back(i->first);
+  return ret;
+}
+
+string ArgvMap::getHelp(const string &item)
+{
+  return helpmap[item];
+}
+
+string & ArgvMap::set(const string &var, const string &help)
+{
+  helpmap[var]=help;
+  d_typeMap[var]="Parameter";
+  return set(var);
+}
+
+void ArgvMap::setCmd(const string &var, const string &help)
+{
+  helpmap[var]=help;
+  d_typeMap[var]="Command";
+  set(var)="no";
+}
+
+string & ArgvMap::setSwitch(const string &var, const string &help)
+{
+  helpmap[var]=help;
+  d_typeMap[var]="Switch";
+  return set(var);
+}
+
+
+// FIXME XXX this is pretty ugly
+bool ArgvMap::contains(const string &var, const string &val)
+{
+  const string content(params[var]);
+
+  if(content==val) // easy as pie
+    return true;
+
+  string part;
+  for(string::const_iterator i=content.begin();
+      i!=content.end();
+      i++)
+    {
+      if((*i==' ' || *i==',' || *i=='\t' || (i+1)==content.end()) && !part.empty())
+       {
+         if(i+1==content.end())
+           part+=*i;
+
+         if(part==val)
+             return true;
+         part="";
+       }
+      else
+       part+=*i;
+       
+    }
+  return false;
+}
+
+
+string ArgvMap::helpstring(string prefix)
+{
+  if(prefix=="no")
+    prefix="";
+  
+  string help;
+  
+  for(map<string,string>::const_iterator i=helpmap.begin();
+      i!=helpmap.end();
+      i++)
+    {
+      if(!prefix.empty() && i->first.find(prefix)) // only print items with prefix
+       continue;
+
+      help+="  --";
+      help+=i->first;
+      
+      string type=d_typeMap[i->first];
+
+      if(type=="Parameter")
+       help+="=...";
+      else if(type=="Switch")
+       {
+         help+=" | --"+i->first+"=yes";
+         help+=" | --"+i->first+"=no";
+       }
+      
+
+      help+="\n\t";
+      help+=i->second;
+      help+="\n";
+
+    }
+  return help;
+}
+
+string ArgvMap::configstring()
+{
+  string help;
+  
+  help="# Autogenerated configuration file template\n";
+  for(map<string,string>::const_iterator i=helpmap.begin();
+      i!=helpmap.end();
+      i++)
+    {
+      if(d_typeMap[i->first]=="Command")
+       continue;
+
+      help+="#################################\n";
+      help+="# ";
+      help+=i->first;
+      help+="\t";
+      help+=i->second;
+      help+="\n#\n";
+      help+="# "+i->first+"="+params[i->first]+"\n\n";
+
+    }
+  return help;
+}
+
+
+const string & ArgvMap::operator[](const string &arg)
+{
+  if(!parmIsset(arg))
+    throw ArgException(string("Undefined but needed argument: '")+arg+"'");
+
+
+  return params[arg];
+}
+
+int ArgvMap::asNum(const string &arg)
+{
+  if(!parmIsset(arg))
+    throw ArgException(string("Undefined but needed argument: '")+arg+"'");
+
+  return atoi(params[arg].c_str());
+}
+
+double ArgvMap::asDouble(const string &arg)
+{
+  if(!parmIsset(arg))
+    throw ArgException(string("Undefined but needed argument: '")+arg+"'");
+
+  return atof(params[arg].c_str());
+}
+
+ArgvMap::ArgvMap()
+{
+
+}
+
+bool ArgvMap::parmIsset(const string &var)
+{
+  return (params.find(var)!=params.end());
+}
+
+void ArgvMap::parseOne(const string &arg, const string &parseOnly, bool lax)
+{
+  string var, val;
+  unsigned int pos;
+
+  if(!arg.find("--") &&(pos=arg.find("="))!=string::npos)  // this is a --port=25 case
+    {
+      var=arg.substr(2,pos-2);
+      val=arg.substr(pos+1);
+    }
+  else if(!arg.find("--") && (arg.find("=")==string::npos))  // this is a --daemon case
+    { 
+      var=arg.substr(2);
+      val="";
+    }
+  else if(arg[0]=='-')
+    {
+      var=arg.substr(1);
+      val="";
+    }
+  else { // command 
+    d_cmds.push_back(arg);
+  }
+
+  if(var!="" && (parseOnly.empty() || var==parseOnly)) {
+    if(parmIsset(var))
+      params[var]=val;
+    else
+      if(!lax)
+       throw ArgException("Trying to set unexisting parameter '"+var+"'");
+  }
+}
+
+const vector<string>&ArgvMap::getCommands()
+{
+  return d_cmds;
+}
+
+void ArgvMap::parse(int &argc, char **argv, bool lax)
+{
+  for(int n=1;n<argc;n++) {
+    parseOne(argv[n],"",lax);
+  }
+}
+
+void ArgvMap::preParse(int &argc, char **argv, const string &arg)
+{
+  for(int n=1;n<argc;n++) {
+    string varval=argv[n];
+    if(!varval.find("--"+arg))
+      parseOne(argv[n]);
+  }
+}
+
+bool ArgvMap::preParseFile(const char *fname, const string &arg)
+{
+  ifstream f(fname);
+  if(!f) 
+    return false;
+  
+  string line;
+  string pline;
+  unsigned int pos;
+
+  while(getline(f,pline)) {
+    chomp(pline,"\t\r\n");
+    if(pline[pline.size()-1]=='\\') {
+      line+=pline.substr(0,pline.length()-1);
+      continue;
+    }
+    else 
+      line+=pline;
+    
+
+    // strip everything after a #
+    if((pos=line.find("#"))!=string::npos)
+      line=line.substr(0,pos);
+
+    // strip trailing spaces
+    chomp(line," ");
+    
+    // strip leading spaces
+    if((pos=line.find_first_not_of(" \t\r\n"))!=string::npos)
+      line=line.substr(pos);
+    
+    // gpgsql-basic-query=sdfsdfs dfsdfsdf sdfsdfsfd
+
+    parseOne(string("--")+line, arg);      
+    line="";
+  }
+  
+  return true;
+}
+
+
+bool ArgvMap::file(const char *fname, bool lax)
+{
+  ifstream f(fname);
+  if(!f) {
+    //    L<<"Tried file '"<<fname<<"' for configuration"<<endl;
+    return false;
+  }
+  if(!lax)
+    L<<"Opened file '"<<fname<<"' for configuration"<<endl;
+  
+  string line;
+  string pline;
+  unsigned int pos;
+  while(getline(f,pline)) {
+    chomp(pline,"\t\r\n");
+
+    if(pline[pline.size()-1]=='\\') {
+      line+=pline.substr(0,pline.length()-1);
+
+      continue;
+    }
+    else 
+      line+=pline;
+
+    // strip everything after a #
+    if((pos=line.find("#"))!=string::npos)
+      line=line.substr(0,pos);
+
+    // strip trailing spaces
+    chomp(line," ");
+
+    
+    // strip leading spaces
+    if((pos=line.find_first_not_of(" \t\r\n"))!=string::npos)
+      line=line.substr(pos);
+    
+    
+    parseOne(string("--")+line,"",lax);      
+    line="";
+  }
+  
+  return true;
+}
diff --git a/pdns/arguments.hh b/pdns/arguments.hh
new file mode 100644 (file)
index 0000000..5f73392
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef ARGUMENTS_HH
+#define ARGUMENTS_HH
+
+#include <map>
+#include <string>
+#include <vector>
+#include "ahuexception.hh"
+
+using namespace std;
+
+typedef AhuException ArgException;
+
+/** This class helps parsing argc and argv into a map of parameters. We have 3 kinds of formats:
+
+
+    -w           this leads to a key/value pair of "w"/void
+
+    --port=25    "port"/"25"
+
+    --daemon     "daemon"/void
+
+    We do not support "--port 25" syntax.
+
+    It can also read from a file. This file can contain '#' to delimit comments.
+
+    Some sample code:
+
+    \code
+
+    ArgvMap R;
+  
+    R.set("port")="25";  // use this to specify default parameters
+    R.file("./default.conf"); // parse configuration file
+    
+    R.parse(argc, argv); // read the arguments from main()
+    
+    cout<<"Will we be a deamon?: "<<R.isset("daemon")<<endl;
+    cout<<"Our port will be "<<R["port"]<<endl;
+    
+    map<string,string>::const_iterator i;
+    cout<<"via iterator"<<endl;
+    for(i=R.begin();i!=R.end();i++)
+    cout<<i->first<<"="<<i->second<<endl;
+    \endcode
+*/
+
+
+
+class ArgvMap
+{
+public:
+  ArgvMap();
+  void parse(int &argc, char **argv, bool lax=false); //!< use this to parse from argc and argv
+  void laxParse(int &argc, char **argv) //!< use this to parse from argc and argv
+  {
+    parse(argc,argv,true);
+  }
+  void ArgvMap::preParse(int &argc, char **argv, const string &arg); //!< use this to preparse a single var
+  bool ArgvMap::preParseFile(const char *fname, const string &arg); //!< use this to preparse a single var in configuration
+
+  bool file(const char *fname, bool lax=false); //!< Parses a file with parameters
+  bool laxFile(const char *fname) 
+  {
+    return file(fname,true);
+  }
+  typedef map<string,string> param_t; //!< use this if you need to know the content of the map
+  bool parmIsset(const string &var); //!< Checks if a parameter is set to *a* value
+  bool mustDo(const string &var); //!< if a switch is given, if we must do something (--help)
+  int asNum(const string &var); //!< return a variable value as a number
+  double asDouble(const string &var); //!< return a variable value as a number
+  string &set(const string &); //!< Gives a writable reference and allocates space for it
+  string &set(const string &, const string &); //!< Does the same but also allows to specify a help message
+  void setCmd(const string &, const string &); //!< Add a command flag
+  string &setSwitch(const string &, const string &); //!< Add a command flag
+  string helpstring(string prefix=""); //!< generates the --help
+  string configstring(); //!< generates the --mkconfig
+  bool contains(const string &var, const string &val);
+
+  vector<string>list();
+  string getHelp(const string &item);
+
+  const param_t::const_iterator begin(); //!< iterator semantics
+  const param_t::const_iterator end(); //!< iterator semantics
+  const string &operator[](const string &); //!< iterator semantics
+  const vector<string>&getCommands();
+private:
+  void parseOne(const string &unparsed, const string &parseOnly="", bool lax=false);
+  map<string,string> params;
+  map<string,string> helpmap;
+  map<string,string> d_typeMap;
+  vector<string> d_cmds;
+};
+
+extern ArgvMap &arg();
+
+#endif /* ARGUMENTS_HH */
diff --git a/pdns/backends/Makefile.am b/pdns/backends/Makefile.am
new file mode 100644 (file)
index 0000000..58dca58
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS=bind 
diff --git a/pdns/backends/Makefile.in b/pdns/backends/Makefile.in
new file mode 100644 (file)
index 0000000..ca0e1a3
--- /dev/null
@@ -0,0 +1,335 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LEX = @LEX@
+LIBDL = @LIBDL@
+LIBRESOLV = @LIBRESOLV@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+SUBDIRS = bind 
+subdir = backends
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
+       uninstall-info-recursive all-recursive install-data-recursive \
+       install-exec-recursive installdirs-recursive install-recursive \
+       uninstall-recursive check-recursive installcheck-recursive
+DIST_COMMON = Makefile.am Makefile.in
+DIST_SUBDIRS = $(SUBDIRS)
+all: all-recursive
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  backends/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$(top_distdir)" \
+               distdir=../$(distdir)/$$subdir \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+
+distclean-am: clean-am distclean-generic distclean-libtool \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \
+       clean-generic clean-libtool clean-recursive distclean \
+       distclean-generic distclean-libtool distclean-recursive \
+       distclean-tags distdir dvi dvi-am dvi-recursive info info-am \
+       info-recursive install install-am install-data install-data-am \
+       install-data-recursive install-exec install-exec-am \
+       install-exec-recursive install-info install-info-am \
+       install-info-recursive install-man install-recursive \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am installdirs-recursive maintainer-clean \
+       maintainer-clean-generic maintainer-clean-recursive mostlyclean \
+       mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
+       tags tags-recursive uninstall uninstall-am uninstall-info-am \
+       uninstall-info-recursive uninstall-recursive
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/pdns/backends/bind/Makefile.am b/pdns/backends/bind/Makefile.am
new file mode 100644 (file)
index 0000000..f9c00ca
--- /dev/null
@@ -0,0 +1,17 @@
+AM_CXXFLAGS=-D_GNU_SOURCE
+lib_LTLIBRARIES = libbindbackend.la
+
+libbindbackend_la_SOURCES=bindbackend.cc bindbackend.hh bindparser.yy \
+bindlexer.l zoneparser2.cc ../../misc.cc huffman.cc huffman.hh zoneparser.hh \
+bindparser.hh ../../unix_utility.cc
+
+bin_PROGRAMS = zone2sql
+
+zone2sql_SOURCES=bindparser.yy bindlexer.l zoneparser2.cc \
+../../arguments.cc ../../logger.cc zone2sql.cc ../../statbag.cc ../../misc.cc \
+../../unix_utility.cc
+
+zone2sql_LDFLAGS=
+
+LFLAGS = -s -i
+YFLAGS = -d --verbose --debug
diff --git a/pdns/backends/bind/Makefile.in b/pdns/backends/bind/Makefile.in
new file mode 100644 (file)
index 0000000..db53ae8
--- /dev/null
@@ -0,0 +1,555 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LEX = @LEX@
+LIBDL = @LIBDL@
+LIBRESOLV = @LIBRESOLV@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+AM_CXXFLAGS = -D_GNU_SOURCE
+lib_LTLIBRARIES = libbindbackend.la
+
+libbindbackend_la_SOURCES = bindbackend.cc bindbackend.hh bindparser.yy \
+bindlexer.l zoneparser2.cc ../../misc.cc huffman.cc huffman.hh zoneparser.hh \
+bindparser.hh ../../unix_utility.cc
+
+
+bin_PROGRAMS = zone2sql
+
+zone2sql_SOURCES = bindparser.yy bindlexer.l zoneparser2.cc \
+../../arguments.cc ../../logger.cc zone2sql.cc ../../statbag.cc ../../misc.cc \
+../../unix_utility.cc
+
+
+zone2sql_LDFLAGS = 
+
+LFLAGS = -s -i
+YFLAGS = -d --verbose --debug
+subdir = backends/bind
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(lib_LTLIBRARIES)
+
+libbindbackend_la_LDFLAGS =
+libbindbackend_la_LIBADD =
+am_libbindbackend_la_OBJECTS = bindbackend.lo bindparser.lo bindlexer.lo \
+       zoneparser2.lo misc.lo huffman.lo unix_utility.lo
+libbindbackend_la_OBJECTS = $(am_libbindbackend_la_OBJECTS)
+bin_PROGRAMS = zone2sql$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS)
+
+am_zone2sql_OBJECTS = bindparser.$(OBJEXT) bindlexer.$(OBJEXT) \
+       zoneparser2.$(OBJEXT) arguments.$(OBJEXT) logger.$(OBJEXT) \
+       zone2sql.$(OBJEXT) statbag.$(OBJEXT) misc.$(OBJEXT) \
+       unix_utility.$(OBJEXT)
+zone2sql_OBJECTS = $(am_zone2sql_OBJECTS)
+zone2sql_LDADD = $(LDADD)
+zone2sql_DEPENDENCIES =
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/arguments.Po $(DEPDIR)/bindbackend.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/bindlexer.Plo $(DEPDIR)/bindlexer.Po \
+@AMDEP_TRUE@   $(DEPDIR)/bindparser.Plo $(DEPDIR)/bindparser.Po \
+@AMDEP_TRUE@   $(DEPDIR)/huffman.Plo $(DEPDIR)/logger.Po \
+@AMDEP_TRUE@   $(DEPDIR)/misc.Plo $(DEPDIR)/misc.Po \
+@AMDEP_TRUE@   $(DEPDIR)/statbag.Po $(DEPDIR)/unix_utility.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/unix_utility.Po $(DEPDIR)/zone2sql.Po \
+@AMDEP_TRUE@   $(DEPDIR)/zoneparser2.Plo $(DEPDIR)/zoneparser2.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXFLAGS = @CXXFLAGS@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+DIST_SOURCES = $(libbindbackend_la_SOURCES) $(zone2sql_SOURCES)
+DIST_COMMON = Makefile.am Makefile.in TODO bindlexer.c bindparser.cc \
+       bindparser.h ylwrap
+SOURCES = $(libbindbackend_la_SOURCES) $(zone2sql_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .l .lo .o .obj .yy
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  backends/bind/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(libdir)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$p"; \
+           $(LIBTOOL) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$p; \
+         else :; fi; \
+       done
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
+         $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+bindparser.h: bindparser.cc
+misc.lo: ../../misc.cc
+unix_utility.lo: ../../unix_utility.cc
+libbindbackend.la: $(libbindbackend_la_OBJECTS) $(libbindbackend_la_DEPENDENCIES) 
+       $(CXXLINK) -rpath $(libdir) $(libbindbackend_la_LDFLAGS) $(libbindbackend_la_OBJECTS) $(libbindbackend_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+         rm -f $(DESTDIR)$(bindir)/$$f; \
+       done
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+bindparser.h: bindparser.cc
+arguments.$(OBJEXT): ../../arguments.cc
+logger.$(OBJEXT): ../../logger.cc
+statbag.$(OBJEXT): ../../statbag.cc
+misc.$(OBJEXT): ../../misc.cc
+unix_utility.$(OBJEXT): ../../unix_utility.cc
+zone2sql$(EXEEXT): $(zone2sql_OBJECTS) $(zone2sql_DEPENDENCIES) 
+       @rm -f zone2sql$(EXEEXT)
+       $(CXXLINK) $(zone2sql_LDFLAGS) $(zone2sql_OBJECTS) $(zone2sql_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/arguments.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindbackend.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindlexer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindlexer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindparser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/bindparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/huffman.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/logger.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/statbag.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/unix_utility.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/unix_utility.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/zone2sql.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/zoneparser2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/zoneparser2.Po@am__quote@
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+CCDEPMODE = @CCDEPMODE@
+
+.cc.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+.cc.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
+
+.cc.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCXXCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+misc.o: ../../misc.cc
+@AMDEP_TRUE@   source='../../misc.cc' object='misc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/misc.Po' tmpdepfile='$(DEPDIR)/misc.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o misc.o `test -f ../../misc.cc || echo '$(srcdir)/'`../../misc.cc
+
+misc.obj: ../../misc.cc
+@AMDEP_TRUE@   source='../../misc.cc' object='misc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/misc.Po' tmpdepfile='$(DEPDIR)/misc.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o misc.obj `cygpath -w ../../misc.cc`
+
+misc.lo: ../../misc.cc
+@AMDEP_TRUE@   source='../../misc.cc' object='misc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/misc.Plo' tmpdepfile='$(DEPDIR)/misc.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o misc.lo `test -f ../../misc.cc || echo '$(srcdir)/'`../../misc.cc
+
+unix_utility.o: ../../unix_utility.cc
+@AMDEP_TRUE@   source='../../unix_utility.cc' object='unix_utility.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/unix_utility.Po' tmpdepfile='$(DEPDIR)/unix_utility.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o unix_utility.o `test -f ../../unix_utility.cc || echo '$(srcdir)/'`../../unix_utility.cc
+
+unix_utility.obj: ../../unix_utility.cc
+@AMDEP_TRUE@   source='../../unix_utility.cc' object='unix_utility.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/unix_utility.Po' tmpdepfile='$(DEPDIR)/unix_utility.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o unix_utility.obj `cygpath -w ../../unix_utility.cc`
+
+unix_utility.lo: ../../unix_utility.cc
+@AMDEP_TRUE@   source='../../unix_utility.cc' object='unix_utility.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/unix_utility.Plo' tmpdepfile='$(DEPDIR)/unix_utility.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o unix_utility.lo `test -f ../../unix_utility.cc || echo '$(srcdir)/'`../../unix_utility.cc
+
+arguments.o: ../../arguments.cc
+@AMDEP_TRUE@   source='../../arguments.cc' object='arguments.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/arguments.Po' tmpdepfile='$(DEPDIR)/arguments.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arguments.o `test -f ../../arguments.cc || echo '$(srcdir)/'`../../arguments.cc
+
+arguments.obj: ../../arguments.cc
+@AMDEP_TRUE@   source='../../arguments.cc' object='arguments.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/arguments.Po' tmpdepfile='$(DEPDIR)/arguments.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arguments.obj `cygpath -w ../../arguments.cc`
+
+arguments.lo: ../../arguments.cc
+@AMDEP_TRUE@   source='../../arguments.cc' object='arguments.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/arguments.Plo' tmpdepfile='$(DEPDIR)/arguments.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arguments.lo `test -f ../../arguments.cc || echo '$(srcdir)/'`../../arguments.cc
+
+logger.o: ../../logger.cc
+@AMDEP_TRUE@   source='../../logger.cc' object='logger.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/logger.Po' tmpdepfile='$(DEPDIR)/logger.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o logger.o `test -f ../../logger.cc || echo '$(srcdir)/'`../../logger.cc
+
+logger.obj: ../../logger.cc
+@AMDEP_TRUE@   source='../../logger.cc' object='logger.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/logger.Po' tmpdepfile='$(DEPDIR)/logger.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o logger.obj `cygpath -w ../../logger.cc`
+
+logger.lo: ../../logger.cc
+@AMDEP_TRUE@   source='../../logger.cc' object='logger.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/logger.Plo' tmpdepfile='$(DEPDIR)/logger.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o logger.lo `test -f ../../logger.cc || echo '$(srcdir)/'`../../logger.cc
+
+statbag.o: ../../statbag.cc
+@AMDEP_TRUE@   source='../../statbag.cc' object='statbag.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/statbag.Po' tmpdepfile='$(DEPDIR)/statbag.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o statbag.o `test -f ../../statbag.cc || echo '$(srcdir)/'`../../statbag.cc
+
+statbag.obj: ../../statbag.cc
+@AMDEP_TRUE@   source='../../statbag.cc' object='statbag.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/statbag.Po' tmpdepfile='$(DEPDIR)/statbag.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o statbag.obj `cygpath -w ../../statbag.cc`
+
+statbag.lo: ../../statbag.cc
+@AMDEP_TRUE@   source='../../statbag.cc' object='statbag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/statbag.Plo' tmpdepfile='$(DEPDIR)/statbag.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o statbag.lo `test -f ../../statbag.cc || echo '$(srcdir)/'`../../statbag.cc
+CXXDEPMODE = @CXXDEPMODE@
+
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LEXLIB = @LEXLIB@
+
+.l.c:
+       $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.yy.cc:
+       $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h -- $(YACCCOMPILE)
+uninstall-info-am:
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+install-binPROGRAMS: install-libLTLIBRARIES
+
+
+installdirs:
+       $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "bindparser.hbindparser.h" || rm -f bindparser.h bindparser.h
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+       clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am \
+       uninstall-libLTLIBRARIES
+
+.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic clean-libLTLIBRARIES clean-libtool distclean \
+       distclean-compile distclean-depend distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am info \
+       info-am install install-am install-binPROGRAMS install-data \
+       install-data-am install-exec install-exec-am install-info \
+       install-info-am install-libLTLIBRARIES install-man \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       tags uninstall uninstall-am uninstall-binPROGRAMS \
+       uninstall-info-am uninstall-libLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/pdns/backends/bind/TODO b/pdns/backends/bind/TODO
new file mode 100644 (file)
index 0000000..2740fc0
--- /dev/null
@@ -0,0 +1,10 @@
+Stuff not working yet in zone2sql/bindbackend:
+
+$TTL
+Symbol notations of SOA, with 1H standing for 3600 etc
+
+We can't handle filenames that are mentioned multiply in named.conf it
+appears
+
+Reading zones only 1 time per all threads and not every time
+
diff --git a/pdns/backends/bind/bindbackend.cc b/pdns/backends/bind/bindbackend.cc
new file mode 100644 (file)
index 0000000..fe0fc3b
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: bindbackend.cc,v 1.1 2002/11/27 15:18:37 ahu Exp $ 
+#include <errno.h>
+#include <string>
+#include <map>
+#include <set>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace std;
+
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "bindbackend.hh"
+#include "dnspacket.hh"
+
+#include "zoneparser.hh"
+#include "bindparser.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "huffman.hh"
+#include "qtype.hh"
+#include "misc.hh"
+
+using namespace std;
+
+
+cmap_t BindBackend::d_qnames;
+map<int,vector<vector<BBResourceRecord>* > > BindBackend::d_zone_id_map;  
+set<string> BindBackend::s_contents;
+HuffmanCodec BindBackend::s_hc;
+
+map<unsigned int,BBDomainInfo> BindBackend::d_bbds;
+
+int BindBackend::s_first=1;
+
+BBDomainInfo::BBDomainInfo()
+{
+  d_loaded=false;
+  d_last_check=0;
+  d_checknow=false;
+  d_rwlock=new pthread_rwlock_t;
+  //cout<<"Generated a new bbdomaininfo: "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+  pthread_rwlock_init(d_rwlock,0);
+}
+
+void BBDomainInfo::setCheckInterval(time_t seconds)
+{
+  d_checkinterval=seconds;
+}
+
+bool BBDomainInfo::current()
+{
+  if(d_checknow)
+    return false;
+
+  if(!d_checkinterval || (time(0)-d_lastcheck<d_checkinterval) || d_filename.empty())
+    return true;
+
+  return (getCtime()==d_ctime);
+}
+
+time_t BBDomainInfo::getCtime()
+{
+  struct stat buf;
+  
+  if(d_filename.empty() || stat(d_filename.c_str(),&buf)<0)
+    return 0; 
+  d_lastcheck=time(0);
+  return buf.st_ctime;
+}
+
+void BBDomainInfo::setCtime()
+{
+  struct stat buf;
+  if(stat(d_filename.c_str(),&buf)<0)
+    return; 
+  d_ctime=buf.st_ctime;
+}
+
+
+void BindBackend::setFresh(u_int32_t domain_id)
+{
+  d_bbds[domain_id].d_last_check=time(0);
+}
+
+bool BindBackend::startTransaction(const string &qname, int id)
+{
+  d_of=new ofstream("/tmp/juh");
+  d_bbds[d_transaction_id=id].lock();
+  return true;
+}
+
+bool BindBackend::commitTransaction()
+{
+  delete d_of;
+  rename("/tmp/juh",d_bbds[d_transaction_id].d_filename.c_str());
+  queueReload(&d_bbds[d_transaction_id]);
+  d_bbds[d_transaction_id].unlock();
+  return true;
+}
+
+
+bool BindBackend::feedRecord(const DNSResourceRecord &r)
+{
+  if(r.qtype.getCode()!=QType::MX)
+    *d_of<<r.qname<<".\t"<<r.ttl<<"\t"<<r.qtype.getName()<<"\t"<<r.content<<endl;
+  else
+    *d_of<<r.qname<<".\t"<<r.ttl<<"\t"<<r.qtype.getName()<<"\t"<<r.ttl<<"\t"<<r.priority<<"\t"<<r.content<<endl;
+  return true;
+}
+
+void BindBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
+{
+  for(map<u_int32_t,BBDomainInfo>::const_iterator i=d_bbds.begin();i!=d_bbds.end();++i) {
+    if(i->second.d_master.empty())
+      continue;
+    DomainInfo sd;
+    sd.id=i->first;
+    sd.zone=i->second.d_name;
+    sd.master=i->second.d_master;
+    sd.last_check=i->second.d_last_check;
+    sd.backend=this;
+    sd.kind=DomainInfo::Slave;
+
+    SOAData soadata;
+    soadata.serial=0;
+    soadata.refresh=0;
+    getSOA(i->second.d_name,soadata);
+    sd.serial=soadata.serial;
+    if(sd.last_check+soadata.refresh<(unsigned int)time(0))
+      unfreshDomains->push_back(sd);    
+  }
+}
+
+bool BindBackend::getDomainInfo(const string &domain, DomainInfo &di)
+{
+  for(map<u_int32_t,BBDomainInfo>::const_iterator i=d_bbds.begin();i!=d_bbds.end();++i) {
+    if(i->second.d_name==domain) {
+      di.id=i->first;
+      di.zone=domain;
+      di.master=i->second.d_master;
+      di.last_check=i->second.d_last_check;
+      di.backend=this;
+      di.kind=i->second.d_master.empty() ? DomainInfo::Master : DomainInfo::Slave;
+
+      return true;
+    }
+  }
+  return false;
+}
+
+
+static string canonic(string ret)
+{
+  string::iterator i;
+  for(i=ret.begin();
+      i!=ret.end();
+      ++i)
+    *i=tolower(*i);
+
+  if(*(i-1)=='.')
+    ret.resize(i-ret.begin()-1);
+  return ret;
+}
+
+
+void BindBackend::insert(int id, const string &qnameu, const string &qtype, const string &content, int ttl=300, int prio=25)
+{
+  static int s_count;
+  static unsigned int len;
+  static unsigned int ulen;
+  DLOG(  
+  if(!((s_count++)%10000))
+    cerr<<"\r"<<s_count-1<<", "<<s_contents.size()<<" different contents, "<<d_qnames.size()<<" different qnames, "<<len/1000000<<"MB, saved: "<<
+      (ulen-len)/1000;
+  );
+  string compressed;
+  s_hc.encode(toLower(canonic(qnameu)),compressed);
+  //  string(compressed).swap(compressed);
+  //  cout<<"saved: "<<qnameu.size()-compressed.size()<<endl;
+
+  vector<BBResourceRecord>::const_iterator i;
+
+  if(d_qnames[compressed].empty()) {  // NEW! NEW! NEW! in de top 40!
+    d_zone_id_map[id].push_back(&d_qnames[compressed]); 
+    i=d_qnames[compressed].end();
+  }
+  else
+    for(i=d_qnames[compressed].begin();i!=d_qnames[compressed].end();++i)
+      if(((i)->qtype==QType::chartocode(qtype.c_str())))
+       if((*(i)->content==canonic(content)))
+         break; 
+  
+  // never saw this specific name/type/content triple before
+  if(i==d_qnames[compressed].end()) {
+    BBResourceRecord v=resourceMaker(id,qtype,canonic(content),ttl,prio);
+    v.qnameptr=&d_qnames.find(compressed)->first;
+    len+=compressed.size();
+    ulen+=qnameu.size();
+    d_qnames[compressed].push_back(v);
+    
+    d_qnames[compressed].reserve(0);
+    //    vector<BBResourceRecord>&tmp=d_qnames[compressed];
+    // vector<BBResourceRecord>(tmp).swap(tmp);
+  }
+  else {
+    s_count--;
+  }
+
+  
+}
+
+
+
+BBResourceRecord BindBackend::resourceMaker(int id, const string &qtype, const string &content, int ttl, int prio)
+{
+  BBResourceRecord make;
+  
+  make.domain_id=id;
+
+  make.qtype=QType::chartocode(qtype.c_str());
+
+  set<string>::const_iterator i=s_contents.find(content);
+  if(i==s_contents.end()) {
+    s_contents.insert(content);
+    i=s_contents.find(content);
+  }
+  make.content=&*i;
+  make.ttl=ttl;
+  make.priority=prio;
+  return make;
+}
+
+static BindBackend *us;
+static int domain_id;
+
+static void callback(const string &domain, const string &qtype, const string &content, int ttl, int prio)
+{
+  us->insert(domain_id,domain,qtype,content,ttl,prio);
+}
+
+
+
+BindBackend::BindBackend(const string &suffix)
+{
+  if(!s_first)
+    return;
+   
+  setArgPrefix("bind"+suffix);
+
+  s_first=0;
+  if(!mustDo("enable-huffman"))
+    s_hc.passthrough(true);
+  
+  if(mustDo("example-zones")) {
+    insert(0,"www.example.com","A","1.2.3.4");
+    insert(0,"example.com","SOA","ns1.example.com hostmaster.example.com");
+    insert(0,"example.com","NS","ns1.example.com",86400);
+    insert(0,"example.com","NS","ns2.example.com",86400);
+    insert(0,"example.com","MX","mail.example.com",3600,25);
+    insert(0,"example.com","MX","mail1.example.com",3600,25);
+    insert(0,"mail.example.com","A","4.3.2.1");
+    insert(0,"mail1.example.com","A","5.4.3.2");
+    insert(0,"ns1.example.com","A","4.3.2.1");
+    insert(0,"ns2.example.com","A","5.4.3.2");
+      
+    for(int i=0;i<1000;i++)
+      insert(0,"host-"+itoa(i)+".example.com","A","2.3.4.5");
+
+    BBDomainInfo bbd;
+    bbd.d_name="example.com";
+    bbd.d_filename="";
+    bbd.d_id=0;
+    d_bbds[0]=bbd; 
+    
+    d_bbds[0].d_loaded=true;
+  }
+  
+
+  if(!getArg("config").empty()) {
+    BindParser BP;
+    BP.parse(getArg("config"));
+    
+    ZoneParser ZP;
+      
+    vector<BindDomainInfo> domains=BP.getDomains();
+    
+    us=this;
+    domain_id=1;
+    ZP.setDirectory(BP.getDirectory());
+    ZP.setCallback(&callback);  
+    L<<Logger::Warning<<"Parsing "<<domains.size()<<" domain(s)"<<endl;
+    
+    for(vector<BindDomainInfo>::const_iterator i=domains.begin();
+       i!=domains.end();
+       ++i)
+      {
+       BBDomainInfo bbd;
+       bbd.d_name=i->name;
+       bbd.d_filename=i->filename;
+       bbd.d_master=i->master;
+       bbd.d_id=domain_id;
+       bbd.setCtime();
+       bbd.setCheckInterval(getArgAsNum("check-interval"));
+       
+       d_bbds[domain_id]=bbd; 
+       
+       ZP.parse(i->filename,i->name); // calls callback for us
+
+       vector<vector<BBResourceRecord> *>&tmp=d_zone_id_map[domain_id];
+       vector<vector<BBResourceRecord> *>(tmp).swap(tmp);
+       d_bbds[domain_id].d_loaded=true;
+       
+       domain_id++;
+      }
+    L<<Logger::Warning<<"Done"<<endl;
+    L<<Logger::Info<<"Number of buckets: "<<d_qnames.bucket_count()<<", number of entries: "<<d_qnames.size()<< endl;
+  }
+}
+
+void BindBackend::rediscover()
+{
+
+}
+
+void BindBackend::queueReload(BBDomainInfo *bbd)
+{
+  // we reload *now* for the time being
+  //cout<<"unlock domain"<<endl;
+  bbd->unlock();
+  //cout<<"lock it again"<<endl;
+  bbd->lock();
+  //cout<<"locked, start nuking records"<<endl;
+  bbd->d_loaded=0; // block further access
+  
+  // now nuke all records with our id
+  for(vector<vector<BBResourceRecord> *>::const_iterator i=d_zone_id_map[bbd->d_id].begin();
+      i!=d_zone_id_map[bbd->d_id].end();++i)
+    {
+      (*i)->clear();
+    }
+  //  cout<<"Now clearing the list of records"<<endl;
+  // now zonk the list with all records for our id
+  d_zone_id_map[bbd->d_id].clear();
+  // now reload
+
+
+  ZoneParser ZP;
+  us=this;
+  domain_id=bbd->d_id;
+  ZP.setCallback(&callback);  
+  ZP.parse(bbd->d_filename,bbd->d_name);
+  bbd->setCtime();
+  // and raise d_loaded again!
+  bbd->d_loaded=1;
+  bbd->d_checknow=0;
+  L<<Logger::Warning<<"Zone '"<<bbd->d_name<<"' ("<<bbd->d_filename<<") reloaded"<<endl;
+}
+
+void BindBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int zoneId )
+{
+  d_handle=new BindBackend::handle;
+  DLOG(L<<"BindBackend constructing handle for search for "<<qtype.getName()<<" for "<<
+       qname<<endl);
+
+  d_handle->qname=qname;
+  d_handle->parent=this;
+  d_handle->qtype=qtype;
+  string compressed;
+  s_hc.encode(toLower(qname),compressed);
+  d_handle->d_records=d_qnames[compressed];
+  d_handle->d_bbd=0;
+  if(!d_handle->d_records.empty()) {
+    BBDomainInfo& bbd=d_bbds[d_handle->d_records.begin()->domain_id];
+    if(!bbd.tryRLock()) {
+      L<<Logger::Warning<<"Can't get read lock on zone '"<<bbd.d_name<<"'"<<endl;
+      delete d_handle;
+      throw AhuException("Temporarily unavailable due to a zone lock"); // fuck
+    }
+      
+    if(!bbd.d_loaded) {
+      delete d_handle;
+      throw AhuException("Temporarily unavailable due to a zone lock"); // fuck
+    }
+
+    if(!bbd.current()) {
+      L<<Logger::Warning<<"Zone '"<<bbd.d_name<<"' ("<<bbd.d_filename<<") needs reloading"<<endl;
+      queueReload(&bbd);
+    }
+    d_handle->d_bbd=&bbd;
+  }
+  else {
+    DLOG(L<<"Query with no results"<<endl);
+  }
+  d_handle->d_iter=d_handle->d_records.begin();
+  d_handle->d_list=false;
+}
+
+BindBackend::handle::handle()
+{
+  d_bbd=0;
+  count=0;
+}
+
+bool  BindBackend::get(DNSResourceRecord &r)
+{
+  if(!d_handle->get(r)) {
+    delete d_handle;
+    d_handle=0;
+    return false;
+  }
+  return true;
+}
+
+bool BindBackend::handle::get(DNSResourceRecord &r)
+{
+  if(d_list)
+    return get_list(r);
+  else
+    return get_normal(r);
+}
+
+bool BindBackend::handle::get_normal(DNSResourceRecord &r)
+{
+  DLOG(L << "BindBackend get() was called for "<<qtype.getName() << " record  for "<<
+       qname<<"- "<<d_records.size()<<" available!"<<endl);
+  
+
+  while(d_iter!=d_records.end() && !(qtype=="ANY" || (d_iter)->qtype==QType(qtype).getCode())) {
+    DLOG(L<<"Skipped "<<qname<<"/"<<QType(d_iter->qtype).getName()<<": '"<<*d_iter->content<<"'"<<endl);
+    d_iter++;
+  }
+  if(d_iter==d_records.end()) { // we've reached the end
+    if(d_bbd) {
+      d_bbd->unlock();
+      d_bbd=0;
+    }
+    return false;
+  }
+
+  DLOG(L << "BindBackend get() returning a rr with a "<<QType(d_iter->qtype).getCode()<<endl);
+
+  r.qname=qname; // fill this in
+  
+  r.content=*(d_iter)->content;
+  r.domain_id=(d_iter)->domain_id;
+  r.qtype=(d_iter)->qtype;
+  r.ttl=(d_iter)->ttl;
+  r.priority=(d_iter)->priority;
+  d_iter++;
+
+  return true;
+}
+
+bool BindBackend::list(int id)
+{
+  d_handle=new BindBackend::handle;
+  DLOG(L<<"BindBackend constructing handle for list of "<<id<<endl);
+
+  d_handle->d_qname_iter=d_zone_id_map[id].begin();
+  d_handle->d_qname_end=d_zone_id_map[id].end();   // iter now points to a vector of pointers to vector<BBResourceRecords>
+  d_handle->d_riter=(*(d_handle->d_qname_iter))->begin();
+  d_handle->d_rend=(*(d_handle->d_qname_iter))->end();
+  // rend?
+  d_handle->parent=this;
+  d_handle->id=id;
+  d_handle->d_list=true;
+  return true;
+}
+
+// naam -> naamnummer
+// naamnummer -> vector<BBResourceRecords>, BBResourceRecord bevat ook een pointer naar 
+
+bool BindBackend::handle::get_list(DNSResourceRecord &r)
+{
+  DLOG(L << "BindBackend get_list()"<<endl);
+
+  while(d_riter==d_rend) {
+    DLOG(L<<"Starting new record"<<endl);
+    d_qname_iter++;
+    if(d_qname_iter==d_qname_end) { // we've reached the end of recordsets for this id
+      DLOG(L<<"Really stop!"<<endl);
+      return false;
+    }
+    d_riter=(*(d_qname_iter))->begin();
+    d_rend=(*(d_qname_iter))->end();
+  }
+  // d_riter points to a pointer to BBResourceRecord 
+
+  //  r.qname=qname; // fill this in  HOW?!
+
+  r.qname=parent->s_hc.decode(*d_riter->qnameptr);
+  
+  r.content=*(d_riter)->content;
+  r.domain_id=(d_riter)->domain_id;
+  r.qtype=(d_riter)->qtype;
+  r.ttl=(d_riter)->ttl;
+  r.priority=(d_riter)->priority;
+  d_riter++;
+  return true;
+}
+
+class BindFactory : public BackendFactory
+{
+   public:
+      BindFactory() : BackendFactory("bind") {}
+
+      void declareArguments(const string &suffix="")
+      {
+         declare(suffix,"config","Location of named.conf","");
+         declare(suffix,"example-zones","Install example zones","no");
+         declare(suffix,"enable-huffman","Enable huffman compression","no");
+         declare(suffix,"check-interval","Interval for zonefile changes","0");
+      }
+
+      DNSBackend *make(const string &suffix="")
+      {
+         return new BindBackend(suffix);
+      }
+};
+
+
+//! Magic class that is activated when the dynamic library is loaded
+class Loader
+{
+public:
+  Loader()
+  {
+    BackendMakers().report(new BindFactory);
+    theL()<<Logger::Notice<<"[BindBackend] This is the bind backend version "VERSION" ("__DATE__", "__TIME__") reporting"<<endl;
+  }
+};
+static Loader loader;
diff --git a/pdns/backends/bind/bindbackend.hh b/pdns/backends/bind/bindbackend.hh
new file mode 100644 (file)
index 0000000..c0655ba
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <string>
+#include <map>
+#include <set>
+#include <pthread.h>
+#include <time.h>
+#include <fstream>
+
+#include "huffman.hh"
+
+#if __GNUC__ >= 3
+# include <ext/hash_map>
+using namespace __gnu_cxx;
+#else
+# include <hash_map>
+#endif
+
+
+using namespace std;
+
+class BBDomainInfo
+{
+public:
+  BBDomainInfo();
+
+#if 0
+  BBDomainInfo(const BBDomainInfo &orig) {
+    d_name=orig.d_name;
+    d_loaded=orig.d_loaded;
+    d_rwlock=orig.d_rwlock;
+    cout<<"Copied "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+  }
+  BBDomainInfo &operator=(const BBDomainInfo &orig) {
+    d_loaded=orig.d_loaded;
+    d_rwlock=orig.d_rwlock;
+    cout<<"Assigned "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+    return *this;
+  }
+#endif 
+
+  void setCtime();
+
+  bool current();
+
+  bool d_loaded;
+  bool d_checknow;
+  time_t d_ctime;
+  string d_name;
+  string d_filename;
+  unsigned int d_id;
+  time_t d_last_check;
+  string d_master;
+
+  bool tryRLock()
+  {
+    //    cout<<"[trylock!] "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+    return pthread_rwlock_tryrdlock(d_rwlock)!=EBUSY;
+  }
+  
+  void unlock()
+  {
+    //    cout<<"[unlock] "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+    pthread_rwlock_unlock(d_rwlock);
+  }
+  
+  void lock()
+  {
+    //cout<<"[writelock!] "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
+
+    pthread_rwlock_wrlock(d_rwlock);
+  }
+
+  void setCheckInterval(time_t seconds);
+private:
+  time_t getCtime();
+  time_t d_checkinterval;
+  time_t d_lastcheck;
+  pthread_rwlock_t *d_rwlock;
+};
+      
+
+
+class BBResourceRecord
+{
+public:
+  bool operator==(const BBResourceRecord &o) const
+  {
+    return (o.domain_id==domain_id && o.qtype==qtype && o.content==content && 
+           o.ttl==ttl && o.priority==priority);
+  }
+  
+  const string *qnameptr; // 4
+  unsigned int domain_id;  // 4
+  unsigned short int qtype;             // 2
+  unsigned short int priority;  // 2
+  const string *content;   // 4 
+  unsigned int ttl;        // 4
+
+};
+
+struct compare_string
+{
+  bool operator()(const string& s1, const string& s2) const
+  {
+    return s1 == s2;
+  }
+};
+
+struct hash_string
+{
+  size_t operator()(const string& s) const
+  {
+    return __stl_hash_string(s.c_str());
+  }
+};
+
+typedef hash_map<string,vector<BBResourceRecord>, hash_string, compare_string> cmap_t; 
+
+
+
+/** The BindBackend is a DNSBackend that can answer DNS related questions. It looks up data
+    in a Bind-style zone file */
+class BindBackend : public DNSBackend
+{
+public:
+  BindBackend(const string &suffix=""); //!< Makes our connection to the database. Calls exit(1) if it fails.
+  void getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains);
+  bool getDomainInfo(const string &domain, DomainInfo &di);
+  time_t getCtime(const string &fname);
+  
+
+  void lookup(const QType &, const string &qdomain, DNSPacket *p=0, int zoneId=-1);
+  bool list(int id);
+  bool get(DNSResourceRecord &);
+
+  static DNSBackend *maker();
+  static set<string> s_contents;
+
+  void setFresh(u_int32_t domain_id);
+
+  bool startTransaction(const string &qname, int id);
+  //  bool BindBackend::stopTransaction(const string &qname, int id);
+  bool feedRecord(const DNSResourceRecord &r);
+  bool commitTransaction();
+  void insert(int id, const string &qname, const string &qtype, const string &content, int ttl, int prio);  
+  void rediscover();
+  static HuffmanCodec s_hc;
+private:
+  class handle
+  {
+  public:
+    bool get(DNSResourceRecord &);
+    ~handle() {
+      if(d_bbd)
+       d_bbd->unlock();
+    }
+    handle();
+
+    BindBackend *parent;
+
+    vector<BBResourceRecord>d_records;
+    vector<BBResourceRecord>::const_iterator d_iter;
+    
+    vector<BBResourceRecord>::const_iterator d_riter;
+    vector<BBResourceRecord>::const_iterator d_rend;
+    vector<vector<BBResourceRecord> *>::const_iterator d_qname_iter;
+    vector<vector<BBResourceRecord> *>::const_iterator d_qname_end;
+
+    // static map<int,vector<vector<BBResourceRecord>* > > d_zone_id_map;  
+    //                vector<vector<BBResourceRecord>* >   d_zone_id_map[id]
+    // iterator NAAR         vector<BBResourceRecord>*    d_zone_id_map[id].begin()
+
+    bool d_list;
+    int id;
+    BBDomainInfo* d_bbd;
+    string qname;
+    QType qtype;
+  private:
+    int count;
+    
+    bool get_normal(DNSResourceRecord &);
+    bool get_list(DNSResourceRecord &);
+  };
+
+  static cmap_t d_qnames;
+  static map<int,vector<vector<BBResourceRecord>* > > d_zone_id_map;  
+
+  static map<unsigned int, BBDomainInfo>d_bbds;
+  static int s_first;
+
+  int d_transaction_id;
+  ofstream *d_of;
+  handle *d_handle;
+  void queueReload(BBDomainInfo *bbd);
+  BBResourceRecord resourceMaker(int id, const string &qtype, const string &content, int ttl, int prio);
+};
diff --git a/pdns/backends/bind/bindlexer.c b/pdns/backends/bind/bindlexer.c
new file mode 100644 (file)
index 0000000..066766a
--- /dev/null
@@ -0,0 +1,1831 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/ahu/tmp/cvs2svn/pdns/pdns/backends/bind/bindlexer.c,v 1.1 2002/11/27 15:18:38 ahu Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <errno.h>
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ *     if ( condition_holds )
+ *             yyless( 5 );
+ *     else
+ *             do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               *yy_cp = yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+       };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yytext_ptr = yy_bp; \
+       yyleng = (int) (yy_cp - yy_bp); \
+       yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 29
+#define YY_END_OF_BUFFER 30
+static yyconst short int yy_accept[99] =
+    {   0,
+       20,   20,    2,    2,    7,    7,   18,   18,   30,   20,
+       25,   24,   17,   20,   20,   23,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   21,   22,    2,    4,    3,
+       29,    7,   29,   18,   19,   20,   25,   20,    0,   27,
+        1,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,    2,    3,    3,    5,    7,    0,   18,   20,    0,
+       26,   12,   20,   20,   20,   20,   20,   20,   20,   20,
+        0,   20,   10,   20,   20,   20,   20,   16,    9,    8,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,    6,   13,   15,   11,   20,   14,    0
+
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
+        1,    6,    1,    1,    1,    1,    7,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    8,    1,
+        1,    1,    1,    1,    9,    1,   10,   11,   12,   13,
+       14,    1,   15,    1,    1,   16,   17,   18,   19,   20,
+        1,   21,   22,   23,   24,    1,    1,    1,   25,   26,
+        1,    1,    1,    1,    1,    1,    9,    1,   10,   11,
+
+       12,   13,   14,    1,   15,    1,    1,   16,   17,   18,
+       19,   20,    1,   21,   22,   23,   24,    1,    1,    1,
+       25,   26,   27,    1,   28,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[29] =
+    {   0,
+        1,    2,    3,    4,    1,    5,    1,    2,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    6,    6
+    } ;
+
+static yyconst short int yy_base[111] =
+    {   0,
+        0,    0,   26,   27,   32,   33,  114,  113,  116,    0,
+      113,  221,  221,   40,   32,  221,  104,   98,   97,   93,
+       91,  100,   88,   82,   87,  221,  221,    0,  221,   39,
+      221,   45,    0,    0,  221,    0,  103,   67,  101,  221,
+        0,   94,   87,   80,   84,   89,   79,   70,   68,   70,
+       71,    0,   43,   45,  221,   52,   84,    0,  121,   84,
+      221,    0,   74,   73,   68,   69,   59,   66,   68,   67,
+       70,   67,    0,   52,   59,   61,   53,    0,    0,  221,
+       43,   54,   46,   42,   44,   42,   47,   44,   35,   34,
+       34,    0,    0,    0,    0,    6,    0,  221,  149,  155,
+
+      161,  167,  172,  178,  184,  190,  196,  202,  208,  214
+    } ;
+
+static yyconst short int yy_def[111] =
+    {   0,
+       98,    1,   99,   99,  100,  100,  101,  101,   98,  102,
+       98,   98,   98,  103,  102,   98,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,   98,   98,  104,   98,  105,
+       98,   98,  106,  107,   98,  102,   98,  103,  108,   98,
+      102,  109,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  104,  105,  105,   98,   98,  106,  107,  109,  110,
+       98,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+       98,  102,  102,  102,  102,  102,  102,  102,  102,   98,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,    0,   98,   98,
+
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98
+    } ;
+
+static yyconst short int yy_nxt[250] =
+    {   0,
+       10,   11,   12,   13,   14,   10,   15,   16,   17,   10,
+       18,   10,   19,   10,   20,   21,   22,   10,   23,   10,
+       10,   10,   24,   10,   10,   25,   26,   27,   29,   29,
+       97,   30,   30,   32,   32,   33,   33,   41,   42,   32,
+       32,   39,   40,   39,   54,   55,   56,   39,   98,   98,
+       54,   55,   56,   56,   96,   95,   94,   93,   92,   56,
+       91,   90,   89,   88,   87,   86,   39,   39,   39,   40,
+       39,   85,   84,   83,   39,   82,   81,   80,   79,   78,
+       77,   76,   75,   74,   73,   72,   61,   71,   70,   69,
+       68,   67,   66,   39,   39,   60,   61,   60,   65,   64,
+
+       63,   60,   62,   40,   37,   51,   50,   49,   48,   47,
+       46,   45,   44,   43,   37,   98,   35,   35,   98,   98,
+       60,   60,   60,   61,   60,   98,   98,   98,   60,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   60,   60,   28,
+       28,   28,   28,   28,   28,   31,   31,   31,   31,   31,
+       31,   34,   34,   34,   34,   34,   34,   36,   98,   98,
+       98,   36,   38,   38,   38,   38,   38,   38,   52,   52,
+       98,   52,   98,   52,   53,   53,   98,   53,   53,   53,
+       57,   98,   98,   98,   57,   57,   58,   58,   58,   98,
+
+       58,   58,   39,   39,   39,   39,   39,   39,   59,   59,
+       59,   59,   59,   59,   60,   60,   60,   60,   60,   60,
+        9,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98
+    } ;
+
+static yyconst short int yy_chk[250] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    3,    4,
+       96,    3,    4,    5,    6,    5,    6,   15,   15,    5,
+        6,   14,   14,   14,   30,   30,   32,   14,   53,   53,
+       54,   54,   32,   56,   91,   90,   89,   88,   87,   56,
+       86,   85,   84,   83,   82,   81,   14,   14,   38,   38,
+       38,   77,   76,   75,   38,   74,   72,   71,   70,   69,
+       68,   67,   66,   65,   64,   63,   60,   57,   51,   50,
+       49,   48,   47,   38,   38,   42,   42,   42,   46,   45,
+
+       44,   42,   43,   39,   37,   25,   24,   23,   22,   21,
+       20,   19,   18,   17,   11,    9,    8,    7,    0,    0,
+       42,   42,   59,   59,   59,    0,    0,    0,   59,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   59,   59,   99,
+       99,   99,   99,   99,   99,  100,  100,  100,  100,  100,
+      100,  101,  101,  101,  101,  101,  101,  102,    0,    0,
+        0,  102,  103,  103,  103,  103,  103,  103,  104,  104,
+        0,  104,    0,  104,  105,  105,    0,  105,  105,  105,
+      106,    0,    0,    0,  106,  106,  107,  107,  107,    0,
+
+      107,  107,  108,  108,  108,  108,  108,  108,  109,  109,
+      109,  109,  109,  109,  110,  110,  110,  110,  110,  110,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+       98,   98,   98,   98,   98,   98,   98,   98,   98
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "bindlexer.l"
+#define INITIAL 0
+#line 2 "bindlexer.l"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define YYSTYPE char *
+
+#ifdef WIN32
+#include "bindparser.tab.hh"
+#define isatty _isatty
+int isatty( int fd )
+{
+  return _isatty( fd );
+}
+#else
+#include "bindparser.h"
+#endif // WIN32
+
+int linenumber;
+#define MAX_INCLUDE_DEPTH 10
+YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+int include_stack_ln[MAX_INCLUDE_DEPTH];
+char *include_stack_name[MAX_INCLUDE_DEPTH];
+char *current_filename;
+char *original_filename;
+int include_stack_ptr = 0;
+extern const char *bind_directory;
+
+#define comment 1
+#define incl 2
+
+#define quoted 3
+
+#define YY_STACK_USED 1
+#line 487 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( yy_current_buffer->yy_is_interactive ) \
+               { \
+               int c = '*', n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+YY_DECL
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+
+#line 36 "bindlexer.l"
+
+
+
+#line 653 "lex.yy.c"
+
+       if ( yy_init )
+               {
+               yy_init = 0;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yy_start )
+                       yy_start = 1;   /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! yy_current_buffer )
+                       yy_current_buffer =
+                               yy_create_buffer( yyin, YY_BUF_SIZE );
+
+               yy_load_buffer_state();
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yy_start;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yy_last_accepting_state = yy_current_state;
+                               yy_last_accepting_cpos = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 99 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 221 );
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+               if ( yy_act == 0 )
+                       { /* have to back up */
+                       yy_cp = yy_last_accepting_cpos;
+                       yy_current_state = yy_last_accepting_state;
+                       yy_act = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+
+do_action:     /* This label is used only to access EOF actions. */
+
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yy_hold_char;
+                       yy_cp = yy_last_accepting_cpos;
+                       yy_current_state = yy_last_accepting_state;
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 39 "bindlexer.l"
+BEGIN(comment);
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 40 "bindlexer.l"
+/* eat anything that's not a '*' */
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 41 "bindlexer.l"
+/* eat up '*'s not followed by '/'s */
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 42 "bindlexer.l"
+++linenumber;
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 43 "bindlexer.l"
+BEGIN(INITIAL);
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 45 "bindlexer.l"
+BEGIN(incl);
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 46 "bindlexer.l"
+/* eat the whitespace */
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 47 "bindlexer.l"
+{ /* got the include file name */
+       char filename[1024];
+        if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+            {
+            fprintf( stderr, "Includes nested too deeply" );
+            exit( 1 );
+            }
+
+        yytext[strlen(yytext)-2]=0;
+
+        include_stack[include_stack_ptr]=YY_CURRENT_BUFFER;
+        include_stack_name[include_stack_ptr]=current_filename=strdup(yytext+1);
+        include_stack_ln[include_stack_ptr++]=linenumber;
+        linenumber=1;
+       if(*(yytext+1)=='/')
+               strcpy(filename,yytext+1);
+       else {
+               strcpy(filename,bind_directory);
+               strcat(filename,"/");
+               strcat(filename,yytext+1);
+       }
+
+        if (*yytext &&!(yyin=fopen(filename,"r"))) {
+         fprintf( stderr, "Unable to open '%s': %s\n",filename,strerror(errno));
+         exit( 1 );
+       }
+
+        BEGIN(INITIAL);
+        yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+
+   }
+       YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(comment):
+case YY_STATE_EOF(incl):
+case YY_STATE_EOF(quoted):
+#line 80 "bindlexer.l"
+{
+        if ( --include_stack_ptr < 0 )
+            {
+            yyterminate();
+            }
+
+        else
+            {
+            yy_delete_buffer(YY_CURRENT_BUFFER);
+            yy_switch_to_buffer(include_stack[include_stack_ptr]);
+            linenumber=include_stack_ln[include_stack_ptr];
+            free(include_stack_name[include_stack_ptr]);
+            if(include_stack_ptr)
+                 current_filename=include_stack_name[include_stack_ptr-1];
+            else
+                 current_filename=original_filename;
+            }
+        }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 102 "bindlexer.l"
+return ZONETOK; 
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 104 "bindlexer.l"
+return FILETOK;
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 105 "bindlexer.l"
+return OPTIONSTOK;
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 106 "bindlexer.l"
+return ACLTOK;
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 107 "bindlexer.l"
+return LOGGINGTOK;
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 108 "bindlexer.l"
+return DIRECTORYTOK;
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 109 "bindlexer.l"
+return MASTERTOK;
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 110 "bindlexer.l"
+return TYPETOK;
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 111 "bindlexer.l"
+yy_push_state(quoted);
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 112 "bindlexer.l"
+yylval=strdup(yytext); return QUOTEDWORD;
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 113 "bindlexer.l"
+yy_pop_state();
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 114 "bindlexer.l"
+yylval=strdup(yytext);return WORD;
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 115 "bindlexer.l"
+return OBRACE;
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 116 "bindlexer.l"
+return EBRACE;
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 117 "bindlexer.l"
+return SEMICOLON;
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 118 "bindlexer.l"
+linenumber++;
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 119 "bindlexer.l"
+;
+       YY_BREAK
+case 26:
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
+yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 120 "bindlexer.l"
+;
+       YY_BREAK
+case 27:
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
+yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 121 "bindlexer.l"
+;
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 122 "bindlexer.l"
+{ 
+                        fprintf(stderr,"Parsing '%s': unable to parse line %d at character '%s'\n",current_filename, linenumber, yytext);
+                        exit(1); }
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 125 "bindlexer.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+       YY_BREAK
+#line 943 "lex.yy.c"
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between yy_current_buffer and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yy_n_chars = yy_current_buffer->yy_n_chars;
+                       yy_current_buffer->yy_input_file = yyin;
+                       yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state();
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yy_c_buf_p;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer() )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap() )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yy_c_buf_p =
+                                       yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yy_c_buf_p =
+                               &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+       {
+       register char *dest = yy_current_buffer->yy_ch_buf;
+       register char *source = yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( yy_current_buffer->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+       else
+               {
+               int num_to_read =
+                       yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = yy_current_buffer;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yy_flex_realloc( (void *) b->yy_ch_buf,
+                                                        b->yy_buf_size + 2 );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = yy_current_buffer->yy_buf_size -
+                                               number_to_move - 1;
+#endif
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+                       yy_n_chars, num_to_read );
+
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       if ( yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       yy_current_buffer->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       yy_n_chars += number_to_move;
+       yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+       return ret_val;
+       }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+
+       yy_current_state = yy_start;
+
+       for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yy_last_accepting_state = yy_current_state;
+                       yy_last_accepting_cpos = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 99 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+       }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+       {
+       register int yy_is_jam;
+       register char *yy_cp = yy_c_buf_p;
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               yy_last_accepting_state = yy_current_state;
+               yy_last_accepting_cpos = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 99 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 98);
+
+       return yy_is_jam ? 0 : yy_current_state;
+       }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+       {
+       register char *yy_cp = yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yy_hold_char;
+
+       if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yy_n_chars + 2;
+               register char *dest = &yy_current_buffer->yy_ch_buf[
+                                       yy_current_buffer->yy_buf_size + 2];
+               register char *source =
+                               &yy_current_buffer->yy_ch_buf[number_to_move];
+
+               while ( source > yy_current_buffer->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               yy_current_buffer->yy_n_chars =
+                       yy_n_chars = yy_current_buffer->yy_buf_size;
+
+               if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+
+       yytext_ptr = yy_bp;
+       yy_hold_char = *yy_cp;
+       yy_c_buf_p = yy_cp;
+       }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+       {
+       int c;
+
+       *yy_c_buf_p = yy_hold_char;
+
+       if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yy_c_buf_p - yytext_ptr;
+                       ++yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer() )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart( yyin );
+
+                                       /* fall through */
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap() )
+                                               return EOF;
+
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yy_c_buf_p = yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yy_c_buf_p;      /* cast for 8-bit char's */
+       *yy_c_buf_p = '\0';     /* preserve yytext */
+       yy_hold_char = *++yy_c_buf_p;
+
+
+       return c;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+       {
+       if ( ! yy_current_buffer )
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+       yy_init_buffer( yy_current_buffer, input_file );
+       yy_load_buffer_state();
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+       {
+       if ( yy_current_buffer == new_buffer )
+               return;
+
+       if ( yy_current_buffer )
+               {
+               /* Flush out information for old buffer. */
+               *yy_c_buf_p = yy_hold_char;
+               yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       yy_current_buffer = new_buffer;
+       yy_load_buffer_state();
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yy_did_buffer_switch_on_eof = 1;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+       {
+       yy_n_chars = yy_current_buffer->yy_n_chars;
+       yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+       yyin = yy_current_buffer->yy_input_file;
+       yy_hold_char = *yy_c_buf_p;
+       }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer( b, file );
+
+       return b;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+       {
+       if ( ! b )
+               return;
+
+       if ( b == yy_current_buffer )
+               yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yy_flex_free( (void *) b->yy_ch_buf );
+
+       yy_flex_free( (void *) b );
+       }
+
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+       {
+       yy_flush_buffer( b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+       b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+       b->yy_is_interactive = 0;
+#else
+       b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+       {
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == yy_current_buffer )
+               yy_load_buffer_state();
+       }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer( b );
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+       {
+       int len;
+       for ( len = 0; yy_str[len]; ++len )
+               ;
+
+       return yy_scan_bytes( yy_str, len );
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+       {
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = len + 2;
+       buf = (char *) yy_flex_alloc( n );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < len; ++i )
+               buf[i] = bytes[i];
+
+       buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer( buf, n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+       {
+       if ( yy_start_stack_ptr >= yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yy_start_stack_depth * sizeof( int );
+
+               if ( ! yy_start_stack )
+                       yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+               else
+                       yy_start_stack = (int *) yy_flex_realloc(
+                                       (void *) yy_start_stack, new_size );
+
+               if ( ! yy_start_stack )
+                       YY_FATAL_ERROR(
+                       "out of memory expanding start-condition stack" );
+               }
+
+       yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+       }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+       {
+       if ( --yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yy_start_stack[yy_start_stack_ptr]);
+       }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+       {
+       return yy_start_stack[yy_start_stack_ptr - 1];
+       }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+       {
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+       }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               yytext[yyleng] = yy_hold_char; \
+               yy_c_buf_p = yytext + n; \
+               yy_hold_char = *yy_c_buf_p; \
+               *yy_c_buf_p = '\0'; \
+               yyleng = n; \
+               } \
+       while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+       {
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+       }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+       {
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+       }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+       {
+       return (void *) malloc( size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+       {
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+       {
+       free( ptr );
+       }
+
+#if YY_MAIN
+int main()
+       {
+       yylex();
+       return 0;
+       }
+#endif
+#line 125 "bindlexer.l"
+
diff --git a/pdns/backends/bind/bindlexer.l b/pdns/backends/bind/bindlexer.l
new file mode 100644 (file)
index 0000000..01c56d1
--- /dev/null
@@ -0,0 +1,125 @@
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define YYSTYPE char *
+
+#ifdef WIN32
+#include "bindparser.tab.hh"
+#define isatty _isatty
+int isatty( int fd )
+{
+  return _isatty( fd );
+}
+#else
+#include "bindparser.h"
+#endif // WIN32
+
+int linenumber;
+#define MAX_INCLUDE_DEPTH 10
+YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+int include_stack_ln[MAX_INCLUDE_DEPTH];
+char *include_stack_name[MAX_INCLUDE_DEPTH];
+char *current_filename;
+char *original_filename;
+int include_stack_ptr = 0;
+extern const char *bind_directory;
+
+%}
+
+%x comment 
+%x incl
+%x quoted
+%option stack
+%%
+
+
+"/*"         BEGIN(comment);
+<comment>[^*\n]*        /* eat anything that's not a '*' */
+<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
+<comment>\n             ++linenumber;
+<comment>"*"+"/"        BEGIN(INITIAL);
+
+include                 BEGIN(incl);
+<incl>[ \t;]*            /* eat the whitespace */
+<incl>\"[^ \t\n";]+\";        { /* got the include file name */
+       char filename[1024];
+        if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+            {
+            fprintf( stderr, "Includes nested too deeply" );
+            exit( 1 );
+            }
+
+        yytext[strlen(yytext)-2]=0;
+
+        include_stack[include_stack_ptr]=YY_CURRENT_BUFFER;
+        include_stack_name[include_stack_ptr]=current_filename=strdup(yytext+1);
+        include_stack_ln[include_stack_ptr++]=linenumber;
+        linenumber=1;
+       if(*(yytext+1)=='/')
+               strcpy(filename,yytext+1);
+       else {
+               strcpy(filename,bind_directory);
+               strcat(filename,"/");
+               strcat(filename,yytext+1);
+       }
+
+        if (*yytext &&!(yyin=fopen(filename,"r"))) {
+         fprintf( stderr, "Unable to open '%s': %s\n",filename,strerror(errno));
+         exit( 1 );
+       }
+
+        BEGIN(INITIAL);
+        yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+
+   }
+
+
+<<EOF>>   {
+        if ( --include_stack_ptr < 0 )
+            {
+            yyterminate();
+            }
+
+        else
+            {
+            yy_delete_buffer(YY_CURRENT_BUFFER);
+            yy_switch_to_buffer(include_stack[include_stack_ptr]);
+            linenumber=include_stack_ln[include_stack_ptr];
+            free(include_stack_name[include_stack_ptr]);
+            if(include_stack_ptr)
+                 current_filename=include_stack_name[include_stack_ptr-1];
+            else
+                 current_filename=original_filename;
+            }
+        }
+
+
+
+
+zone                   return ZONETOK; 
+
+file                   return FILETOK;
+options                 return OPTIONSTOK;
+acl                     return ACLTOK;
+logging                 return LOGGINGTOK;
+directory               return DIRECTORYTOK;
+masters                 return MASTERTOK;
+type                    return TYPETOK;
+\"                      yy_push_state(quoted);
+<quoted>[^\"]*          yylval=strdup(yytext); return QUOTEDWORD;
+<quoted>\"              yy_pop_state();
+[^\" \t\n{};]*               yylval=strdup(yytext);return WORD;
+\{                      return OBRACE;
+\}                      return EBRACE;
+;                       return SEMICOLON;
+\n                      linenumber++;
+[ \t]*                  ;
+\/\/.*$                        ;
+\#.*$                  ;
+.                       { 
+                        fprintf(stderr,"Parsing '%s': unable to parse line %d at character '%s'\n",current_filename, linenumber, yytext);
+                        exit(1); }
+%%
diff --git a/pdns/backends/bind/bindparser.cc b/pdns/backends/bind/bindparser.cc
new file mode 100644 (file)
index 0000000..c34973c
--- /dev/null
@@ -0,0 +1,1321 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/* A Bison parser, made from /home/ahu/programming/ahudns/backends/bind/bindparser.yy
+   by GNU bison 1.35.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+# define       WORD    257
+# define       QUOTEDWORD      258
+# define       OBRACE  259
+# define       EBRACE  260
+# define       SEMICOLON       261
+# define       ZONETOK 262
+# define       FILETOK 263
+# define       OPTIONSTOK      264
+# define       DIRECTORYTOK    265
+# define       ACLTOK  266
+# define       LOGGINGTOK      267
+# define       CLASSTOK        268
+# define       TYPETOK 269
+# define       MASTERTOK       270
+
+#line 1 "bindparser.yy"
+\r
+\r
+#define DIRTY_HACK WORD\r
+#undef WORD\r
+\r
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <utility>
+#include <errno.h>
+#include "misc.hh"
+#include "ahuexception.hh"
+using namespace std;
+#define YYDEBUG 1
+extern int yydebug;
+#include "bindparser.hh"
+\r
+#define WORD DIRTY_HACK \r
+
+#define YYSTYPE char *
+
+extern "C" 
+{
+       int yyparse(void);
+       int yylex(void);
+       int yywrap()
+       {
+               return 1;
+       }
+
+}
+
+extern int yydebug;
+const char *bind_directory;
+extern int linenumber;
+static void yyerror(const char *str)
+{
+  extern char *current_filename;       
+  throw AhuException("Error in bind configuration '"+string(current_filename)+"' on line "+itoa(linenumber)+": "+str);
+}
+
+extern FILE *yyin;
+static BindParser *parent;
+BindDomainInfo s_di;
+
+void BindParser::parse(const string &fname)
+{      
+       yydebug=0;
+       yyin=fopen(fname.c_str(),"r");
+
+       if(!yyin)
+               throw AhuException("Unable to open '"+fname+"': "+strerror(errno));
+
+       linenumber=1;
+       parent=this;
+       extern char *current_filename;
+       extern char *original_filename;
+
+       current_filename=original_filename=(char*)fname.c_str();
+
+       yyparse();
+
+//     cerr<<"Need to parse "<<d_zonedomains.size()<<" zone statements"<<endl;
+}
+
+void BindParser::setDirectory(const string &dir)
+{
+       d_dir=dir;
+       bind_directory=d_dir.c_str();
+}
+
+const string &BindParser::getDirectory()
+{
+       return d_dir;
+}
+
+const vector<BindDomainInfo>& BindParser::getDomains()
+{
+       return d_zonedomains;
+}
+
+void BindParser::setVerbose(bool verbose)
+{
+  d_verbose=verbose;
+}
+
+void BindParser::commit(BindDomainInfo DI)
+{
+  if(DI.filename[0]!='/')
+    DI.filename=d_dir+"/"+DI.filename;
+
+  if(d_verbose)
+    cerr<<"Domain "<<DI.name<<" lives in file '"<<DI.filename<<"'"<<endl;
+
+  d_zonedomains.push_back(DI);
+}
+
+#ifndef YYSTYPE
+# define YYSTYPE int
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+
+
+#define        YYFINAL         73
+#define        YYFLAG          -32768
+#define        YYNTBASE        17
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 270 ? yytranslate[x] : 41)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     1,     5,     7,     9,    11,    13,    14,    18,
+      20,    24,    29,    34,    39,    43,    47,    51,    52,    56,
+      58,    59,    63,    65,    67,    70,    71,    74,    76,    78,
+      80,    84,    88,    89,    93,    95,    97,    99,   101,   106,
+     107,   111,   113,   116,   119,   121
+};
+static const short yyrhs[] =
+{
+      -1,    17,    18,     7,     0,    20,     0,    23,     0,    21,
+       0,    22,     0,     0,    19,    20,     7,     0,    29,     0,
+       8,    39,    32,     0,     8,    39,     3,    32,     0,    10,
+       5,    27,     6,     0,    13,     5,    27,     6,     0,    12,
+      39,    24,     0,    12,    40,    24,     0,     5,    25,     6,
+       0,     0,    26,     7,    25,     0,     3,     0,     0,    22,
+       7,    27,     0,    20,     0,    28,     0,    11,    39,     0,
+       0,    29,    30,     0,     3,     0,    31,     0,    39,     0,
+       5,    19,     6,     0,     5,    33,     6,     0,     0,    33,
+      21,     7,     0,    20,     0,    37,     0,    38,     0,    34,
+       0,    16,     5,    35,     6,     0,     0,    35,    36,     7,
+       0,     3,     0,     9,    39,     0,    15,     3,     0,     4,
+       0,     3,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   107,   108,   112,   112,   112,   112,   115,   116,   120,
+     124,   131,   141,   143,   147,   148,   151,   154,   155,   159,
+     163,   164,   168,   168,   171,   178,   179,   183,   183,   183,
+     185,   189,   193,   194,   198,   198,   198,   198,   201,   204,
+     205,   209,   215,   223,   232,   239
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "WORD", "QUOTEDWORD", "OBRACE", "EBRACE", 
+  "SEMICOLON", "ZONETOK", "FILETOK", "OPTIONSTOK", "DIRECTORYTOK", 
+  "ACLTOK", "LOGGINGTOK", "CLASSTOK", "TYPETOK", "MASTERTOK", 
+  "root_commands", "root_command", "commands", "command", "zone_command", 
+  "options_command", "acl_command", "acl_block", "acls", "acl", 
+  "options_commands", "options_directory_command", "terms", "term", 
+  "block", "zone_block", "zone_commands", "zone_masters_command", 
+  "masters", "master", "zone_file_command", "zone_type_command", 
+  "quotedname", "filename", 0
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    17,    17,    18,    18,    18,    18,    19,    19,    20,
+      21,    21,    22,    22,    23,    23,    24,    25,    25,    26,
+      27,    27,    22,    22,    28,    29,    29,    30,    30,    30,
+      31,    32,    33,    33,    21,    21,    21,    21,    34,    35,
+      35,    36,    37,    38,    39,    40
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     0,     3,     1,     1,     1,     1,     0,     3,     1,
+       3,     4,     4,     4,     3,     3,     3,     0,     3,     1,
+       0,     3,     1,     1,     2,     0,     2,     1,     1,     1,
+       3,     3,     0,     3,     1,     1,     1,     1,     4,     0,
+       3,     1,     2,     2,     1,     1
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       1,    25,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     3,     5,     6,     4,    23,     9,    37,    35,    36,
+      44,     0,    42,    25,    24,    45,     0,     0,    25,    43,
+      39,     2,    27,     7,    26,    28,    29,     0,    32,    10,
+      22,     0,     0,    17,    14,    15,     0,     0,    25,    11,
+      25,    25,    12,    19,     0,     0,    13,    41,    38,     0,
+      30,     0,    31,    34,     0,    21,    16,    17,    40,     8,
+      33,    18,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+       1,    10,    48,    40,    12,    41,    14,    44,    54,    55,
+      42,    15,    16,    34,    35,    39,    50,    17,    47,    59,
+      18,    19,    21,    27
+};
+
+static const short yypact[] =
+{
+  -32768,     2,    16,    16,    18,    16,     5,    27,    34,    33,
+      32,-32768,-32768,-32768,-32768,-32768,    31,-32768,-32768,-32768,
+  -32768,    22,-32768,    20,-32768,-32768,    35,    35,    20,-32768,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,    36,-32768,-32768,
+  -32768,    37,    39,    40,-32768,-32768,    42,     1,    44,-32768,
+      13,    20,-32768,-32768,    45,    46,-32768,-32768,-32768,    47,
+  -32768,    48,-32768,-32768,    49,-32768,-32768,    40,-32768,-32768,
+  -32768,-32768,    52,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,-32768,-32768,    -1,    -8,    56,-32768,    19,    -9,-32768,
+     -27,-32768,-32768,-32768,-32768,    23,-32768,-32768,-32768,-32768,
+  -32768,-32768,     0,-32768
+};
+
+
+#define        YYLAST          60
+
+
+static const short yytable[] =
+{
+      11,    46,    72,    22,    57,    24,    26,    58,    25,    20,
+       2,     3,     4,     5,     6,     7,    36,     8,     9,    62,
+      20,     2,     3,    23,    65,    37,   -20,    38,     8,     9,
+       4,     5,    28,     7,    32,    20,    33,    29,    30,    31,
+      43,    38,    64,    53,    51,    52,    45,    61,    56,    63,
+      60,    66,    73,    67,    68,    69,    70,    13,    71,     0,
+      49
+};
+
+static const short yycheck[] =
+{
+       1,    28,     0,     3,     3,     5,     6,     6,     3,     4,
+       8,     9,    10,    11,    12,    13,    16,    15,    16,     6,
+       4,     8,     9,     5,    51,     3,     6,     5,    15,    16,
+      10,    11,     5,    13,     3,     4,     5,     3,     5,     7,
+       5,     5,    50,     3,     7,     6,    27,    48,     6,    50,
+       6,     6,     0,     7,     7,     7,     7,     1,    67,    -1,
+      37
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This program 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, 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+        || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))     \
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         register YYSIZE_T yyi;                \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;   \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT        goto yyabortlab
+#define YYERROR                goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   Current.last_line   = Rhs[N].last_line;     \
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX                 yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+\f
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+\f
+#line 315 "/usr/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES                      \
+/* The lookahead symbol.  */                           \
+int yychar;                                            \
+                                                       \
+/* The semantic value of the lookahead symbol. */      \
+YYSTYPE yylval;                                                \
+                                                       \
+/* Number of parse errors so far.  */                  \
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES                      \
+                                               \
+/* Location data for the lookahead symbol.  */ \
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+       YYLTYPE *yyls1 = yyls;
+       /* This used to be a conditional around just the two extra args,
+          but that might be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+       yyls = yyls1;
+# else
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yystacksize);
+# endif
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+# if YYLSP_NEEDED
+       YYSTACK_RELOCATE (yyls);
+# endif
+# undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+       which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+       {
+         YYFPRINTF (stderr, "Next token is %d (%s",
+                    yychar, yytname[yychar1]);
+         /* Give the individual parser a way to print the precise
+            meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+         YYPRINT (stderr, yychar, yylval);
+# endif
+         YYFPRINTF (stderr, ")\n");
+       }
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 10:
+#line 126 "bindparser.yy"
+{
+               s_di.name=yyvsp[-1];
+               parent->commit(s_di);
+               s_di.clear();
+       }
+    break;
+case 11:
+#line 133 "bindparser.yy"
+{
+               s_di.name=yyvsp[-2];
+               parent->commit(s_di);
+               s_di.clear();
+       }
+    break;
+case 24:
+#line 172 "bindparser.yy"
+{
+               parent->setDirectory(yyvsp[0]);
+       }
+    break;
+case 41:
+#line 210 "bindparser.yy"
+{
+               s_di.master=yyvsp[0];
+       }
+    break;
+case 42:
+#line 217 "bindparser.yy"
+{
+         //            printf("Found a filename: '%s'\n",$2);
+               s_di.filename=yyvsp[0];
+       }
+    break;
+case 43:
+#line 225 "bindparser.yy"
+{
+         //            printf("Found a filename: '%s'\n",$2);
+         //            ztype=$2;
+       }
+    break;
+case 44:
+#line 234 "bindparser.yy"
+{
+               yyval=yyvsp[0];
+       }
+    break;
+}
+
+#line 705 "/usr/share/bison/bison.simple"
+
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 240 "bindparser.yy"
diff --git a/pdns/backends/bind/bindparser.h b/pdns/backends/bind/bindparser.h
new file mode 100644 (file)
index 0000000..b0336ba
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef BISON_Y_TAB_H
+# define BISON_Y_TAB_H
+
+# ifndef YYSTYPE
+#  define YYSTYPE int
+#  define YYSTYPE_IS_TRIVIAL 1
+# endif
+# define       WORD    257
+# define       QUOTEDWORD      258
+# define       OBRACE  259
+# define       EBRACE  260
+# define       SEMICOLON       261
+# define       ZONETOK 262
+# define       FILETOK 263
+# define       OPTIONSTOK      264
+# define       DIRECTORYTOK    265
+# define       ACLTOK  266
+# define       LOGGINGTOK      267
+# define       CLASSTOK        268
+# define       TYPETOK 269
+# define       MASTERTOK       270
+
+
+extern YYSTYPE yylval;
+
+#endif /* not BISON_Y_TAB_H */
diff --git a/pdns/backends/bind/bindparser.hh b/pdns/backends/bind/bindparser.hh
new file mode 100644 (file)
index 0000000..1971037
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef BINDPARSER_HH
+#define BINDPARSER_HH
+#include <string>
+#include <map>
+#include <vector>
+
+using namespace std;
+
+class BindDomainInfo 
+{
+public:
+  void clear() 
+  {
+    name=filename=master="";
+  }
+  string name;
+  string filename;
+  string master;
+};
+
+extern const char *bind_directory;
+class BindParser
+{
+ public:
+  BindParser() : d_dir("."), d_verbose(false) {bind_directory=d_dir.c_str();}
+  void parse(const string &fname);
+  void commit(BindDomainInfo DI);
+  void setDirectory(const string &dir);
+  const string &getDirectory();
+  const vector<BindDomainInfo>& getDomains();
+  void setVerbose(bool verbose);
+private:
+  string d_dir;
+  bool d_verbose;
+  typedef map<string,string> zonedomain_t;
+
+  vector<BindDomainInfo> d_zonedomains;
+};
+
+#endif /* BINDPARSER_HH */
diff --git a/pdns/backends/bind/bindparser.yy b/pdns/backends/bind/bindparser.yy
new file mode 100644 (file)
index 0000000..345f9bd
--- /dev/null
@@ -0,0 +1,240 @@
+%{\r
+\r
+#define DIRTY_HACK WORD\r
+#undef WORD\r
+\r
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <utility>
+#include <errno.h>
+#include "misc.hh"
+#include "ahuexception.hh"
+using namespace std;
+#define YYDEBUG 1
+extern int yydebug;
+#include "bindparser.hh"
+\r
+#define WORD DIRTY_HACK \r
+
+#define YYSTYPE char *
+
+extern "C" 
+{
+       int yyparse(void);
+       int yylex(void);
+       int yywrap()
+       {
+               return 1;
+       }
+
+}
+
+extern int yydebug;
+const char *bind_directory;
+extern int linenumber;
+static void yyerror(const char *str)
+{
+  extern char *current_filename;       
+  throw AhuException("Error in bind configuration '"+string(current_filename)+"' on line "+itoa(linenumber)+": "+str);
+}
+
+extern FILE *yyin;
+static BindParser *parent;
+BindDomainInfo s_di;
+
+void BindParser::parse(const string &fname)
+{      
+       yydebug=0;
+       yyin=fopen(fname.c_str(),"r");
+
+       if(!yyin)
+               throw AhuException("Unable to open '"+fname+"': "+strerror(errno));
+
+       linenumber=1;
+       parent=this;
+       extern char *current_filename;
+       extern char *original_filename;
+
+       current_filename=original_filename=(char*)fname.c_str();
+
+       yyparse();
+
+//     cerr<<"Need to parse "<<d_zonedomains.size()<<" zone statements"<<endl;
+}
+
+void BindParser::setDirectory(const string &dir)
+{
+       d_dir=dir;
+       bind_directory=d_dir.c_str();
+}
+
+const string &BindParser::getDirectory()
+{
+       return d_dir;
+}
+
+const vector<BindDomainInfo>& BindParser::getDomains()
+{
+       return d_zonedomains;
+}
+
+void BindParser::setVerbose(bool verbose)
+{
+  d_verbose=verbose;
+}
+
+void BindParser::commit(BindDomainInfo DI)
+{
+  if(DI.filename[0]!='/')
+    DI.filename=d_dir+"/"+DI.filename;
+
+  if(d_verbose)
+    cerr<<"Domain "<<DI.name<<" lives in file '"<<DI.filename<<"'"<<endl;
+
+  d_zonedomains.push_back(DI);
+}
+
+%}
+
+%token WORD QUOTEDWORD OBRACE EBRACE SEMICOLON ZONETOK FILETOK OPTIONSTOK
+%token DIRECTORYTOK ACLTOK LOGGINGTOK CLASSTOK TYPETOK MASTERTOK
+
+%%
+
+root_commands:
+       |        
+       root_commands root_command SEMICOLON
+       ;
+
+root_command: command | acl_command | zone_command | options_command
+       ;
+
+commands:
+       |
+       commands command SEMICOLON
+       ;
+
+command:
+       terms 
+       ;
+
+zone_command:
+       ZONETOK quotedname zone_block
+       {
+               s_di.name=$2;
+               parent->commit(s_di);
+               s_di.clear();
+       }
+       |       
+       ZONETOK quotedname WORD zone_block
+       {
+               s_di.name=$2;
+               parent->commit(s_di);
+               s_di.clear();
+       }
+       ;
+
+
+options_command:
+       OPTIONSTOK OBRACE options_commands EBRACE
+       |
+       LOGGINGTOK OBRACE options_commands EBRACE
+       ;
+
+acl_command:
+       ACLTOK quotedname acl_block |   ACLTOK filename acl_block
+       ;
+
+acl_block: OBRACE acls EBRACE
+       ;
+       
+acls: 
+       |
+       acl SEMICOLON acls
+       ;
+
+acl:
+       WORD
+       ;
+
+options_commands:
+       |
+       options_command SEMICOLON options_commands
+       ;
+
+options_command: command | options_directory_command
+       ;
+
+options_directory_command: DIRECTORYTOK quotedname
+       {
+               parent->setDirectory($2);
+       }
+       ;
+
+
+terms: /* empty */
+       |
+       terms term
+       ;
+
+term: WORD | block | quotedname
+       ;
+block: 
+       OBRACE commands EBRACE 
+       ;
+
+zone_block:
+       OBRACE zone_commands EBRACE
+       ;
+
+zone_commands: 
+       |
+       zone_commands zone_command SEMICOLON
+       ;
+
+zone_command: command | zone_file_command | zone_type_command | zone_masters_command
+       ;
+
+zone_masters_command: MASTERTOK OBRACE masters EBRACE
+       ;
+
+masters: /* empty */
+       | 
+       masters master SEMICOLON 
+       ;
+
+master: WORD
+       {
+               s_di.master=$1;
+       }
+       ;
+
+zone_file_command:
+       FILETOK quotedname
+       {
+         //            printf("Found a filename: '%s'\n",$2);
+               s_di.filename=$2;
+       }
+       ;
+
+zone_type_command:
+       TYPETOK WORD
+       {
+         //            printf("Found a filename: '%s'\n",$2);
+         //            ztype=$2;
+       }
+       ;
+
+
+quotedname:
+       QUOTEDWORD
+       {
+               $$=$1;
+       }
+       ;
+
+filename: WORD
+       ;
\ No newline at end of file
diff --git a/pdns/backends/bind/huffman.cc b/pdns/backends/bind/huffman.cc
new file mode 100644 (file)
index 0000000..4e7e2d9
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <string>
+#include "huffman.hh"
+#include <bitset>
+#include <map>
+#include <sstream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+#include <utility>
+
+void HuffmanCodec::set(char c,const string &code)
+{
+  d_dict[c]=code;
+}
+
+HuffmanCodec::HuffmanCodec()
+{
+  d_dict.clear();
+  set('6',"0000");
+  set('5',"0001");
+  set(0,"0010");
+  set('3',"0011");
+  set('4',"0100");
+  set('s',"0101");
+  set('n',"011");
+  set('c',"100000");
+  set('u',"100001");
+  set('-',"1000100");
+  set('1',"1000101");
+  set('f',"1000110");
+  set('j',"10001110");
+  set('9',"1000111100");
+  set('*',"100011110100");
+  set('q',"100011110101");
+  set('7',"10001111011");
+  set('8',"100011111");
+  set('o',"10010");
+  set('t',"10011");
+  set('e',"1010");
+  set('a',"10110");
+  set('r',"10111");
+  set('d',"110000");
+  set('2',"1100010");
+  set('k',"1100011");
+  set('.',"110010");
+  set('v',"1100110");
+  set('w',"1100111");
+  set('i',"1101");
+  set('l',"111000");
+  set('p',"1110010");
+  set('b',"1110011");
+  set('z',"111010000");
+  set('y',"111010001");
+  set('x',"11101001");
+  set('h',"1110101");
+  set('m',"1110110");
+  set('g',"1110111");
+  set('0',"1111");
+
+  d_min=10000;
+  d_max=0;
+  d_rdict.resize(128);
+  for(map<char,string>::const_iterator i=d_dict.begin();i!=d_dict.end();++i) {
+    d_min=min(d_min,i->second.length());
+    d_max=max(d_max,i->second.length());
+
+    (d_rdict[i->second.length()])[i->second]=i->first;
+  }
+  d_last_compressed=d_last_out="";
+  d_passthrough=false;
+}
+
+void HuffmanCodec::passthrough(bool shoulddo)
+{
+  d_passthrough=shoulddo;
+}
+
+
+//       Bitify input: 1001101110101001000101
+//Decode got offered: '1001101110101001'
+
+
+void HuffmanCodec::decode(const string &compressed, string &out)
+{
+  if(d_passthrough) {
+    out=compressed;
+    return;
+  }
+  if(compressed==d_last_compressed) {
+    out=d_last_out;
+    return;
+  }
+  string full;
+
+  out="";
+  unbitify(compressed, full);
+  //  cout<<"Decode got offered: '"<<full<<"'"<<endl;
+
+  unsigned int pos=0;
+  size_t cleft=full.length();
+  size_t mlen;
+  out.reserve(full.length()/5);
+  while(cleft) {
+    map<string,char>::const_iterator i;
+
+    for(mlen=d_min;mlen<=cleft && mlen<=d_max;++mlen) {
+      if(d_rdict[mlen].empty())
+       continue;
+
+      i=d_rdict[mlen].find(full.substr(pos,mlen));
+
+      if(i!=d_rdict[mlen].end()) { // match 
+       if(!i->second) {
+         d_last_compressed=compressed;
+         d_last_out=out;
+         return;
+       }
+
+       out.append(1,i->second);
+
+       pos+=mlen;
+       cleft-=mlen;
+       break;
+      }
+    }
+  }
+  if(cleft)
+    throw AhuException("Unable to parse huffman symbol "+full.substr(pos));
+  d_last_compressed=compressed;
+  d_last_out=out;
+}
+
+void HuffmanCodec::encode(const string &in, string &out)
+{
+  if(d_passthrough) {
+    out=in;
+    return;
+  }
+  string full;
+  for(string::const_iterator i=in.begin();i!=in.end();++i) {
+    map<char,string>::const_iterator j=d_dict.find(tolower(*i));
+    if(j==d_dict.end()) {
+      string c;
+      char cc=tolower(*i);
+      c.append(1,cc);
+      throw AhuException("Trying to huffman encode an unknown symbol '"+c+"'");
+    }
+    full.append(j->second);
+  }
+  full.append(d_dict[0]);
+  bitify(full,out);
+  //  cout<<"full: "<<full<<endl;
+}
+
+void HuffmanCodec::bitify(const string &full, string &out)
+{
+  unsigned char bitpos=0;
+  unsigned char curbyte=0;
+  //  cout<<"Bitify input: "<<full<<endl;
+  for(string::const_iterator i=full.begin();i!=full.end();++i) {
+    curbyte|= (*i=='1')<<(7-bitpos);
+    if(bitpos++==7) {
+      out.append(1,curbyte);
+      bitpos=0;
+      curbyte=0;
+    }
+  }
+  out.append(1,curbyte);
+}
+
+void HuffmanCodec::unbitify(const string &in, string &full) 
+{
+  bitset<8> byte;
+  ostringstream os;
+  full.reserve(in.length()*8);
+  for(string::const_iterator i=in.begin();i!=in.end();++i) {
+    byte=*i;
+    os<<byte;
+  }
+  full.append(os.str());
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+  string in(argv[1]);
+  string compressed;
+
+  try {
+    HuffmanCodec hc;
+    //  hc.initDictionary(dict);
+    //    cout<<"in: "<<in.length()<<endl;
+    hc.encode(in,compressed);
+    // cout<<"compressed: "<<compressed.length()<<endl;
+    //    cout<<"Compressed: '"<<compressed<<"'"<<endl;
+    
+    string out;
+    hc.decode(compressed,out);
+    
+    cout<<"'"<<out<<"'"<<endl;
+  }
+  catch(AhuException &ae) {
+    cerr<<"Fatal error: "<<ae.reason<<endl;
+  }
+}
+#endif
diff --git a/pdns/backends/bind/huffman.hh b/pdns/backends/bind/huffman.hh
new file mode 100644 (file)
index 0000000..8475820
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_HUFFMAN
+#define PDNS_HUFFMAN
+#include <string>
+#include <bitset>
+#include <map>
+#include <sstream>
+#include <vector>
+#include "../../ahuexception.hh"
+
+using namespace std;
+
+class HuffmanCodec
+{
+public:
+  HuffmanCodec();
+  void encode(const string &in, string &out);
+  void decode(const string &compressed, string &out);
+  void passthrough(bool);
+  string decode(const string &in) {
+    string tmp;
+    decode(in,tmp);
+    return tmp;
+  }
+private:
+  void bitify(const string &full, string &out);
+  void unbitify(const string &in, string &full);
+  void set(char c,const string &code);
+  map<char,string> d_dict;
+  vector<map<string,char> >d_rdict;
+  size_t d_min, d_max;
+  string d_last_compressed;
+  string d_last_out;
+  bool d_passthrough;
+};
+#endif /* PDNS_HUFFMAN */
diff --git a/pdns/backends/bind/ylwrap b/pdns/backends/bind/ylwrap
new file mode 100755 (executable)
index 0000000..5ea68e4
--- /dev/null
@@ -0,0 +1,143 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+# Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program 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, 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# 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.
+
+# Usage:
+#     ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+# * INPUT is the input file
+# * OUTPUT is file PROG generates
+# * DESIRED is file we actually want
+# * PROGRAM is program to run
+# * ARGS are passed to PROG
+# Any number of OUTPUT,DESIRED pairs may be used.
+
+# The input.
+input="$1"
+shift
+case "$input" in
+ [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+ *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+# The directory holding the input.
+input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+# Quote $INPUT_DIR so we can use it in a regexp.
+# FIXME: really we should care about more than `.' and `\'.
+input_rx=`echo "$input_dir" | sed -e 's,\\\\,\\\\\\\\,g' -e 's,\\.,\\\\.,g'`
+
+echo "got $input_rx"
+
+pairlist=
+while test "$#" -ne 0; do
+   if test "$1" = "--"; then
+      shift
+      break
+   fi
+   pairlist="$pairlist $1"
+   shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+$prog ${1+"$@"} "$input"
+status=$?
+
+if test $status -eq 0; then
+   set X $pairlist
+   shift
+   first=yes
+   # Since DOS filename conventions don't allow two dots,
+   # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+   # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+   y_tab_nodot="no"
+   if test -f y_tab.c || test -f y_tab.h; then
+      y_tab_nodot="yes"
+   fi
+
+   while test "$#" -ne 0; do
+      from="$1"
+      # Handle y_tab.c and y_tab.h output by DOS
+      if test $y_tab_nodot = "yes"; then
+        if test $from = "y.tab.c"; then
+           from="y_tab.c"
+        else
+           if test $from = "y.tab.h"; then
+              from="y_tab.h"
+           fi
+        fi
+      fi
+      if test -f "$from"; then
+         # If $2 is an absolute path name, then just use that,
+         # otherwise prepend `../'.
+         case "$2" in
+          [\\/]* | ?:[\\/]*) target="$2";;
+          *) target="../$2";;
+        esac
+
+        # Edit out `#line' or `#' directives.  We don't want the
+        # resulting debug information to point at an absolute srcdir;
+        # it is better for it to just mention the .y file with no
+        # path.
+        sed -e "/^#/ s,$input_rx,," "$from" > "$target" || status=$?
+      else
+        # A missing file is only an error for the first file.  This
+        # is a blatant hack to let us support using "yacc -d".  If -d
+        # is not specified, we don't want an error when the header
+        # file is "missing".
+        if test $first = yes; then
+           status=1
+        fi
+      fi
+      shift
+      shift
+      first=no
+   done
+else
+   status=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $status
diff --git a/pdns/backends/bind/zone2sql.cc b/pdns/backends/bind/zone2sql.cc
new file mode 100644 (file)
index 0000000..b55cf2e
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/* accepts a named.conf as parameter and outputs heaps of sql */
+
+// $Id: zone2sql.cc,v 1.1 2002/11/27 15:18:39 ahu Exp $ 
+#ifdef WIN32
+# pragma warning ( disable: 4786 )
+# include <unistd.h>
+#endif // WIN32
+
+#include <string>
+#include <map>
+
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+
+#include "dns.hh"
+#include "arguments.hh"
+#include "zoneparser.hh"
+#include "bindparser.hh"
+#include "statbag.hh"
+#include "misc.hh"
+
+StatBag S;
+
+string sqlstr(const string &str)
+{
+  if(str.find("\'")!=string::npos)
+    throw 0;
+
+  string ret="\'";
+  ret+=str;
+  ret+="\'";
+  return ret;
+}
+
+static int dirty_hack_num;
+
+enum dbmode_t {MYSQL=0,ORACLE=1,BARE=2,POSTGRES=3};
+dbmode_t mode;
+bool g_intransaction;
+
+static int num_records;
+static string lastsoa_qname;
+static void callback(const string &domain, const string &qtype, const string &content, int ttl, int prio)
+{
+  static int lastsoa_domain_id=-1;
+
+  num_records++;
+
+  if(qtype=="SOA") {
+    if(dirty_hack_num==lastsoa_domain_id && lastsoa_qname!=domain) {
+      dirty_hack_num++;
+      cerr<<"Second SOA in zone, raised domain_id"<<endl;
+      if(mode==POSTGRES || mode==ORACLE) {
+       if(g_intransaction && arg().mustDo("transactions")) {
+         cout<<"COMMIT WORK;"<<endl;
+       }
+       if(arg().mustDo("transactions")) {
+         if(mode==POSTGRES)
+           cout<<"BEGIN TRANSACTION;"<<endl;
+         g_intransaction=1;
+       }
+       
+       if(mode==POSTGRES) {
+         cout<<"insert into domains (name,type) values ("<<sqlstr(domain)<<",'NATIVE');"<<endl;
+       }
+       else if(mode==ORACLE) {
+         cout<<"insert into domains (id,name,type) values (domains_id_sequence.nextval,"<<toLower(sqlstr(domain))<<",'NATIVE');"<<endl;
+       }
+      }
+    }
+    lastsoa_qname=domain;
+  }
+  
+  lastsoa_domain_id=dirty_hack_num;
+
+  if(mode==MYSQL) {
+    cout<<"insert into records (domain_id, name,type,content,ttl,prio) values ("<< dirty_hack_num<<", "<<
+      sqlstr(ZoneParser::canonic(domain))<<", "<<
+      sqlstr(qtype)<<", "<<
+      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<<");\n";
+  }
+  if(mode==POSTGRES) {
+    cout<<"insert into records (domain_id, name,type,content,ttl,prio) select id ,"<<
+      sqlstr(toLower(ZoneParser::canonic(domain)))<<", "<<
+      sqlstr(qtype)<<", "<<
+      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<< 
+      " from domains where name="<<toLower(sqlstr(lastsoa_qname))<<";\n";
+  }
+  else if(mode==ORACLE) {
+    cout<<"insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,"<<
+      sqlstr(toLower(ZoneParser::canonic(domain)))<<", "<<
+      sqlstr(qtype)<<", "<<
+      sqlstr(ZoneParser::canonic(content))<<", "<<ttl<<", "<<prio<< 
+      " from Domains where name="<<toLower(sqlstr(lastsoa_qname))<<";\n";
+  }
+  else if(mode==BARE) {
+    cout<< dirty_hack_num<<"\t"<<
+      sqlstr(ZoneParser::canonic(domain))<<"\t"<<
+      sqlstr(qtype)<<"\t"<<sqlstr(ZoneParser::canonic(content))<<"\t"<<prio<<"\t"<<ttl<<"\n";
+  }
+
+}
+
+
+/* 2 modes of operation, either --named or --zone (the latter needs $ORIGIN) 
+   2 further modes: --mysql or --oracle 
+   and a parameter: --start-id
+*/
+
+ArgvMap &arg()
+{
+  static ArgvMap theArg;
+  return theArg;
+}
+
+
+int main(int argc, char **argv)
+{
+  try {
+#if __GNUC__ >= 3
+    ios_base::sync_with_stdio(false);
+#endif
+
+    arg().setSwitch("mysql","Output in format suitable for mysqlbackend")="yes";
+    arg().setCmd("gpgsql","Output in format suitable for default gpgsqlbackend");
+    arg().setCmd("gmysql","Output in format suitable for default gmysqlbackend");
+    arg().setCmd("oracle","Output in format suitable for the oraclebackend");
+    arg().setCmd("bare","Output in a bare format, suitable for further parsing");
+    arg().setSwitch("verbose","Verbose comments on operation")="no";
+    arg().setSwitch("slave","Keep BIND slaves as slaves")="no";
+    arg().setSwitch("transactions","If target SQL supports it, use transactions")="no";
+    arg().setSwitch("on-error-resume-next","Continue after errors")="no";
+    arg().set("start-id","Value of first domain-id")="0";
+    arg().set("zone","Zonefile with $ORIGIN to parse")="";
+    arg().set("zone-name","Specify an $ORIGIN in case it is not present")="";
+    arg().set("named-conf","Bind 8 named.conf to parse")="";
+
+    arg().setCmd("help","Provide a helpful message");
+
+    S.declare("logmessages");
+
+    string namedfile="";
+    string zonefile="";
+
+    arg().parse(argc, argv);
+  
+    if(argc<2 || arg().mustDo("help")) {
+      cerr<<"syntax:"<<endl<<endl;
+      cerr<<arg().helpstring()<<endl;
+      exit(1);
+    }
+  
+    if(arg().mustDo("mysql")) 
+      mode=MYSQL;
+    if(arg().mustDo("gpgsql") || arg().mustDo("gmysql"))
+      mode=POSTGRES;
+    if(arg().mustDo("bare"))
+      mode=BARE;
+    if(arg().mustDo("oracle")) {
+      mode=ORACLE;
+      if(!arg().mustDo("transactions"))
+       cout<<"set autocommit on;"<<endl;
+    }
+
+
+    dirty_hack_num=arg().asNum("start-id");
+    namedfile=arg()["named-conf"];
+    zonefile=arg()["zone"];
+
+    int count=0;
+
+    if(zonefile.empty()) {
+      BindParser BP;
+      BP.setVerbose(arg().mustDo("verbose"));
+      BP.parse(namedfile.empty() ? "./named.conf" : namedfile);
+    
+      ZoneParser ZP;
+    
+      const vector<BindDomainInfo> &domains=BP.getDomains();
+
+      int numdomains=domains.size();
+      int tick=numdomains/100;
+      ZP.setDirectory(BP.getDirectory());
+      ZP.setCallback(&callback);  
+    
+      for(vector<BindDomainInfo>::const_iterator i=domains.begin();
+         i!=domains.end();
+         ++i)
+       {
+         try {
+           if(mode==POSTGRES || mode==ORACLE) {
+             if(g_intransaction && arg().mustDo("transactions")) {
+               cout<<"COMMIT WORK;"<<endl;
+             }
+             if(arg().mustDo("transactions")) {
+               if(mode==POSTGRES)
+                 cout<<"BEGIN TRANSACTION;"<<endl;
+               g_intransaction=1;
+             }
+
+             if(mode==POSTGRES) {
+               if(arg().mustDo("slave")) {
+                 if(i->master.empty())
+                   cout<<"insert into domains (name,type) values ("<<sqlstr(i->name)<<",'NATIVE');"<<endl;
+                 else
+                   cout<<"insert into domains (name,type,master) values ("<<sqlstr(i->name)<<",'SLAVE'"<<", '"<<i->master<<"');"<<endl;
+               }
+               else
+                 cout<<"insert into domains (name,type) values ("<<sqlstr(i->name)<<",'NATIVE');"<<endl;
+             }
+             else if(mode==ORACLE) {
+               cout<<"insert into domains (id,name,type) values (domains_id_sequence.nextval,"<<toLower(sqlstr(i->name))<<",'NATIVE');"<<endl;
+             }
+             lastsoa_qname=i->name;
+           }
+           ZP.parse(i->filename,i->name);
+         }
+         catch(AhuException &ae) {
+           if(!arg().mustDo("on-error-resume-next"))
+             throw;
+           else
+             cerr<<ae.reason<<endl;
+         }
+
+         dirty_hack_num++;
+         if(!tick || !((count++)%tick))
+           cerr<<"\r"<<count*100/numdomains<<"% done ("<<i->filename<<")\033\133\113";
+       }
+      cerr<<"\r100% done\033\133\113"<<endl;
+    }
+    else {
+      ZoneParser ZP;
+      ZP.setDirectory(".");
+      ZP.setCallback(&callback);  
+      ZP.parse(zonefile,arg()["zone-name"]);
+      dirty_hack_num++;
+    }
+    cerr<<"Parsed "<<num_records<<" records"<<endl;
+    
+  }
+  catch(AhuException &ae) {
+    cerr<<"Fatal error: "<<ae.reason<<endl;
+    return 0;
+  }
+  
+  if((mode==POSTGRES || mode==ORACLE) && arg().mustDo("transactions") && g_intransaction)
+    cout<<"COMMIT WORK;"<<endl;
+  return 1;
+
+}
diff --git a/pdns/backends/bind/zoneparser.hh b/pdns/backends/bind/zoneparser.hh
new file mode 100644 (file)
index 0000000..76258ce
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef ZONEPARSER_HH
+#define ZONEPARSER_HH
+#include <string>
+#include <map>
+#include <vector>
+#include <time.h>
+
+using namespace std;
+
+class ZoneParser
+{
+ public:
+  struct Record
+  {
+    string name;
+    string qtype;
+    string content;
+    int ttl;
+    int prio;
+  };
+  ZoneParser() : d_ttl(3600) {}
+  ~ZoneParser();
+  void parse(const string &fname,const string &origin);
+  void parse(const string &fname,const string &origin, vector<Record>&records);
+  
+  typedef void callback_t(const string &domain, const string &qtype, const string &content, int ttl, int prio);
+  void setCallback(callback_t *callback);
+  callback_t *d_callback;
+  bool parseLine(const vector<string>&words, vector<Record> &);
+  bool eatLine(string line, vector<Record>&);
+  void setDirectory(const string &dir);
+  static string canonic(const string& dom);
+    
+private:
+  unsigned int zoneNumber(const string &str);
+  string d_filename;
+  string d_dir;
+  unsigned int d_lineno;
+  void soaCanonic(string &content);
+  bool isNumber(const string &);
+  bool isType(const string &);
+  bool isClass(const string &);
+  string d_origin;
+  time_t d_ttl;
+  void cutOff(string &line, const string &delim);
+  void fillRec(const string &qname, const string &qtype, const string &content, int ttl, int prio, vector<Record>&rec);
+  string expandWord(const string &line, int value);
+};
+
+
+#endif /* BINDPARSER_HH */
diff --git a/pdns/backends/bind/zoneparser2.cc b/pdns/backends/bind/zoneparser2.cc
new file mode 100644 (file)
index 0000000..49b7cfa
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+\r
+#ifdef WIN32\r
+# pragma warning ( disable: 4786 )\r
+#endif // WIN32\r
+\r
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <utility>
+#include <ctype.h>
+#include <errno.h>
+#include <stack>\r
+#include "utility.hh"
+#include "misc.hh"
+#include "ahuexception.hh"
+#include <algorithm>
+using namespace std;
+
+#include "zoneparser.hh"
+
+extern const char *bind_directory;
+void ZoneParser::setDirectory(const string &dir)
+{
+  d_dir=dir;
+
+}
+
+void ZoneParser::parse(const string &fname, const string &origin)
+{      
+  d_filename=fname.c_str();
+
+  FILE *zonein=fopen(fname.c_str(),"r");
+
+  if(!zonein)
+    throw AhuException("Unable to open zonefile '"+fname+"': "+stringerror());
+
+  d_origin=origin;
+  
+  char line[2048];
+  d_lineno=0;
+  vector<Record> rec;
+  stack<FILE *>fds;
+  fds.push(zonein);
+  while(!fds.empty()) {
+    while(fgets(line,2047,fds.top())) {
+      d_lineno++;
+      if(strstr(line, "$INCLUDE ")==line) {
+       vector<string> parts;
+       stringtok(parts,line," \t\n");
+       if(parts.size()!=2)
+         throw AhuException("Invalid $INCLUDE statement in zonefile '"+fname+"'");
+       
+       string filename=parts[1];
+       if(filename[0]!='/')
+         filename=d_dir+"/"+filename;
+
+
+       FILE *fp=fopen(filename.c_str(),"r");
+       if(!fp)
+         throw AhuException("Unable to open zonefile '"+filename+"' included from '"+fname+"': "+stringerror());
+       fds.push(fp);
+       continue;
+      }
+      if(eatLine(line,rec))
+       for(vector<Record>::const_iterator i=rec.begin();i!=rec.end();++i)
+         d_callback(i->name, i->qtype,i->content,i->ttl,i->prio);
+    }
+    fclose(fds.top());
+    fds.pop();
+  }
+}
+
+
+void ZoneParser::fillRec(const string &qname, const string &qtype, const string &content, int ttl, int prio, vector<Record>&recs)
+{
+  Record rec;
+  rec.name=qname;
+  rec.qtype=qtype;
+  rec.content=content;
+  rec.ttl=ttl;
+  rec.prio=prio;
+  recs.push_back(rec);
+
+}
+
+void ZoneParser::parse(const string &fname, const string &origin, vector<Record>&records)
+{      
+  d_filename=fname.c_str();
+
+  FILE *zonein=fopen(fname.c_str(),"r");
+
+  if(!zonein)
+    throw AhuException("Unable to open zonefile '"+fname+"': "+stringerror());
+
+  d_origin=origin;
+  
+  char line[2048];
+  d_lineno=0;
+  vector<Record> rec;
+  stack<FILE *>fds;
+  fds.push(zonein);
+  while(!fds.empty()) {
+    while(fgets(line,2047,fds.top())) {
+      d_lineno++;
+      if(strstr(line, "$INCLUDE ")==line) {
+       vector<string> parts;
+       stringtok(parts,line," \t\n");
+       if(parts.size()!=2)
+         throw AhuException("Invalid $INCLUDE statement in zonefile '"+fname+"'");
+
+
+       FILE *fp=fopen(parts[1].c_str(),"r");
+       if(!fp)
+         throw AhuException("Unable to open zonefile '"+parts[1]+"' included from '"+parts[1]+"': "+stringerror());
+       fds.push(fp);
+       continue;
+      }
+      if(eatLine(line,rec))
+       for(vector<Record>::const_iterator i=rec.begin();i!=rec.end();++i)
+         records.push_back(*i);
+    }
+    fclose(fds.top());
+    fds.pop();
+  }
+  
+
+}
+
+void ZoneParser::cutOff(string &line, const string &delim)
+{
+  unsigned int pos=line.find_first_of(delim);
+  if(pos==string::npos)
+    return;
+  line=line.substr(0,pos);
+}
+
+bool ZoneParser::eatLine(string line, vector<Record> &rec)
+{
+
+  rec.clear();
+  static string tline;
+  static string lastfirstword;
+  chomp(line," \x1a\r\n");
+  cutOff(line,";");
+  unsigned int pos=string::npos;
+
+  if(tline.empty()) {
+    pos=line.find("(");
+    if(pos!=string::npos) { // this is a line that continues
+      tline=line.substr(0,pos);
+      return false;
+    }
+    else 
+      tline=line; // complete & boring line
+  }
+  else { // continuation
+    pos=line.find(")");
+    if(pos==string::npos) { // middle part
+      tline.append(line);
+      return false;
+    }
+    else {
+      tline.append(line.substr(0,pos)); // end part, we have a complete line!
+    }
+  }
+  
+  // full & unparenthesised line now in tline!
+  //  cout<<"line: '"<<tline<<"'"<<endl;
+  if(tline.empty() || tline.find_first_not_of(" \t\n")==string::npos) {
+
+    tline="";
+    return false;
+  }
+
+  if(isspace(tline[0]))
+    tline=lastfirstword+"\t"+tline;
+
+  vector<string> parts;
+  stringtok(parts,tline," \t");
+  if(parts[0][0]!='$' && !isspace(parts[0][0]))
+    lastfirstword=parts[0];
+
+  //  for_each(parts.begin(),parts.end(),print);
+  tline="";
+  return parseLine(parts,rec);
+}
+
+ZoneParser::~ZoneParser()
+{
+
+}
+
+void ZoneParser::setCallback(callback_t *callback)
+{
+       d_callback=callback;
+}
+
+bool ZoneParser::isNumber(const string &s)
+{
+  for(string::const_iterator i=s.begin();
+      i!=s.end();
+      ++i) {
+    if(i+1==s.end())
+      if(*i=='M' || *i=='D' || *i=='H' || *i=='W' || *i=='m' || *i=='d' || *i=='h' || *i=='w') // last character
+       continue;
+    if(!isdigit(*i))
+      return false;
+  }
+  return true;
+}
+
+bool ZoneParser::isType(const string &s)
+{
+  if(isNumber(s))
+    return false;
+
+  if(isClass(s))
+    return false;
+
+
+  return true;
+}
+
+bool ZoneParser::isClass(const string &s)
+{
+  return (s=="IN" || s=="CH" || s=="HS");
+}
+
+unsigned int ZoneParser::zoneNumber(const string &str)
+{
+  unsigned int val=atoi(str.c_str());
+  char lc=toupper(str[str.length()-1]);
+  if(!isdigit(lc))
+    switch(lc) {
+    case 'H':
+      val*=3600;
+      break;
+    case 'D':
+      val*=3600*24;
+      break;
+    case 'W':
+      val*=3600*24*7;
+      break;
+    case 'M':
+      val*=3600*24*7*4;
+      break;
+    case 'Y': // ? :-)
+      val*=3600*24*365;
+      break;
+    default:
+      throw AhuException("Unable to parse "+d_origin+" time specification '"+str+"'");
+    }
+  return val;
+
+}
+
+/** this parser handles 10 cases (sigh)
+    1) qname TTL CLASS QTYPE *
+    2) qname CLASS TTL QTYPE *
+    3) qname CLASS QTYPE *
+    4) qname TTL QTYPE *
+    5) qname QTYPE *
+
+    And then everything again with a space first character, which implies 'same as last name'
+*/
+
+void ZoneParser::soaCanonic(string &content)
+{
+  vector<string>parts;
+  stringtok(parts,content," \t");
+  int pos=0;
+
+  // 'ns.naamserver.net. hostmaster.naamserver.net 2001102501 8H 2H 1W 1D'
+
+  string newcontent;
+  for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i,++pos) {
+    if(pos<3) {
+      if(pos)
+       newcontent.append(1,' ');
+      newcontent.append(*i);
+    }
+    else {
+      unsigned int val=zoneNumber(*i);
+
+      newcontent.append(1,' ');
+      newcontent.append(itoa(val));
+    }
+  }
+  content=newcontent;
+}
+
+string ZoneParser::expandWord(const string &line, int value)
+{
+  string newline;
+  bool escape=false;
+  for(string::const_iterator i=line.begin();i!=line.end();++i) {
+    if(*i=='\\')
+      escape=true;
+    else{
+      if(!escape && *i=='$') {
+       if(i+2<line.end() && *(i+1)=='{') { // shit
+         string::const_iterator k=(i+=2);
+         while(k++!=line.end() && *k!='}')
+           ;
+         if(k==line.end())
+           throw AhuException("Malformed $GENERATE statement");
+
+         string spec;
+         
+         //copy(i,k,back_inserter(spec));\r
+    for ( string::const_iterator a = i; a != k; ++a )\r
+      spec += *a;\r
+\r
+         vector<string> partjes;
+         stringtok(partjes,spec,",");
+         if(partjes.empty())
+           throw AhuException("Malformed $GENERATE statement: '"+spec+"'");
+         
+         value+=atoi(partjes[0].c_str());
+         int width=0;
+         char radix='d';
+         if(partjes.size()>=2)
+           width=atoi(partjes[1].c_str());
+         if(partjes.size()>=3)
+           radix=partjes[2][0];
+
+         char tmp[20];
+         string format;
+         format="%0";
+         format+=itoa(width);
+         format.append(1,radix);
+         
+         snprintf(tmp,19,format.c_str(),value);
+
+         newline.append(tmp);
+         i=k;
+       }
+       else
+         newline.append(itoa(value));
+      }
+      else
+       newline.append(1,*i);
+      escape=false;
+    }
+  }
+  return newline;
+}
+
+string ZoneParser::canonic(const string& dom)
+{
+  if(dom[dom.size()-1]!='.')
+    return dom;
+
+  return dom.substr(0,dom.size()-1);
+
+}
+
+
+bool ZoneParser::parseLine(const vector<string>&words, vector<Record>&rec)
+{
+  int cpos=0;
+  if(!words.size())
+    return false;
+
+  if(words[0][0]=='$')
+    {
+    if(!Utility::strcasecmp(words[0].c_str(),"$ORIGIN") && words.size()>1) {
+       d_origin=canonic(words[1]);
+      }
+      else if(!Utility::strcasecmp(words[0].c_str(),"$TTL") && words.size()>1) {
+       d_ttl=zoneNumber(words[1]);
+      }
+      else if(!Utility::strcasecmp(words[0].c_str(),"$GENERATE") && words.size()>1) {
+       // $GENERATE 1-127 $ CNAME $.0
+       string range=words[1];  // 1-127 means 1...127 (including 127). 1-127/2 is 1..3..5..
+       vector<string>parts;
+       stringtok(parts,range,"-/");
+       if(parts.size()<2 || parts.size()>3)
+         throw AhuException("Malformed $GENERATE on line "+itoa(d_lineno)+" of "+d_filename);
+
+       int start, stop, step=1;
+       start=atoi(parts[0].c_str());
+       stop=atoi(parts[1].c_str());
+       if(parts.size()==3)
+         step=atoi(parts[2].c_str());
+       vector<string>newwords;
+
+       for(int i=start;i<stop;++i) {
+         newwords.clear();
+         for(unsigned int j=2;j<words.size();++j) {
+           newwords.push_back(expandWord(words[j],i));
+         }
+         parseLine(newwords, rec);
+       }
+       return true;
+      }
+      else {
+       throw AhuException("Unhandled command '"+words[0]+"' on line "+itoa(d_lineno)+" of "+d_filename);
+      }
+      
+      return false;
+
+    }
+  if(words.size()<3)
+    {
+      if(words.size()==1 && words[0]==";")
+       return false;
+      cerr<<"Short line: "<<words.size()<<" words. Probably due to repeated record without domainname"<<endl;
+      cerr<<"'"<<words[0]<<"'"<<endl;
+      return false;
+    }
+
+  string qname=words[0];
+  string qclass="IN";
+  int ttl=d_ttl;
+  string qtype="NONE";
+  if(isNumber(words[1])) // 1 || 4
+    {
+      ttl=zoneNumber(words[1]);
+      if(isClass(words[2])) 
+       {
+//       cout<<1<<endl;
+         qclass=words[2];
+         qtype=words[3];
+         cpos=4;
+         // 1
+       }
+      else
+       {
+//       cout<<4<<endl;
+
+         qtype=words[2];
+         cpos=3;
+         // 4
+       }
+    }
+  else /* 2 || 3 || 5 */
+    {
+      if(!isClass(words[1]))
+       {
+
+         qtype=words[1];
+         cpos=2;
+//       cout<<5<<endl;
+         // 5
+       }
+      else // 2 || 3
+       {
+         qclass=words[1];
+         if(isNumber(words[2])) 
+           {
+             ttl=zoneNumber(words[2]);
+             qtype=words[3];
+//           cout<<2<<endl;
+             cpos=4;
+             // 2
+           }
+         else if(isType(words[2]))
+           {
+             qtype=words[2];
+//           cout<<4<<endl;
+             cpos=3;
+             // 4
+           }
+       }
+      
+    }
+  if(!cpos)
+    {
+      cerr<<"Funky parse case!"<<endl;
+    }
+
+  if(qname=="@")
+    qname=d_origin;
+  else
+    if(qname[qname.size()-1]!='.')
+      qname+="."+d_origin;
+
+
+//  cerr<<qname<<", "<<qclass<<", "<<qtype<<", "<<ttl<<", rest from field "<<cpos<<endl;
+         
+  int left=words.size()-cpos;
+  string content;
+
+  if(qtype=="MX" && left==2)
+    {
+      int prio=atoi(words[cpos++].c_str());
+      content=words[cpos];
+      if(content=="@")
+       content=d_origin;
+      else
+       if(content[content.size()-1]!='.')
+         content+="."+d_origin;
+
+      fillRec(qname, qtype, content, ttl, prio,rec);
+      return true;
+    }
+  else if(left)
+    {
+      content=words[cpos++];left--;
+
+      while(left--)
+       content+=" "+words[cpos++];
+
+      if(qtype=="MX" || qtype=="CNAME" || qtype=="NS") {
+       if(content=="@")
+         content=d_origin;
+       else
+         if(content[content.size()-1]!='.')
+           content+="."+d_origin;
+      }
+      if(qtype=="SOA")
+       soaCanonic(content);
+
+      fillRec(qname, qtype, content,ttl, 0, rec);
+      return true;
+    }
+  else
+    {
+      cerr<<"NO CONTENT!"<<endl;
+    }
+  return false;
+}
+
+
diff --git a/pdns/binpatch.cc b/pdns/binpatch.cc
new file mode 100644 (file)
index 0000000..498dd1b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+#include <errno.h>
+#include <climits>
+#include <string>
+#include <map>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+
+
+using namespace std;
+
+static void imbue(char *pname, const char *search, const string &replace);
+static string stringerror();
+static off_t filesize(int fd);
+
+int main(int argc, char **argv)
+{
+  if(argc!=3) {
+    cerr<<"Syntax: binpatch binary configuration-directory"<<endl;
+    exit(0);
+  }
+
+  imbue(argv[1],"!@@SYSCONFDIR@@:",argv[2]);
+}
+
+static void imbue(char *pname, const char *search, const string &replace)
+{
+  int fd=open(pname, O_RDWR);
+  if(fd<0) {
+    cerr<<"Unable to open executable read/write for imbuing: "<<stringerror()<<endl;
+    exit(1);
+  }
+  int fs=filesize(fd);
+  void *ptr=mmap(0,fs,PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if(ptr==(caddr_t)-1) {
+    cerr<<"Unable to mmap executable read/write for imbuing: "<<stringerror()<<endl;
+    exit(1);
+  }
+  
+  char *p=(char *)ptr;
+  char *end=p+fs;
+  for(;p<end;++p) 
+    if(*p==*search && *(p+1)==*(search+1) && !memcmp(p,search,strlen(search)))
+      break;
+
+  if(p==end) {
+    cerr<<"Cannot find marker in binary, not imbueing"<<endl;
+    exit(1);
+  }
+  strcpy(p+strlen(search),replace.c_str());
+  munmap(ptr,filesize(fd));
+  close(fd);
+  cerr<<"Imbued configuration location '"<<replace<<"'"<<endl;
+  return;
+}
+
+static off_t filesize(int fd)
+{
+  struct stat buf;
+  fstat(fd, &buf);
+  return buf.st_size;
+}
+static string stringerror()
+{
+  return strerror(errno);
+}
diff --git a/pdns/bootstrap b/pdns/bootstrap
new file mode 100755 (executable)
index 0000000..dc8a7a9
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+echo Please ignore this warning when you see it:
+echo warning: AC_TRY_RUN called without default to allow cross compiling
+echo
+
+
+aclocal
+autoheader
+automake --add-missing --foreign
+autoconf
+
diff --git a/pdns/buildroot.sh.in b/pdns/buildroot.sh.in
new file mode 100755 (executable)
index 0000000..f217ece
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+prefix=@prefix@
+
+echo building PowerDNS chroot in $prefix
+echo -n "Copying libraries: "
+cp $(./finddeps ahudns resolver dynloader /bin/sh) $prefix/lib
+echo done
+echo -n "Copying in /bin/sh: "
+cp /bin/sh $prefix/bin
+echo done
+
+preprefix=$(echo $prefix | sed s/$(basename $prefix)//)
+
+echo -n "Making tmp and pre-prefix in root: "
+mkdir -p $prefix/tmp $prefix/$preprefix
+echo "done"
+echo -n "Creating $prefix in $prefix: "
+cd $prefix/$preprefix
+ln -s .. $(basename $prefix)
+cd -
+echo done
+echo -n "Creating launch script: "
+echo \#\!/bin/sh > $prefix/launch
+echo cd $prefix >> $prefix/launch 
+echo export ORACLE_HOME=$prefix/oracle >> $prefix/launch
+echo chroot . ./bin/ahudns >> $prefix/launch
+chmod +x $prefix/launch
+echo done
+
diff --git a/pdns/choosepaths b/pdns/choosepaths
new file mode 100755 (executable)
index 0000000..cbe3235
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+IB="dialog --inputbox"
+MB="dialog --msgbox"
+YN="dialog --yesno"
+
+. ./pathconfig
+
+$MB "\nWelcome to the PowerDNS installation program!\n\nPlease select \
+locations for the different PowerDNS files." 11 60
+
+redo=1
+while [ "$redo" = "1" ]
+do
+echo $redo
+
+askPath()
+{
+       val=`eval echo \\$$2`
+       $IB "$1\n\n" 10 60 $val 2> ./dialog.tmp
+       if [ "$?" != "0" ] ; then exit ; fi
+       eval $2=`cat ./dialog.tmp`
+}
+
+askPath "Intended location of your init.d scripts" INITDPATH
+askPath "Intended location of your binaries" BINARYPATH 
+askPath "Intended location of your configuration files" CONFIGPATH  
+askPath "Intended location of the controlsocket directory" SOCKETPATH 
+askPath "Intended location of the PowerDNS plugins directory" LIBRARYPATH  
+askPath "Intended location of the PowerDNS documentation directory" DOCPATH  
+
+$MB "\nPowerDNS can be configured to run as an\n\
+unprivileged user.\n\
+This is highly recommended. You should\n\
+now create a user and a group for PDNS\n\
+to run as and then press enter, \n\
+after which you will be asked for\n\
+the identity." 15 60
+
+askPath "Intended user id for PDNS to run as" PDNSUID
+askPath "Intended group id for PDNS to run as" PDNSGID
+
+$YN "Do you accept these values?\n\ninit.d: $INITDPATH\n\
+binaries: $BINARYPATH\n\
+configuration: $CONFIGPATH\n\
+sockets: $SOCKETPATH\n\
+plugins: $LIBRARYPATH\n\
+documentation: $DOCPATH\n\
+uid: $PDNSUID\n\
+gid: $PDNSGID\n" 15 60
+redo=$?
+echo $ready
+done
+
+mv pathconfig pathconfig.old 2> /dev/null > /dev/null
+
+(echo INITDPATH=$INITDPATH
+echo BINARYPATH=$BINARYPATH
+echo CONFIGPATH=$CONFIGPATH
+echo SOCKETPATH=$SOCKETPATH
+echo LIBRARYPATH=$LIBRARYPATH
+echo PDNSUID=$PDNSUID
+echo DOCPATH=$DOCPATH
+echo PDNSGID=$PDNSGID) > pathconfig
+
+$MB "\nDone recording your directory preferences." 7 70
+
+
diff --git a/pdns/codedocs/Makefile b/pdns/codedocs/Makefile
new file mode 100644 (file)
index 0000000..bfc658d
--- /dev/null
@@ -0,0 +1,219 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+prefix = /opt/pdns
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/pdns
+pkglibdir = $(libdir)/pdns
+pkgincludedir = $(includedir)/pdns
+top_builddir = ..
+
+ACLOCAL = ${SHELL} /home/ahu/programming/ahudns/missing --run aclocal
+AUTOCONF = ${SHELL} /home/ahu/programming/ahudns/missing --run autoconf
+AUTOMAKE = ${SHELL} /home/ahu/programming/ahudns/missing --run automake
+AUTOHEADER = ${SHELL} /home/ahu/programming/ahudns/missing --run autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = i686-pc-linux-gnu
+build_triplet = i686-pc-linux-gnu
+host_alias = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+target_alias = i686-pc-linux-gnu
+target_triplet = i686-pc-linux-gnu
+AMTAR = ${SHELL} /home/ahu/programming/ahudns/missing --run tar
+AS = @AS@
+AWK = mawk
+CC = gcc
+CXX = c++
+DEPDIR = .deps
+DLLTOOL = @DLLTOOL@
+ECHO = echo
+EXEEXT = 
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LEX = flex
+LIBDL = -ldl 
+LIBRESOLV = -lresolv 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+OBJDUMP = @OBJDUMP@
+OBJEXT = o
+PACKAGE = pdns
+RANLIB = ranlib
+STRIP = strip
+VERSION = 2.9
+YACC = bison -y
+am__include = include
+am__quote = 
+install_sh = /home/ahu/programming/ahudns/install-sh
+subdir = codedocs
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = Makefile.am Makefile.in
+all: all-am
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  codedocs/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+       distclean distclean-generic distclean-libtool distdir dvi \
+       dvi-am info info-am install install-am install-data \
+       install-data-am install-exec install-exec-am install-info \
+       install-info-am install-man install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool uninstall uninstall-am uninstall-info-am
+
+
+codedocs: .
+       doxygen doxygen.conf
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/pdns/codedocs/Makefile.am b/pdns/codedocs/Makefile.am
new file mode 100644 (file)
index 0000000..398a6eb
--- /dev/null
@@ -0,0 +1,2 @@
+codedocs: .
+       doxygen doxygen.conf
diff --git a/pdns/codedocs/Makefile.in b/pdns/codedocs/Makefile.in
new file mode 100644 (file)
index 0000000..38a867a
--- /dev/null
@@ -0,0 +1,219 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LEX = @LEX@
+LIBDL = @LIBDL@
+LIBRESOLV = @LIBRESOLV@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+subdir = codedocs
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = Makefile.am Makefile.in
+all: all-am
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  codedocs/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+       distclean distclean-generic distclean-libtool distdir dvi \
+       dvi-am info info-am install install-am install-data \
+       install-data-am install-exec install-exec-am install-info \
+       install-info-am install-man install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool uninstall uninstall-am uninstall-info-am
+
+
+codedocs: .
+       doxygen doxygen.conf
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/pdns/codedocs/doxygen.conf b/pdns/codedocs/doxygen.conf
new file mode 100644 (file)
index 0000000..374a642
--- /dev/null
@@ -0,0 +1,788 @@
+# Doxyfile 1.2.6
+
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a 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 (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project. 
+
+PROJECT_NAME           = ahudns
+
+# 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         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# 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       = ./
+
+# 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. 
+# The default language is English, other supported languages are: 
+# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, 
+# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, 
+# Polish, Portuguese and Slovene.
+
+OUTPUT_LANGUAGE        = English
+
+# 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 and EXTRACT_STATIC tags are set to YES 
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation. 
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation. 
+
+EXTRACT_STATIC         = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) 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. 
+
+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 (the default) these class will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled. 
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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. 
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) 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. 
+
+REPEAT_BRIEF           = YES
+
+# 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. 
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then 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. 
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then 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. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        = 
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation. 
+
+INTERNAL_DOCS          = NO
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a class diagram (in Html and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. 
+
+CLASS_DIAGRAMS         = YES
+
+# 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. 
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation. 
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible. 
+
+STRIP_CODE_COMMENTS    = YES
+
+# 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 
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden. 
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) 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. 
+
+VERBATIM_HEADERS       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put list of the files that are included by a file in the documentation 
+# of that file. 
+
+SHOW_INCLUDE_FILES     = YES
+
+# 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 
+# comments  will behave just like the Qt-style comments (thus requiring an 
+# explict @brief command for a brief description. 
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# reimplements. 
+
+INHERIT_DOCS           = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members. 
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) 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. 
+
+SORT_MEMBER_DOCS       = 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.
+
+DISTRIBUTE_GROUP_DOC   = 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. 
+
+TAB_SIZE               = 8
+
+# The ENABLE_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif. 
+
+ENABLED_SECTIONS       = 
+
+# 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.
+
+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.
+
+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.
+
+GENERATE_BUGLIST       = YES
+
+# This tag can be used to specify a number of aliases that acts 
+# 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                = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consist of 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 initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting. 
+
+MAX_INITIALIZER_LINES  = 30
+
+# 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. 
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# 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. 
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used. 
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used. 
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED 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. 
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# 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. 
+
+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 stderr. 
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be 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. 
+
+INPUT                  = ../
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_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. 
+
+FILE_PATTERNS          = *.cc \
+                         *.hh
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used. 
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# 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. 
+
+EXCLUDE                = 
+
+# 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. 
+
+EXCLUDE_PATTERNS       = 
+
+# 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       = 
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are 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 <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output. 
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse. 
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# 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. 
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20]) 
+
+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 one or more prefixes that 
+# should be ignored while generating the index headers. 
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output. 
+
+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. If left blank `html' will be used as the default path. 
+
+HTML_OUTPUT            = html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+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 the tag is left blank doxygen 
+# will generate a default style sheet 
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used. 
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation. 
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set YES to add extra items for group members 
+# to the contents of the Html help documentation and to the tree view. 
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. 
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation. 
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag 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 and frames is required (for instance Netscape 4.0+ 
+# or Internet explorer 4.0+). 
+
+GENERATE_TREEVIEW      = NO
+
+# 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. 
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output. 
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path. 
+
+LATEX_OUTPUT           = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general. 
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used. 
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output. 
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing! 
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer. 
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation. 
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML. 
+
+LATEX_BATCHMODE        = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimised for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = YES
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path. 
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general. 
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using a WORD or other. 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links. 
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assigments. You only have to provide 
+# replacements, missing definitions are set to their default value. 
+
+RTF_STYLESHEET_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages 
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path. 
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3) 
+
+MAN_EXTENSION          = .3
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files. 
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES. 
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags. 
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found. 
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor. 
+
+INCLUDE_PATH           =  ../
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used. 
+
+INCLUDE_FILE_PATTERNS  = *.hh
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. 
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition. 
+
+EXPAND_AS_DEFINED      = 
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles. 
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads. 
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed. 
+
+ALLEXTERNALS           = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl'). 
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default) 
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes. 
+
+COLLABORATION_GRAPH    = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to 
+# YES then doxygen will generate a graph for each documented file showing 
+# the direct and indirect include dependencies of the file with other 
+# documented files. 
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to 
+# YES then doxygen will generate a graph for each documented header file showing 
+# the documented files that directly or indirectly include this file 
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one. 
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path. 
+
+DOT_PATH               = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images. 
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images. 
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs. 
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermedate dot files that are used to generate 
+# the various graphs. 
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored. 
+
+SEARCHENGINE           = NO
+
+# The CGI_NAME tag should be the name of the CGI script that 
+# starts the search engine (doxysearch) with the correct parameters. 
+# A script with this name will be generated by doxygen. 
+
+CGI_NAME               = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the 
+# cgi binaries are located. See the documentation of your http daemon for 
+# details. 
+
+CGI_URL                = 
+
+# The DOC_URL tag should be the absolute URL to the directory where the 
+# documentation is located. If left blank the absolute path to the 
+# documentation, with file:// prepended to it, will be used. 
+
+DOC_URL                = 
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the 
+# documentation is located. If left blank the directory on the local machine 
+# will be used. 
+
+DOC_ABSPATH            = 
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
+# is installed. 
+
+BIN_ABSPATH            = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# documentation generated for other projects. This allows doxysearch to search 
+# the documentation for these projects as well. 
+
+EXT_DOC_PATHS          = 
diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc
new file mode 100644 (file)
index 0000000..54771b4
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "common_startup.hh"\r
+\r
+typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor;\r
+\r
+\r
+ArgvMap theArg;\r
+StatBag S;  //!< Statistics are gathered accross PDNS via the StatBag class S\r
+PacketCache PC; //!< This is the main PacketCache, shared accross all threads\r
+DNSProxy *DP;\r
+DynListener *dl;\r
+CommunicatorClass Communicator;\r
+UDPNameserver *N;\r
+int avg_latency;\r
+TCPNameserver *TN;\r
+\r
+ArgvMap &arg()\r
+{\r
+  return theArg;\r
+}\r
+\r
+\r
+void declareArguments()\r
+{\r
+  arg().set("local-port","The port on which we listen")="53";\r
+  arg().setSwitch("log-failed-updates","If PDNS should log failed update requests")="";\r
+  arg().setSwitch("log-dns-details","If PDNS should log failed update requests")="";\r
+  arg().set("urlredirector","Where we send hosts to that need to be url redirected")="127.0.0.1";\r
+  arg().set("smtpredirector","Our smtpredir MX host")="a.misconfigured.powerdns.smtp.server";\r
+  arg().set("local-address","Local IP address to which we bind")="0.0.0.0";\r
+  arg().set("local-ipv6","Local IP address to which we bind")="";\r
+  arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000";\r
+  arg().set("soa-serial-offset","Make sure that no SOA serial is less than this number")="0";\r
+  arg().set("only-soa","Make sure that no SOA serial is less than this number")="org";\r
+  arg().setCmd("help","Provide a helpful message");\r
+  arg().setCmd("config","Provide a helpful message");\r
+  arg().setCmd("list-modules","Lists all modules available");\r
+  arg().setCmd("no-config","Don't parse configuration file");\r
+  \r
+  arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will!\r
+  arg().set("fancy-records","Process URL and MBOXFW records")="no";\r
+  arg().set("wildcard-url","Process URL and MBOXFW records")="no";\r
+  arg().set("wildcards","Honor wildcards in the database")="";\r
+  arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4";\r
+  arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server";\r
+  arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3";\r
+  arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; \r
+  arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no"; \r
+  arg().set("lazy-recursion","Only recurse if question cannot be answered locally")="yes";\r
+  arg().set("allow-recursion","List of netmasks that are allowed to recurse")=""; \r
+  \r
+  arg().set("disable-tcp","Do not listen to TCP queries")="no";\r
+  arg().set("disable-axfr","Do not allow zone transfers")="no";\r
+  \r
+  arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";\r
+\r
+  arg().set("load-modules","Load this module - supply absolute or relative path")="";\r
+  arg().set("launch","Which backends to launch and order to query them in")="";\r
+  arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no";\r
+  arg().set("allow-axfr-ips","If disabled, DO allow zonetransfers from these IP addresses")="";\r
+  arg().set("slave-cycle-interval","Reschedule failed SOA serial checks once every .. seconds")="60";\r
+  \r
+  arg().setSwitch("slave","Act as a slave")="no";\r
+  arg().setSwitch("master","Act as a master")="no";\r
+  arg().setSwitch("guardian","Run within a guardian process")="no";\r
+  arg().setSwitch("skip-cname","Do not perform CNAME indirection for each query")="no";\r
+  arg().setSwitch("strict-rfc-axfrs","Perform strictly rfc compliant axfrs (very slow)")="no";\r
+  \r
+  arg().setSwitch("webserver","Start a webserver for monitoring")="no"; \r
+  arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no"; \r
+  arg().set("webserver-address","IP Address of webserver to listen on")="127.0.0.1";\r
+  arg().set("webserver-port","Port of webserver to listen on")="8081";\r
+  arg().set("webserver-password","Password required for accessing the webserver")="";\r
+\r
+  arg().set("receiver-threads","Number of receiver threads to launch")="1";\r
+  \r
+  arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="no";\r
+  arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";\r
+  \r
+  arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";\r
+  arg().set("recursive-cache-ttl","Seconds to store packets in the PacketCache")="10";\r
+  arg().set("negquery-cache-ttl","Seconds to store packets in the PacketCache")="60";\r
+  arg().set("query-cache-ttl","Seconds to store packets in the PacketCache")="20";\r
+  arg().set("soa-minimum-ttl","Default SOA mininum ttl")="3600";\r
+  arg().set("max-tcp-connections","Maximum number of TCP connections")="10";\r
+\r
+  arg().setSwitch( "use-logfile", "Use a log file" )= "no";\r
+  arg().set( "logfile", "Logfile to use" )= "pdns.log";\r
+\r
+}\r
+\r
+\r
+\r
+void declareStats(void)\r
+{\r
+  S.declare("udp-queries","Number of UDP queries received");\r
+  S.declare("udp-answers","Number of answers sent out over UDP");\r
+  S.declare("recursing-answers","Number of recursive answers sent out");\r
+  S.declare("recursing-questions","Number of questions sent to recursor");\r
+  S.declare("corrupt-packets","Number of corrupt packets received");\r
+\r
+  S.declare("tcp-queries","Number of TCP queries received");\r
+  S.declare("tcp-answers","Number of answers sent out over TCP");\r
+\r
+  S.declare("qsize-q","Number of questions waiting for database attention");\r
+\r
+  S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance");\r
+  S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance");\r
+\r
+  S.declare("query-cache-hit","Number of hits on the query cache");\r
+  S.declare("query-cache-miss","Number of misses on the query cache");\r
+\r
+\r
+  S.declare("servfail-packets","Number of times a server-failed packet was sent out");\r
+  S.declare("latency","Average number of microseconds needed to answer a question");\r
+  S.declare("timedout-packets","Number of packets which weren't answered within timeout set");\r
+\r
+  S.declareRing("queries","UDP Queries Received");\r
+  S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains");\r
+  S.declareRing("noerror-queries","Queries for existing records, but for type we don't have");\r
+  S.declareRing("servfail-queries","Queries that could not be answered due to backend errors");\r
+  S.declareRing("unauth-queries","Queries for domains that we are not authoritative for");\r
+  S.declareRing("logmessages","Log Messages");\r
+  S.declareRing("remotes","Remote server IP addresses");\r
+  S.declareRing("remotes-unauth","Remote hosts querying domains for which we are not auth");\r
+  S.declareRing("remotes-corrupt","Remote hosts sending corrupt packets");\r
+\r
+}\r
+\r
+\r
+int isGuarded(char **argv)\r
+{\r
+  char *p=strstr(argv[0],"-instance");\r
+\r
+  return !!p;\r
+}\r
+\r
+\r
+void sendout(const DNSDistributor::AnswerData &AD)\r
+{\r
+  static int &numanswered=*S.getPointer("udp-answers");\r
+  if(!AD.A)\r
+    return;\r
+  \r
+  N->send(AD.A);\r
+  numanswered++;\r
+  int diff=AD.A->d_dt.udiff();\r
+  avg_latency=(int)(0.999*avg_latency+0.001*diff);\r
+\r
+  delete AD.A;  \r
+\r
+\r
+}\r
+\r
+\r
+//! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for futher processing\r
+void *qthread(void *p)\r
+{\r
+  DNSDistributor *D=static_cast<DNSDistributor *>(p);\r
+\r
+  DNSPacket *P;\r
+\r
+  DNSPacket question;\r
+  DNSPacket cached;\r
+\r
+  int &numreceived=*S.getPointer("udp-queries");\r
+  int &numanswered=*S.getPointer("udp-answers");\r
+  numreceived=-1;\r
+  int diff;\r
+\r
+  for(;;) {\r
+    if(!((numreceived++)%50)) { // maintenance tasks\r
+      S.set("latency",(int)avg_latency);\r
+      int qcount, acount;\r
+      D->getQueueSizes(qcount, acount);\r
+      S.set("qsize-q",qcount);\r
+    }\r
+    \r
+    if(!(P=N->receive(&question))) { // receive a packet         inline\r
+      continue;                    // packet was broken, try again\r
+    }\r
+\r
+\r
+    S.ringAccount("queries", P->qdomain+"/"+P->qtype.getName());\r
+    S.ringAccount("remotes",P->getRemote());\r
+\r
+    if(PC.get(P,&cached)) { // short circuit - does the PacketCache recognize this question?\r
+      cached.setRemote((struct sockaddr *)(P->remote),P->d_socklen);  // inlined\r
+      cached.setSocket(P->getSocket());                               // inlined\r
+      cached.spoofID(P->d.id);                                        // inlined \r
+      cached.d.rd=P->d.rd; // copy in recursion desired bit \r
+      cached.commitD(); // commit d to the packet                        inlined\r
+\r
+      N->send(&cached);   // answer it then                              inlined\r
+      diff=P->d_dt.udiff();                                                    \r
+      avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA'\r
+      \r
+      numanswered++;\r
+      continue;\r
+    }\r
+\r
+    D->question(P, &sendout); // otherwise, give to the distributor\r
+  }\r
+  return 0;\r
+}\r
+\r
+\r
+void mainthread()\r
+{\r
+  Utility::srandom(time(0));\r
+\r
+   int newgid=0;      \r
+   if(!arg()["setgid"].empty()) \r
+     newgid=Utility::makeGidNumeric(arg()["setgid"]);      \r
+   int newuid=0;      \r
+   if(!arg()["setuid"].empty())        \r
+     newuid=Utility::makeUidNumeric(arg()["setuid"]); \r
+   if(!arg()["chroot"].empty()) {  \r
+     if(chroot(arg()["chroot"].c_str())<0) {\r
+       L<<Logger::Error<<"Unable to chroot: "<<strerror(errno)<<", exiting"<<endl; \r
+       exit(1);\r
+     }   \r
+     else\r
+       L<<Logger::Error<<"Chrooted to '"<<arg()["chroot"]<<"'"<<endl;      \r
+   }  \r
+   Utility::dropPrivs(newuid, newgid);\r
+\r
+  if(arg().mustDo("recursor")){\r
+    DP=new DNSProxy(arg()["recursor"]);\r
+    DP->onlyFrom(arg()["allow-recursion"]);\r
+    DP->go();\r
+  }\r
+  // NOW SAFE TO CREATE THREADS!\r
+  dl->go();\r
+\r
+\r
+\r
+\r
+  pthread_t qtid;\r
+  StatWebServer sws;\r
+\r
+  if(arg()["webserver"]!="no") \r
+    sws.go();\r
+  \r
+  if(arg().mustDo("slave") || arg().mustDo("master"))\r
+    Communicator.go(); \r
+\r
+  if(TN)\r
+    TN->go(); // tcp nameserver launch\r
+    \r
+  //  fork(); (this worked :-))\r
+  for(int n=0;n<arg().asNum("receiver-threads");++n) {\r
+    DNSDistributor *D= new DNSDistributor(arg().asNum("distributor-threads")); // the big dispatcher!\r
+    pthread_create(&qtid,0,qthread,static_cast<void *>(D)); // receives packets\r
+  }\r
+\r
+  void *p;\r
+  pthread_join(qtid, &p);\r
+  \r
+  L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl;\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/pdns/common_startup.hh b/pdns/common_startup.hh
new file mode 100644 (file)
index 0000000..7421139
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+\r
+#ifndef COMMON_STARTUP_HH\r
+#define COMMON_STARTUP_HH\r
+\r
+\r
+#include "utility.hh"\r
+#include "arguments.hh"\r
+#include "communicator.hh"\r
+#include "distributor.hh"\r
+#include "dnspacket.hh"\r
+#include "dnsproxy.hh"\r
+#include "dynlistener.hh"\r
+#include "nameserver.hh"\r
+#include "statbag.hh"\r
+#include "tcpreceiver.hh"\r
+#include "webserver.hh"\r
+#include "ws.hh"\r
+\r
+extern ArgvMap theArg;\r
+extern StatBag S;  //!< Statistics are gathered accross PDNS via the StatBag class S\r
+extern PacketCache PC; //!< This is the main PacketCache, shared accross all threads\r
+extern DNSProxy *DP;\r
+extern DynListener *dl;\r
+extern CommunicatorClass Communicator;\r
+extern UDPNameserver *N;\r
+extern int avg_latency;\r
+extern TCPNameserver *TN;\r
+\r
+\r
+extern ArgvMap & arg( void );\r
+extern void declareArguments();\r
+extern void declareStats();\r
+extern void mainthread();\r
+extern int isGuarded( char ** );\r
+\r
+#endif // COMMON_STARTUP_HH\r
diff --git a/pdns/communicator.cc b/pdns/communicator.cc
new file mode 100644 (file)
index 0000000..646acb8
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"
+#include <errno.h>
+#include "communicator.hh"
+#include <set>
+
+#include "dnsbackend.hh"
+#include "ueberbackend.hh"
+#include "packethandler.hh"
+#include "resolver.hh"
+#include "logger.hh"
+#include "dns.hh"
+#include "arguments.hh"
+#include "session.hh"
+
+
+void CommunicatorClass::addSuckRequest(const string &domain, const string &master)
+{
+  Lock l(&d_lock);
+  
+  SuckRequest sr;
+  sr.domain = domain;
+  sr.master = master;
+
+  d_suckdomains.push(sr);
+  
+  d_suck_sem.post();
+  d_any_sem.post();
+}
+
+
+void CommunicatorClass::suck(const string &domain,const string &remote)
+{
+  u_int32_t domain_id;
+  PacketHandler P;
+
+  DomainInfo di;
+  di.backend=0;
+    
+  try {
+    Resolver resolver;
+    resolver.axfr(remote,domain.c_str());
+
+    UeberBackend *B=dynamic_cast<UeberBackend *>(P.getBackend());
+
+    if(!B->getDomainInfo(domain, di) || !di.backend) {
+      L<<Logger::Error<<"Can't determine backend for domain '"<<domain<<"'"<<endl;
+      return;
+    }
+    domain_id=di.id;
+    di.backend->startTransaction(domain, domain_id);
+    
+    L<<Logger::Error<<"AXFR started for '"<<domain<<"', transaction started"<<endl;
+    Resolver::res_t recs;
+    
+    while(resolver.axfrChunk(recs)) {
+      for(Resolver::res_t::iterator i=recs.begin();i!=recs.end();++i) {
+       if((i->qname.size()-toLower(i->qname).rfind(toLower(domain)))!=domain.size()) {
+         L<<Logger::Error<<"Remote "<<remote<<" sneaked in out-of-zone data '"<<i->qname<<"' during AXFR of zone '"<<domain<<"'"<<endl;
+         di.backend->abortTransaction();
+         return;
+       }
+       i->domain_id=domain_id;
+       di.backend->feedRecord(*i);
+      }
+    }
+    di.backend->commitTransaction();
+    di.backend->setFresh(domain_id);
+    L<<Logger::Error<<"AXFR done for '"<<domain<<"', zone committed"<<endl;
+  }
+  catch(ResolverException &re) {
+    L<<Logger::Error<<"Unable to AXFR zone '"+domain+"': "<<re.reason<<endl;
+    if(di.backend) {
+      L<<Logger::Error<<"Aborting possible open transaction for domain '"<<domain<<"' AXFR"<<endl;
+      di.backend->abortTransaction();
+    }
+  }
+}
+
+class FindNS
+{
+public:
+  vector<string>lookup(const string &name, DNSBackend *B)
+  {
+    vector<string>addresses;
+    struct hostent *h;
+    h=gethostbyname(name.c_str());
+
+    if(h) {
+      for(char **h_addr_list=h->h_addr_list;*h_addr_list;++h_addr_list) {
+       ostringstream os;
+       unsigned char *p=reinterpret_cast<unsigned char *>(*h_addr_list);
+       os<<(int)*p++<<".";
+       os<<(int)*p++<<".";
+       os<<(int)*p++<<".";
+       os<<(int)*p++;
+
+       addresses.push_back(os.str());
+      }
+    }
+
+    B->lookup(QType(QType::A),name);
+    DNSResourceRecord rr;
+    while(B->get(rr)) 
+      addresses.push_back(rr.content);   // SOL if you have a CNAME for an NS
+
+    return addresses;
+  }
+}d_fns;
+
+void CommunicatorClass::queueNotifyDomain(const string &domain, DNSBackend *B)
+{
+  set<string> ips;
+  
+  DNSResourceRecord rr;
+  set<string>nsset;
+
+  B->lookup(QType(QType::NS),domain);
+  while(B->get(rr)) 
+    nsset.insert(rr.content);
+  
+  for(set<string>::const_iterator j=nsset.begin();j!=nsset.end();++j) {
+    vector<string>nsips=d_fns.lookup(*j, B);
+    for(vector<string>::const_iterator k=nsips.begin();k!=nsips.end();++k)
+      ips.insert(*k);
+  }
+  
+  // make calls to d_nq.add(domain, ip);
+  for(set<string>::const_iterator j=ips.begin();j!=ips.end();++j)
+    d_nq.add(domain,*j);
+  
+  set<string>alsoNotify;
+  B->alsoNotifies(domain, &alsoNotify);
+  
+  for(set<string>::const_iterator j=alsoNotify.begin();j!=alsoNotify.end();++j)
+    d_nq.add(domain,*j);
+}
+
+bool CommunicatorClass::notifyDomain(const string &domain)
+{
+  DomainInfo di;
+  PacketHandler P;
+  if(!P.getBackend()->getDomainInfo(domain, di)) {
+    L<<Logger::Error<<"No such domain '"<<domain<<"' in our database"<<endl;
+    return false;
+  }
+  queueNotifyDomain(domain, P.getBackend());
+  // call backend and tell them we sent out the notification - even though that is premature    
+  di.backend->setNotified(di.id,di.serial);   
+
+  return true; 
+}
+
+
+void CommunicatorClass::masterUpdateCheck(PacketHandler *P)
+{
+  if(!arg().mustDo("master"))
+    return; 
+
+  UeberBackend *B=dynamic_cast<UeberBackend *>(P->getBackend());
+  vector<DomainInfo> cmdomains;
+  B->getUpdatedMasters(&cmdomains);
+  
+  if(cmdomains.empty())
+    L<<Logger::Error<<"No master domains need notifications"<<endl;
+  else
+    L<<Logger::Error<<cmdomains.size()<<" domain"<<(cmdomains.size()>1 ? "s" : "")<<" for which we are master need"<<
+      (cmdomains.size()>1 ? "" : "s")<<
+      " notifications"<<endl;
+
+  // figure out A records of everybody needing notification
+  // do this via the FindNS class, d_fns
+  
+
+  for(vector<DomainInfo>::const_iterator i=cmdomains.begin();i!=cmdomains.end();++i) {
+    queueNotifyDomain(i->zone,P->getBackend());
+    i->backend->setNotified(i->id,i->serial); 
+  }
+
+
+
+  // call it a day
+  // day()
+
+}
+
+void CommunicatorClass::slaveRefresh(PacketHandler *P)
+{
+  UeberBackend *B=dynamic_cast<UeberBackend *>(P->getBackend());
+  vector<DomainInfo> sdomains;
+  B->getUnfreshSlaveInfos(&sdomains);
+  
+  if(sdomains.empty())
+  {
+    L<<Logger::Error<<"All slave domains are fresh"<<endl;
+    return;
+  }
+  else
+    L<<Logger::Error<<sdomains.size()<<" slave domain"<<(sdomains.size()>1 ? "s" : "")<<" need"<<
+      (sdomains.size()>1 ? "" : "s")<<
+      " checking"<<endl;
+  
+  for(vector<DomainInfo>::const_iterator i=sdomains.begin();i!=sdomains.end();++i) {
+    u_int32_t theirserial=0;
+    try {
+      Resolver resolver;
+      int res=resolver.getSoaSerial(i->master,i->zone, &theirserial);
+      if(res<=0) {
+       L<<Logger::Error<<"Unable to determine SOA serial for "<<i->zone<<" at "<<i->master<<endl;
+       continue;
+      }
+      
+      if(theirserial<i->serial) {
+       L<<Logger::Error<<"Domain "<<i->zone<<" more recent than master, our serial "<<i->serial<<" > their serial "<<theirserial<<endl;
+       i->backend->setFresh(i->id);
+      }
+      else if(theirserial==i->serial) {
+       L<<Logger::Warning<<"Domain "<<i->zone<<" is fresh"<<endl;
+       i->backend->setFresh(i->id);
+      }
+      else {
+       L<<Logger::Error<<"Domain "<<i->zone<<" is stale, master serial "<<theirserial<<", our serial "<<i->serial<<endl;
+       addSuckRequest(i->zone,i->master);
+      }
+    }
+    catch(ResolverException &re) {
+      L<<Logger::Error<<"Trying to retrieve/refresh '"+i->zone+"': "+re.reason<<endl;
+    }
+  }
+}  
+
+
+
+int CommunicatorClass::doNotifications()
+{
+  struct sockaddr_in from;
+  Utility::socklen_t fromlen=sizeof(from);
+  char buffer[1500];
+  int size;
+  static Resolver d_nresolver;
+  // receive incoming notifications on the nonblocking socket and take them off the list
+
+#ifndef WIN32
+  while((size=recvfrom(d_nsock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen))>0) {
+#else
+  while((size=recvfrom(d_nsock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen))>0) {
+#endif
+
+
+
+    DNSPacket p;
+
+    p.setRemote((struct sockaddr *)&from, fromlen);
+
+    if(p.parse(buffer,size)<0) {
+      L<<Logger::Warning<<"Unable to parse SOA notification answer from "<<p.getRemote()<<endl;
+      continue;
+    }
+
+    if(p.d.rcode)
+      L<<Logger::Warning<<"Received unsuccesful notification report for '"<<p.qdomain<<"' from "<<p.getRemote()<<", rcode: "<<p.d.rcode<<endl;      
+    else if(d_nq.removeIf(p.getRemote(), p.d.id, p.qdomain))
+      L<<Logger::Warning<<"Received valid notify answer for '"<<p.qdomain<<"' from "<<p.getRemote()<<endl;      
+    else
+      L<<Logger::Warning<<"Received spurious notify answer for '"<<p.qdomain<<"' from "<<p.getRemote()<<endl;      
+  }
+
+  // send out possible new notifications
+  string domain, ip;
+  u_int16_t id;
+
+  bool purged;
+  while(d_nq.getOne(domain, ip, &id, purged)) {
+    if(!purged) {
+      d_nresolver.notify(d_nsock,domain,ip,id);
+      drillHole(domain,ip);
+    }
+    else
+      L<<Logger::Error<<Logger::NTLog<<"Notification for "<<domain<<" to "<<ip<<" failed after retries"<<endl;
+  }
+
+  return d_nq.earliest();
+}
+
+void CommunicatorClass::drillHole(const string &domain, const string &ip)
+{
+  Lock l(&d_holelock);
+  d_holes[make_pair(domain,ip)]=time(0);
+}
+
+bool CommunicatorClass::justNotified(const string &domain, const string &ip)
+{
+  Lock l(&d_holelock);
+  if(d_holes.find(make_pair(domain,ip))==d_holes.end()) // no hole
+    return false;
+
+  if(d_holes[make_pair(domain,ip)]>time(0)-900)    // recent hole
+    return true;
+
+  // do we want to purge this? XXX FIXME 
+  return false;
+}
+
+void CommunicatorClass::makeNotifySocket()
+{
+  if((d_nsock=socket(AF_INET, SOCK_DGRAM,0))<0)
+    throw AhuException(string("notification socket: ")+strerror(errno));
+
+  struct sockaddr_in sin;
+  memset((char *)&sin,0, sizeof(sin));
+  
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = INADDR_ANY;
+  int n=0;
+  for(;n<10;n++) {
+    sin.sin_port = htons(10000+(Utility::random()%50000));
+    
+    if(bind(d_nsock, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 
+      break;
+  }
+  if(n==10) {
+    Utility::closesocket(d_nsock);
+    d_nsock=-1;
+    throw AhuException(string("binding dnsproxy socket: ")+strerror(errno));
+  }
+  if( !Utility::setNonBlocking( d_nsock ))
+    throw AhuException(string("error getting or setting notify socket non-blocking: ")+strerror(errno));
+
+}
+
+void CommunicatorClass::notify(const string &domain, const string &ip)
+{
+  d_nq.add(domain,ip);
+
+  d_any_sem.post();
+}
+
+void CommunicatorClass::mainloop(void)
+{
+  try {
+#ifndef WIN32
+    signal(SIGPIPE,SIG_IGN);
+#endif // WIN32
+    L<<Logger::Error<<"Master/slave communicator launching"<<endl;
+    PacketHandler P;
+    d_tickinterval=arg().asNum("slave-cycle-interval");
+    makeNotifySocket();
+
+    int rc;
+    time_t next;
+
+    int tick;
+
+    for(;;) {
+      slaveRefresh(&P);
+      masterUpdateCheck(&P);
+
+      tick=min(doNotifications(),
+              d_tickinterval);
+
+      next=time(0)+tick;
+
+      while(time(0)<next) {
+       rc=d_any_sem.tryWait();
+
+       if(rc)
+         Utility::sleep(1);
+       else { 
+         if(!d_suck_sem.tryWait()) {
+           SuckRequest sr;
+           {
+             Lock l(&d_lock);
+             sr=d_suckdomains.front();
+             d_suckdomains.pop();
+           }
+           suck(sr.domain,sr.master);
+         }
+       }
+       // this gets executed at least once every second
+       doNotifications();
+      }
+    }
+  }
+  catch(AhuException &ae) {
+    L<<Logger::Error<<"Communicator thread died because of error: "<<ae.reason<<endl;
+    sleep(1);
+    exit(0);
+  }
+  catch(exception &e) {
+    L<<Logger::Error<<"Communicator thread died because of STL error: "<<e.what()<<endl;
+    exit(0);
+  }
+  catch( ... )
+  {
+    L << Logger::Error << "Communicator caught unknown exception." << endl;
+    exit( 0 );
+  }
+}
+
diff --git a/pdns/communicator.hh b/pdns/communicator.hh
new file mode 100644 (file)
index 0000000..5fd6123
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_COMMUNICATOR_HH
+#define PDNS_COMMUNICATOR_HH
+
+#include <pthread.h>
+#include <string>
+#include <semaphore.h>
+#include <queue>
+#include <list>
+\r
+#ifndef WIN32\r
+# include <unistd.h>\r
+# include <fcntl.h>\r
+# include <netdb.h>\r
+#endif // WIN32\r
+\r
+#include "lock.hh"
+#include "packethandler.hh"
+
+using namespace std;
+
+struct SuckRequest
+{
+  string domain;
+  string master;
+};
+
+class NotificationQueue
+{
+public:
+  void add(const string &domain, const string &ip)
+  {
+    NotificationRequest nr;\r
+    nr.domain   = domain;\r
+    nr.ip       = ip;\r
+    nr.attempts = 0;\r
+    nr.id       = Utility::random()%0xffff;\r
+    nr.next     = time(0);\r
+
+    d_nqueue.push_back(nr);
+  }
+  
+  bool removeIf(const string &remote, u_int16_t id, const string &domain)
+  {
+    for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) {
+      cout<<i->id<<" "<<id<<endl;
+      cout<<i->ip<<" "<<remote<<endl;
+      cout<<i->domain<<" "<<domain<<endl;
+
+      if(i->id==id && i->ip==remote && i->domain==domain) {
+       d_nqueue.erase(i);
+       return true;
+      }
+    }
+    return false;
+  }
+
+  bool getOne(string &domain, string &ip, u_int16_t *id, bool &purged)
+  {
+    for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) 
+      if(i->next <= time(0)) {
+       i->attempts++;
+       purged=false;
+       i->next=time(0)+1+(1<<i->attempts);
+       domain=i->domain;
+       ip=i->ip;
+       *id=i->id;
+       purged=false;
+       if(i->attempts>4) {
+         purged=true;
+         d_nqueue.erase(i);
+       }
+       return true;
+      }
+    return false;
+  }
+  
+  time_t earliest()
+  {
+    time_t early=1<<31-1; // y2038 problem lurking here :-)
+    for(d_nqueue_t::const_iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) 
+      early=min(early,i->next);
+    return early-time(0);
+  }
+
+private:
+  struct NotificationRequest
+  {
+    string domain;
+    string ip;
+    int attempts;
+    u_int16_t id;
+    time_t next;
+  };
+
+  typedef list<NotificationRequest>d_nqueue_t;
+  d_nqueue_t d_nqueue;
+
+};
+
+/** this class contains a thread that communicates with other nameserver and does housekeeping.
+    Initially, it is notified only of zones that need to be pulled in because they have been updated. */
+
+class CommunicatorClass
+{
+public:
+  CommunicatorClass() 
+  {
+    pthread_mutex_init(&d_lock,0);
+    pthread_mutex_init(&d_holelock,0);
+//    sem_init(&d_suck_sem,0,0);
+//    sem_init(&d_any_sem,0,0);
+    d_tickinterval=60;
+  }
+  int doNotifications();    
+  void go()
+  {
+    pthread_t tid;
+    pthread_create(&tid,0,&launchhelper,this);
+  }
+
+  void drillHole(const string &domain, const string &ip);
+  bool justNotified(const string &domain, const string &ip);
+  void addSuckRequest(const string &domain, const string &master);
+  void notify(const string &domain, const string &ip);
+  void mainloop();
+  static void *launchhelper(void *p)
+  {
+    static_cast<CommunicatorClass *>(p)->mainloop();
+    return 0;
+  }
+  bool notifyDomain(const string &domain);
+private:
+  void makeNotifySocket();
+  void queueNotifyDomain(const string &domain, DNSBackend *B);
+  int d_nsock;
+  map<pair<string,string>,time_t>d_holes;
+  pthread_mutex_t d_holelock;
+  void suck(const string &domain, const string &remote);
+  void slaveRefresh(PacketHandler *P);
+  void masterUpdateCheck(PacketHandler *P);
+  pthread_mutex_t d_lock;
+  queue<SuckRequest> d_suckdomains;
+  Semaphore d_suck_sem;
+  Semaphore d_any_sem;
+  int d_tickinterval;
+  NotificationQueue d_nq;
+};
+
+#endif
diff --git a/pdns/config.guess b/pdns/config.guess
new file mode 100755 (executable)
index 0000000..ed2e03b
--- /dev/null
@@ -0,0 +1,1321 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# 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 <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted 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.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # 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
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+         if test $? = 0 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       rm -f $dummy.c $dummy.o $dummy.rel ;
+       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'
+
+# 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
+
+# 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 tupples: *-*-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
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-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 __ELF__ >/dev/null
+               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
+       release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       # 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 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    alpha:OSF1:*:*)
+       if test $UNAME_RELEASE = "V4.0"; then
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+       fi
+       # 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.
+       cat <<EOF >$dummy.s
+       .data
+\$Lformat:
+       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
+
+       .text
+       .globl main
+       .align 4
+       .ent main
+main:
+       .frame \$30,16,\$26,0
+       ldgp \$29,0(\$27)
+       .prologue 1
+       .long 0x47e03d80 # implver \$0
+       lda \$2,-1
+       .long 0x47e20c21 # amask \$2,\$1
+       lda \$16,\$Lformat
+       mov \$0,\$17
+       not \$1,\$18
+       jsr \$26,printf
+       ldgp \$29,0(\$26)
+       mov 0,\$16
+       jsr \$26,exit
+       .end main
+EOF
+       eval $set_cc_for_build
+       $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+       if test "$?" = 0 ; then
+               case `./$dummy` in
+                       0-0)
+                               UNAME_MACHINE="alpha"
+                               ;;
+                       1-0)
+                               UNAME_MACHINE="alphaev5"
+                               ;;
+                       1-1)
+                               UNAME_MACHINE="alphaev56"
+                               ;;
+                       1-101)
+                               UNAME_MACHINE="alphapca56"
+                               ;;
+                       2-303)
+                               UNAME_MACHINE="alphaev6"
+                               ;;
+                       2-307)
+                               UNAME_MACHINE="alphaev67"
+                               ;;
+                       2-1307)
+                               UNAME_MACHINE="alphaev68"
+                               ;;
+               esac
+       fi
+       rm -f $dummy.s $dummy
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit 0 ;;
+    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 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit 0 ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    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 0 ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    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 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    # 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 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* 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 $dummy.c -o $dummy \
+         && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    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 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????: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 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    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 0 ;;
+    *: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 <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+               rm -f $dummy.c $dummy
+               echo rs6000-ibm-aix3.2.5
+       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 0 ;;
+    *:AIX:*:[45])
+       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 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    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 <stdlib.h>
+              #include <unistd.h>
+
+              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 $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+                   if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+                   rm -f $dummy.c $dummy
+               fi ;;
+       esac
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       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 $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    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 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3D:*:*:*)
+       echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    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 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:3*)
+       echo i386-pc-interix3
+       exit 0 ;;
+    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 i386-pc-interix
+       exit 0 ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       rm -f $dummy.c
+       test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    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 ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit 0 ;;
+    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-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit 0 ;;               
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       rm -f $dummy.c
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    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 0 ;;
+    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 0 ;;
+    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 0 ;;
+    i*86:*:5:[78]*)
+       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 0 ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
+    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 i386.
+       echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    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 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*: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 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *: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 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit 0 ;;
+    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 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit 0 ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit 0 ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Darwin:*:*)
+       echo `uname -p`-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *: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 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *: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 0 ;;
+    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 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+  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"); 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 <sys/param.h>
+#  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 $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# 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 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> 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/pdns/config.h.in b/pdns/config.h.in
new file mode 100644 (file)
index 0000000..88a5e7f
--- /dev/null
@@ -0,0 +1,89 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+#undef SETVBUF_REVERSED
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+/* Define when extra posix typedefs are needed (solaris2.6) */
+#undef NEED_POSIX_TYPEDEF
+#undef VERBOSELOG
+
+/* Define if you have the gethostname function.  */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the gettimeofday function.  */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the mkdir function.  */
+#undef HAVE_MKDIR
+
+/* Define if you have the mktime function.  */
+#undef HAVE_MKTIME
+
+/* Define if you have the select function.  */
+#undef HAVE_SELECT
+
+/* Define if you have the socket function.  */
+#undef HAVE_SOCKET
+
+/* Define if you have the strerror function.  */
+#undef HAVE_STRERROR
+
+/* Define if you have the <dlfcn.h> header file.  */
+#undef HAVE_DLFCN_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <getopt.h> header file.  */
+#undef HAVE_GETOPT_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <syslog.h> header file.  */
+#undef HAVE_SYSLOG_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the dl library (-ldl).  */
+#undef HAVE_LIBDL
+
+/* Define if you have the resolv library (-lresolv).  */
+#undef HAVE_LIBRESOLV
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/pdns/config.sub b/pdns/config.sub
new file mode 100755 (executable)
index 0000000..f365797
--- /dev/null
@@ -0,0 +1,1443 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-07'
+
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# 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 <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted 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.
+
+# 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # 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 0;;
+
+    * )
+       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* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    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)
+               os=
+               basic_machine=$1
+               ;;
+       -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
+               ;;
+       -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/'`
+               ;;
+       -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*)
+               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 \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+       | c4x | clipper \
+       | d10v | d30v | dsp16xx \
+       | fr30 \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | m32r | m68000 | m68k | m88k | mcore \
+       | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+       | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+       | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+       | mipsisa32 | mipsisa64 \
+       | mn10200 | mn10300 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+
+       # 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-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armv*-* \
+       | avr-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c54x-* \
+       | clipper-* | cydra-* \
+       | d10v-* | d30v-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fr30-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | m32r-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+       | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+       | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # 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
+               ;;
+       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
+               ;;
+       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
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       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
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       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
+               ;;
+       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'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       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
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       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
+               ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       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
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       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
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+        pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2)
+               basic_machine=i686-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-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  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
+               ;;
+       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
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       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
+               ;;
+       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
+               ;;
+       t3d)
+               basic_machine=alpha-cray
+               os=-unicos
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       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
+               ;;
+       windows32)
+               basic_machine=i386-pc
+               os=-windows32-msvcrt
+               ;;
+        xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-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
+               ;;
+       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
+               ;;
+       sh3 | sh4 | sh3eb | sh4eb)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv9 | sparcv9b)
+               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
+               ;;
+       c4x*)
+               basic_machine=c4x-none
+               os=-coff
+               ;;
+       *-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.
+       -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* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto*)
+               os=-nto-qnx
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -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
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -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
+               ;;
+       -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
+               ;;
+       -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
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+       # 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
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       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
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-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
+                               ;;
+                       -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
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -vxsim* | -vxworks*)
+                               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 0
+
+# 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/pdns/configure b/pdns/configure
new file mode 100755 (executable)
index 0000000..169757a
--- /dev/null
@@ -0,0 +1,7537 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --disable-dependency-tracking Speeds up one-time builds
+  --enable-dependency-tracking  Do not reject slow dependency extractors"
+ac_default_prefix=/opt/pdns
+ac_help="$ac_help
+  --enable-shared[=PKGS]  build shared libraries [default=yes]"
+ac_help="$ac_help
+  --enable-static[=PKGS]  build static libraries [default=yes]"
+ac_help="$ac_help
+  --enable-fast-install[=PKGS]  optimize for fast installation [default=yes]"
+ac_help="$ac_help
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]"
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "$0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+ac_help="$ac_help
+  --disable-libtool-lock  avoid locking (might break parallel builds)"
+ac_help="$ac_help
+  --with-pic              try to use only PIC/non-PIC objects [default=use both]"
+ac_help="$ac_help
+  --with-stl-includes=PATH Specify location of STL headers"
+ac_help="$ac_help
+  --with-stl-libs=PATH    Specify location of STL libs"
+ac_help="$ac_help
+  --enable-verbose-logging     Do verbose logging"
+ac_help="$ac_help
+  --enable-static-binaries     Build static binaries"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -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 ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$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" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$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)
+    # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$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" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    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)
+    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" ;;
+
+  -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 ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=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" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=receiver.cc
+
+# 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 its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  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
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+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
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+#    same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+#    as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:755: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:776: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+  case $nonopt in
+  NONE) target_alias=$host_alias ;;
+  *) target_alias=$nonopt ;;
+  esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:794: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+  case $nonopt in
+  NONE) build_alias=$host_alias ;;
+  *) build_alias=$nonopt ;;
+  esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd`
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:832: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:885: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { echo "configure: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  am_backtick='`'
+  echo "configure: warning: ${am_backtick}missing' script is too old or missing" 1>&2
+fi
+
+for ac_prog in mawk gawk nawk awk
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:956: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AWK="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AWK="$ac_cv_prog_AWK"
+if test -n "$AWK"; then
+  echo "$ac_t""$AWK" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AWK" && break
+done
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:986: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval="$enable_dependency_tracking"
+  :
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+
+rm -f .deps 2>/dev/null
+mkdir .deps 2>/dev/null
+if test -d .deps; then
+  DEPDIR=.deps
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  DEPDIR=_deps
+fi
+rmdir .deps 2>/dev/null
+
+
+# test to see if srcdir already configured
+if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  { echo "configure: error: source directory already configured; run \"make distclean\" there first" 1>&2; exit 1; }
+fi
+
+# Define the identity of the package.
+PACKAGE=pdns
+VERSION=2.9
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+# Autoconf 2.50 wants to disallow AM_ names.  We explicitly allow
+# the ones we care about.
+
+# Autoconf 2.50 always computes EXEEXT.  However we need to be
+# compatible with 2.13, for now.  So we always define EXEEXT, but we
+# don't compute it.
+
+# Similar for OBJEXT -- only we only use OBJEXT if the user actually
+# requests that it be used.  This is a bit dumb.
+: ${OBJEXT=o}
+
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+
+
+  
+
+CXXFLAGS="-Wall -pthread -O2"
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1111: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1141: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_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 $# -gt 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
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1192: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1224: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1235 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1240: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1266: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1271: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1280: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1299: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&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
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+doit:
+       @echo done
+END
+# If we don't find an include directive, just comment out the code.
+echo $ac_n "checking for style of include used by $am_make""... $ac_c" 1>&6
+echo "configure:1338: checking for style of include used by $am_make" >&5
+am__include='#'
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote='"'
+      _am_result=BSD
+   fi
+fi
+
+
+echo "$ac_t""$_am_result" 1>&6
+rm -f confinc confmf
+
+
+depcc="$CC"   am_compiler_list=
+
+echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6
+echo "configure:1372: checking dependency style of $depcc" >&5
+if eval "test \"`echo '$''{'am_cv_CC_dependencies_compiler_type'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    echo '#include "conftest.h"' > conftest.c
+    echo 'int i;' > conftest.h
+    echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=conftest.c object=conftest.o \
+       depfile=conftest.Po tmpdepfile=conftest.TPo \
+       $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 &&
+       grep conftest.h conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      am_cv_CC_dependencies_compiler_type=$depmode
+      break
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+
+echo "$ac_t""$am_cv_CC_dependencies_compiler_type" 1>&6
+CCDEPMODE="depmode=$am_cv_CC_dependencies_compiler_type"
+
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1443: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CXX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+  echo "$ac_t""$CXX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1475: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1486 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:1491: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cxx_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cxx_cross=no
+  else
+    ac_cv_prog_cxx_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+  { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1517: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:1522: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.C <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1531: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gxx=yes
+else
+  ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:1550: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+  ac_cv_prog_cxx_g=yes
+else
+  ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+
+depcc="$CXX"  am_compiler_list=
+
+echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6
+echo "configure:1584: checking dependency style of $depcc" >&5
+if eval "test \"`echo '$''{'am_cv_CXX_dependencies_compiler_type'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    echo '#include "conftest.h"' > conftest.c
+    echo 'int i;' > conftest.h
+    echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=conftest.c object=conftest.o \
+       depfile=conftest.Po tmpdepfile=conftest.TPo \
+       $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 &&
+       grep conftest.h conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      am_cv_CXX_dependencies_compiler_type=$depmode
+      break
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+
+echo "$ac_t""$am_cv_CXX_dependencies_compiler_type" 1>&6
+CXXDEPMODE="depmode=$am_cv_CXX_dependencies_compiler_type"
+
+
+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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1655: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+  echo "$ac_t""$YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1686: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 1701 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1707: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1718 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1724: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1735 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1741: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1771: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LEX" && break
+done
+test -n "$LEX" || LEX="${am_missing_run}flex"
+
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1804: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="flex"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+  case "$LEX" in
+  flex*) ac_lib=fl ;;
+  *) ac_lib=l ;;
+  esac
+  echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:1838: checking for yywrap in -l$ac_lib" >&5
+ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-l$ac_lib  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1846 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:1857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LEXLIB="-l$ac_lib"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+echo "configure:1880: checking lex output file root" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # The minimal lex program is just a single line: %%.  But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+echo '%%
+%%' | $LEX
+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
+  { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+echo "configure:1901: checking whether yytext is a pointer" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&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
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS="$LIBS"
+LIBS="$LIBS $LEXLIB"
+cat > conftest.$ac_ext <<EOF
+#line 1913 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+  cat >> confdefs.h <<\EOF
+#define YYTEXT_POINTER 1
+EOF
+
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1953: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:2006: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) lt_cv_sys_path_separator=';' ;;
+    *)     lt_cv_sys_path_separator=':' ;;
+  esac
+  PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:2044: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2049 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:2060: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_cygwin=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:2077: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2082 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:2089: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_mingw32=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:2186: checking for ld used by GCC" >&5
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:2216: checking for GNU ld" >&5
+else
+  echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:2219: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  echo "$ac_t""$LD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:2254: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  lt_cv_prog_gnu_ld=yes
+else
+  lt_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$lt_cv_prog_gnu_ld" 1>&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6
+echo "configure:2271: checking for $LD option to reload object files" >&5
+if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+
+echo "$ac_t""$lt_cv_ld_reload_flag" 1>&6
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:2283: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm=$ac_dir/${ac_tool_prefix}nm
+    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -B"
+       break
+      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -p"
+       break
+      else
+       lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+
+NM="$lt_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:2321: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+  rm -f conftestdata
+  ac_cv_prog_LN_S="ln -s"
+else
+  ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6
+echo "configure:2342: checking how to recognise dependant libraries" >&5
+if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin* | mingw* | pw32*)
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  case "$host_os" in
+  rhapsody* | darwin1.[012])
+    lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+    ;;
+  *) # Darwin 1.3 on
+    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+    ;;
+  esac
+  ;;
+
+freebsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20*|hpux11*)
+  lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libc.sl
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+  irix5* | nonstopux*)
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case $LD in
+    *-32|*"-32 ") libmagic=32-bit;;
+    *-n32|*"-n32 ") libmagic=N32;;
+    *-64|*"-64 ") libmagic=64-bit;;
+    *) libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+openbsd*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+  else
+    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  # this will be overridden with pass_all, but let us keep it just in case
+  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=/lib/libc.so
+  ;;
+
+sysv5uw[78]* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  esac
+  ;;
+esac
+
+fi
+
+echo "$ac_t""$lt_cv_deplibs_check_method" 1>&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+
+echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+echo "configure:2519: checking for object suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  rm -f conftest*
+echo 'int i = 1;' > conftest.$ac_ext
+if { (eval echo configure:2525: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  for ac_file in conftest.*; do
+    case $ac_file in
+    *.c) ;;
+    *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
+    esac
+  done
+else
+  { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_objext" 1>&6
+OBJEXT=$ac_cv_objext
+ac_objext=$ac_cv_objext
+
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:2545: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+  ac_cv_exeext=.exe
+else
+  rm -f conftest*
+  echo 'int main () { return 0; }' > conftest.$ac_ext
+  ac_cv_exeext=
+  if { (eval echo configure:2555: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+    for file in conftest.*; do
+      case $file in
+      *.$ac_ext | *.c | *.o | *.obj) ;;
+      *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+      esac
+    done
+  else
+    { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+  fi
+  rm -f conftest*
+  test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+if test $host != $build; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+echo "configure:2586: checking command to parse $NM output" >&5
+if eval "test \"`echo '$''{'lt_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+solaris* | sysv5*)
+  symcode='[BDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $host_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[        ]\($symcode$symcode*\)[         ][      ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if { (eval echo configure:2666: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { (eval echo configure:2669: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+         sed "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         save_LIBS="$LIBS"
+         save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if { (eval echo configure:2720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+           pipe_works=yes
+         fi
+         LIBS="$save_LIBS"
+         CFLAGS="$save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+  global_symbol_to_c_name_address=
+else
+  global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+  global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+fi
+if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+then
+  echo "$ac_t""failed" 1>&6
+else
+  echo "$ac_t""ok" 1>&6
+fi
+
+for ac_hdr in dlfcn.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2769: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2774 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2779: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6
+echo "configure:2814: checking for ${ac_tool_prefix}file" >&5
+if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           egrep "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$ac_t""$MAGIC_CMD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    echo $ac_n "checking for file""... $ac_c" 1>&6
+echo "configure:2876: checking for file" >&5
+if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           egrep "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$ac_t""$MAGIC_CMD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2947: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2979: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  RANLIB=":"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3014: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+STRIP="$ac_cv_prog_STRIP"
+if test -n "$STRIP"; then
+  echo "$ac_t""$STRIP" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_STRIP"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3046: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_STRIP="strip"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_STRIP" && ac_cv_prog_STRIP=":"
+fi
+fi
+STRIP="$ac_cv_prog_STRIP"
+if test -n "$STRIP"; then
+  echo "$ac_t""$STRIP" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  STRIP=":"
+fi
+fi
+
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+  :
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 3095 "configure"' > conftest.$ac_ext
+  if { (eval echo configure:3096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+echo "configure:3117: checking whether the C compiler needs -belf" >&5
+if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+     ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+     cat > conftest.$ac_ext <<EOF
+#line 3130 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=no
+fi
+rm -f conftest*
+     ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+fi
+
+echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+need_locks="$enable_libtool_lock"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+if test x"$host" != x"$build"; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case $host_os in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for objdir""... $ac_c" 1>&6
+echo "configure:3257: checking for objdir" >&5
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t""$objdir" 1>&6
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+  withval="$with_pic"
+  pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+test -z "$pic_mode" && pic_mode=default
+
+# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+# in isolation, and that seeing it set (from the cache) indicates that
+# the associated values are set (in the cache) correctly too.
+echo $ac_n "checking for $compiler option to produce PIC""... $ac_c" 1>&6
+echo "configure:3284: checking for $compiler option to produce PIC" >&5
+if eval "test \"`echo '$''{'lt_cv_prog_cc_pic'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+   lt_cv_prog_cc_pic=
+  lt_cv_prog_cc_shlib=
+  lt_cv_prog_cc_wl=
+  lt_cv_prog_cc_static=
+  lt_cv_prog_cc_no_builtin=
+  lt_cv_prog_cc_can_build_shared=$can_build_shared
+
+  if test "$GCC" = yes; then
+    lt_cv_prog_cc_wl='-Wl,'
+    lt_cv_prog_cc_static='-static'
+
+    case $host_os in
+    aix*)
+      # Below there is a dirty hack to force normal static linking with -ldl
+      # The problem is because libdl dynamically linked with both libc and
+      # libC (AIX C++ library), which obviously doesn't included in libraries
+      # list by gcc. This cause undefined symbols with -static flags.
+      # This hack allows C programs to be linked with "-static -ldl", but
+      # not sure about C++ programs.
+      lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_cv_prog_cc_pic='-fno-common'
+      ;;
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+        lt_cv_prog_cc_pic=-Kconform_pic
+      fi
+      ;;
+    *)
+      lt_cv_prog_cc_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for PIC flags for the system compiler.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      lt_cv_prog_cc_wl='-Wl,'
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_cv_prog_cc_static='-Bstatic'
+      else
+       lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+      lt_cv_prog_cc_pic='+Z'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      # PIC (with -KPIC) is the default.
+      ;;
+
+    cygwin* | mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_cv_prog_cc_pic='-DDLL_EXPORT'
+      ;;
+
+    newsos6)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      # All OSF/1 code is PIC.
+      lt_cv_prog_cc_wl='-Wl,'
+      lt_cv_prog_cc_static='-non_shared'
+      ;;
+
+    sco3.2v5*)
+      lt_cv_prog_cc_pic='-Kpic'
+      lt_cv_prog_cc_static='-dn'
+      lt_cv_prog_cc_shlib='-belf'
+      ;;
+
+    solaris*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Wl,'
+      ;;
+
+    sunos4*)
+      lt_cv_prog_cc_pic='-PIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      lt_cv_prog_cc_wl='-Qoption ld '
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      lt_cv_prog_cc_pic='-KPIC'
+      lt_cv_prog_cc_static='-Bstatic'
+      if test "x$host_vendor" = xsni; then
+       lt_cv_prog_cc_wl='-LD'
+      else
+       lt_cv_prog_cc_wl='-Wl,'
+      fi
+      ;;
+
+    uts4*)
+      lt_cv_prog_cc_pic='-pic'
+      lt_cv_prog_cc_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_cv_prog_cc_pic='-Kconform_pic'
+       lt_cv_prog_cc_static='-Bstatic'
+      fi
+      ;;
+
+    *)
+      lt_cv_prog_cc_can_build_shared=no
+      ;;
+    esac
+  fi
+
+fi
+
+if test -z "$lt_cv_prog_cc_pic"; then
+  echo "$ac_t""none" 1>&6
+else
+  echo "$ac_t""$lt_cv_prog_cc_pic" 1>&6
+
+  # Check to make sure the pic_flag actually works.
+  echo $ac_n "checking if $compiler PIC flag $lt_cv_prog_cc_pic works""... $ac_c" 1>&6
+echo "configure:3436: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
+  if eval "test \"`echo '$''{'lt_cv_prog_cc_pic_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+      save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+    cat > conftest.$ac_ext <<EOF
+#line 3443 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3450: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+        case $host_os in
+      hpux9* | hpux10* | hpux11*)
+       # On HP-UX, both CC and GCC only warn that PIC is supported... then
+       # they create non-PIC objects.  So, if there were any warnings, we
+       # assume that PIC is not supported.
+       if test -s conftest.err; then
+         lt_cv_prog_cc_pic_works=no
+       else
+         lt_cv_prog_cc_pic_works=yes
+       fi
+       ;;
+      *)
+       lt_cv_prog_cc_pic_works=yes
+       ;;
+      esac
+    
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+        lt_cv_prog_cc_pic_works=no
+    
+fi
+rm -f conftest*
+    CFLAGS="$save_CFLAGS"
+  
+fi
+
+
+  if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+    lt_cv_prog_cc_pic=
+    lt_cv_prog_cc_can_build_shared=no
+  else
+    lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+  fi
+
+  echo "$ac_t""$lt_cv_prog_cc_pic_works" 1>&6
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$lt_cv_prog_cc_shlib"; then
+  echo "configure: warning: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" 1>&2
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[         ]$lt_cv_prog_cc_shlib[  ]" >/dev/null; then :
+  else
+   echo "configure: warning: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" 1>&2
+    lt_cv_prog_cc_can_build_shared=no
+  fi
+fi
+
+echo $ac_n "checking if $compiler static flag $lt_cv_prog_cc_static works""... $ac_c" 1>&6
+echo "configure:3502: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
+if eval "test \"`echo '$''{'lt_cv_prog_cc_static_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    lt_cv_prog_cc_static_works=no
+  save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+  cat > conftest.$ac_ext <<EOF
+#line 3510 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  lt_cv_prog_cc_static_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+  LDFLAGS="$save_LDFLAGS"
+
+fi
+
+
+# Belt *and* braces to stop my trousers falling down:
+test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+echo "$ac_t""$lt_cv_prog_cc_static_works" 1>&6
+
+pic_flag="$lt_cv_prog_cc_pic"
+special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+wl="$lt_cv_prog_cc_wl"
+link_static_flag="$lt_cv_prog_cc_static"
+no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+can_build_shared="$lt_cv_prog_cc_can_build_shared"
+
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.$ac_objext""... $ac_c" 1>&6
+echo "configure:3544: checking if $compiler supports -c -o file.$ac_objext" >&5
+if eval "test \"`echo '$''{'lt_cv_compiler_c_o'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+echo "int some_variable = 0;" > conftest.$ac_ext
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+compiler_c_o=no
+if { (eval echo configure:3563: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+  if test -s out/conftest.err; then
+    lt_cv_compiler_c_o=no
+  else
+    lt_cv_compiler_c_o=yes
+  fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&5
+  lt_cv_compiler_c_o=no
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+fi
+
+compiler_c_o=$lt_cv_compiler_c_o
+echo "$ac_t""$compiler_c_o" 1>&6
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  echo $ac_n "checking if $compiler supports -c -o file.lo""... $ac_c" 1>&6
+echo "configure:3592: checking if $compiler supports -c -o file.lo" >&5
+  if eval "test \"`echo '$''{'lt_cv_compiler_o_lo'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+  lt_cv_compiler_o_lo=no
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  save_objext="$ac_objext"
+  ac_objext=lo
+  cat > conftest.$ac_ext <<EOF
+#line 3603 "configure"
+#include "confdefs.h"
+
+int main() {
+int some_variable = 0;
+; return 0; }
+EOF
+if { (eval echo configure:3610: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+      # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      lt_cv_compiler_o_lo=no
+    else
+      lt_cv_compiler_o_lo=yes
+    fi
+  
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+  ac_objext="$save_objext"
+  CFLAGS="$save_CFLAGS"
+  
+fi
+
+  compiler_o_lo=$lt_cv_compiler_o_lo
+  echo "$ac_t""$compiler_o_lo" 1>&6
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  echo $ac_n "checking if we can lock with hard links""... $ac_c" 1>&6
+echo "configure:3641: checking if we can lock with hard links" >&5
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  echo "$ac_t""$hard_links" 1>&6
+  if test "$hard_links" = no; then
+    echo "configure: warning: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" 1>&2
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$GCC" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions""... $ac_c" 1>&6
+echo "configure:3660: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+  compiler_rtti_exceptions=no
+  cat > conftest.$ac_ext <<EOF
+#line 3666 "configure"
+#include "confdefs.h"
+
+int main() {
+int some_variable = 0;
+; return 0; }
+EOF
+if { (eval echo configure:3673: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+      # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+    if test -s conftest.err; then
+      compiler_rtti_exceptions=no
+    else
+      compiler_rtti_exceptions=yes
+    fi
+  
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+  CFLAGS="$save_CFLAGS"
+  echo "$ac_t""$compiler_rtti_exceptions" 1>&6
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+fi
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries""... $ac_c" 1>&6
+echo "configure:3700: checking whether the linker ($LD) supports shared libraries" >&5
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+old_archive_from_expsyms_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_into_libs=no
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+link_all_deplibs=unknown
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+extract_expsyms_cmds=
+
+case $host_os in
+cygwin* | mingw* | pw32*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$GCC" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+openbsd*)
+  with_gnu_ld=no
+  ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case $host_os in
+  aix3* | aix4* | aix5*)
+    # On AIX, the GNU linker is very broken
+    # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+      sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+      test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+      if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+      else $CC -o impgen impgen.c ; fi)~
+      $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+
+    old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+
+    # cygwin and mingw dlls have different entry points and sets of symbols
+    # to exclude.
+    # FIXME: what about values for MSVC?
+    dll_entry=__cygwin_dll_entry@12
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+    case $host_os in
+    mingw*)
+      # mingw values
+      dll_entry=_DllMainCRTStartup@12
+      dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+      ;;
+    esac
+
+    # mingw and cygwin differ, and it's simplest to just exclude the union
+    # of the two symbol sets.
+    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+
+    # recent cygwin and mingw systems supply a stub DllMain which the user
+    # can override, but on older systems we have to supply one (in ltdll.c)
+    if test "x$lt_cv_need_dllmain" = "xyes"; then
+      ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+      ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+       test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+    else
+      ltdll_obj=
+      ltdll_cmds=
+    fi
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    # Be careful not to strip the DATA tag left be newer dlltools.
+    export_symbols_cmds="$ltdll_cmds"'
+      $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+    # If the export-symbols file already is a .def file (1st line
+    # is EXPORTS), use it as is.
+    # If DATA tags from a recent dlltool are present, honour them!
+    archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname-def;
+      else
+       echo EXPORTS > $output_objdir/$soname-def;
+       _lt_hint=1;
+       cat $export_symbols | while read symbol; do
+        set dummy \$symbol;
+        case \$# in
+          2) echo "   \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+          *) echo "     \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;;
+        esac;
+        _lt_hint=`expr 1 + \$_lt_hint`;
+       done;
+      fi~
+      '"$ltdll_cmds"'
+      $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+      $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+      $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+      wlarc=
+    else
+      archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    fi
+    ;;
+
+  solaris* | sysv5*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw* | pw32*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec=
+      fi
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case $host_os in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$GCC" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+       done
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    hardcode_direct=yes
+    archive_cmds=''
+    hardcode_libdir_separator=':'
+    if test "$GCC" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+         strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         hardcode_direct=yes
+       else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+       fi
+      esac
+
+      shared_flag='-shared'
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       shared_flag='${wl}-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall can do strange things, so it is better to
+    # generate a list of symbols to export.
+    always_export_symbols=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag='-berok'
+      hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+      archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+    else
+      if test "$host_cpu" = ia64; then
+       hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+       allow_undefined_flag="-z nodefs"
+       archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+       hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='${wl}-berok'
+       # This is a bit strange, but is similar to how AIX traditionally builds
+       # it's shared libraries.
+       archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
+      fi
+    fi
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+    fix_srcfile_path='`cygpath -w "$srcfile"`'
+    ;;
+
+  darwin* | rhapsody*)
+    case "$host_os" in
+    rhapsody* | darwin1.[012])
+      allow_undefined_flag='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      allow_undefined_flag='-flat_namespace -undefined suppress'
+      ;;
+    esac
+    # FIXME: Relying on posixy $() will cause problems for
+    #        cross-compilation, but unfortunately the echo tests do not
+    #        yet detect zsh echo's removal of \ escapes.  Also zsh mangles
+    #       `"' quotes if we put them in here... so don't!
+    archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
+    # We need to add '_' to the symbols in $export_symbols first
+    #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    whole_archive_flag_spec='-all_load $convenience'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case $host_os in
+    hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+                        # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6* | nonstopux*)
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    link_all_deplibs=yes
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+    fi
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  newsos6)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+    else
+      case "$host_os" in
+      openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_libdir_flag_spec='-R$libdir'
+        ;;
+      *)
+        archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+        hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+        ;;
+      esac
+    fi
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+    ;;
+
+  osf3*)
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  osf4* | osf5*)       # as osf3* with the addition of -msym flag
+    if test "$GCC" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+      $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+      #Both c and cxx compiler support -rpath directly
+      hardcode_libdir_flag_spec='-rpath $libdir'
+    fi
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    export_dynamic_flag_spec='${wl}-Bexport'
+    ;;
+
+  solaris*)
+    # gcc --version < 3.0 without binutils cannot create self contained
+    # shared libraries reliably, requiring libgcc.a to resolve some of
+    # the object symbols generated in some cases.  Libraries that use
+    # assert need libgcc.a to resolve __eprintf, for example.  Linking
+    # a copy of libgcc.a into every shared library to guarantee resolving
+    # such symbols causes other problems:  According to Tim Van Holder
+    # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+    # (to the application) exception stack for one thing.
+    no_undefined_flag=' -z defs'
+    if test "$GCC" = yes; then
+      case `$CC --version 2>/dev/null` in
+      [12].*)
+       cat <<EOF 1>&2
+
+*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+*** create self contained shared libraries on Solaris systems, without
+*** introducing a dependency on libgcc.a.  Therefore, libtool is disabling
+*** -no-undefined support, which will at least allow you to build shared
+*** libraries.  However, you may find that when you link such libraries
+*** into an application without using GCC, you have to manually add
+*** \`gcc --print-libgcc-file-name\` to the link command.  We urge you to
+*** upgrade to a newer version of GCC.  Another option is to rebuild your
+*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+
+EOF
+        no_undefined_flag=
+       ;;
+      esac
+    fi
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case $host_os in
+    solaris2.[0-5] | solaris2.[0-5].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    link_all_deplibs=yes
+    ;;
+
+  sunos4*)
+    if test "x$host_vendor" = xsequent; then
+      # Use $CC to link under sequent, because it throws in some extra .o
+      # files that make .init and .fini sections work.
+      archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+    fi
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    if test "x$host_vendor" = xsno; then
+      archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes # is this really true???
+    else
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  sysv5*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+    hardcode_libdir_flag_spec=
+    hardcode_shlibpath_var=no
+    runpath_var='LD_RUN_PATH'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ld_shlibs=yes
+    fi
+    ;;
+
+  sysv4.2uw2*)
+    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+    hardcode_direct=yes
+    hardcode_minus_L=no
+    hardcode_shlibpath_var=no
+    hardcode_runpath_var=yes
+    runpath_var=LD_RUN_PATH
+    ;;
+
+  sysv5uw7* | unixware7*)
+    no_undefined_flag='${wl}-z ${wl}text'
+    if test "$GCC" = yes; then
+      archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    else
+      archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+    fi
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+echo "$ac_t""$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs""... $ac_c" 1>&6
+echo "configure:4385: checking how to hardcode library paths into programs" >&5
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+echo "$ac_t""$hardcode_action" 1>&6
+
+striplib=
+old_striplib=
+echo $ac_n "checking whether stripping libraries is possible""... $ac_c" 1>&6
+echo "configure:4413: checking whether stripping libraries is possible" >&5
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+# PORTME Fill in your ld.so characteristics
+echo $ac_n "checking dynamic linker characteristics""... $ac_c" 1>&6
+echo "configure:4427: checking dynamic linker characteristics" >&5
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+            echo ' yes '
+            echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+         :
+       else
+         can_build_shared=no
+       fi
+       ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can
+    # not hardcode correct soname into executable. Probably we can
+    # add versioning support to collect2, so additional links can
+    # be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}.so$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  export_dynamic_flag_spec=-rdynamic
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  need_version=no
+  need_lib_prefix=no
+  case $GCC,$host_os in
+  yes,cygwin*)
+    library_names_spec='$libname.dll.a'
+    soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog .libs/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    ;;
+  yes,mingw*)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+    sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
+    ;;
+  yes,pw32*)
+    library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll'
+    ;;
+  *)
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  # FIXME: Relying on posixy $() will cause problems for
+  #        cross-compilation, but unfortunately the echo tests do not
+  #        yet detect zsh echo's removal of \ escapes.
+  library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)'
+  soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  *)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)          version_type=irix ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case "$host_os" in
+    openbsd2.[89] | openbsd2.[89].*)
+      shlibpath_overrides_runpath=no
+      ;;
+    *)
+      shlibpath_overrides_runpath=yes
+      ;;
+    esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_version=no
+  need_lib_prefix=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+echo "$ac_t""$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo $ac_n "checking if libtool supports shared libraries""... $ac_c" 1>&6
+echo "configure:4828: checking if libtool supports shared libraries" >&5
+echo "$ac_t""$can_build_shared" 1>&6
+
+echo $ac_n "checking whether to build shared libraries""... $ac_c" 1>&6
+echo "configure:4832: checking whether to build shared libraries" >&5
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+echo "$ac_t""$enable_shared" 1>&6
+
+echo $ac_n "checking whether to build static libraries""... $ac_c" 1>&6
+echo "configure:4855: checking whether to build static libraries" >&5
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$ac_t""$enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  *)
+    echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "configure:4896: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4901 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char shl_load();
+
+int main() {
+
+/* 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_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4924: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "configure:4942: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4950 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo configure:4961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "configure:4980: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4985 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+
+/* 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_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:5008: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:5026: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5034 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:5045: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6
+echo "configure:5064: checking for dlopen in -lsvld" >&5
+ac_lib_var=`echo svld'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsvld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5072 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:5083: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "configure:5102: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5110 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo configure:5121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+             
+fi
+
+           
+fi
+
+         
+fi
+
+       
+fi
+
+      
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+        test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "configure:5177: checking whether a program can dlopen itself" >&5
+if eval "test \"`echo '$''{'lt_cv_dlopen_self'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 5187 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}
+EOF
+  if { (eval echo configure:5248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_unknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+    
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      LDFLAGS="$LDFLAGS $link_static_flag"
+      echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "configure:5271: checking whether a statically linked program can dlopen itself" >&5
+if eval "test \"`echo '$''{'lt_cv_dlopen_self_static'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 5281 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}
+EOF
+  if { (eval echo configure:5342: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+      
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+if test "$enable_shared" = yes && test "$GCC" = yes; then
+  case $archive_cmds in
+  *'~'*)
+    # FIXME: we may have to deal with multi-command sequences.
+    ;;
+  '$CC '*)
+    # Test whether the compiler implicitly links with -lc since on some
+    # systems, -lgcc has to come before -lc. If gcc already passes -lc
+    # to ld, don't add -lc before -lgcc.
+    echo $ac_n "checking whether -lc should be explicitly linked in""... $ac_c" 1>&6
+echo "configure:5391: checking whether -lc should be explicitly linked in" >&5
+    if eval "test \"`echo '$''{'lt_cv_archive_cmds_need_lc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  $rm conftest*
+    echo 'static int dummy;' > conftest.$ac_ext
+
+    if { (eval echo configure:5398: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+      soname=conftest
+      lib=conftest
+      libobjs=conftest.$ac_objext
+      deplibs=
+      wl=$lt_cv_prog_cc_wl
+      compiler_flags=-v
+      linker_flags=-v
+      verstring=
+      output_objdir=.
+      libname=conftest
+      save_allow_undefined_flag=$allow_undefined_flag
+      allow_undefined_flag=
+      if { (eval echo configure:5411: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\") 1>&5; (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5; }
+      then
+       lt_cv_archive_cmds_need_lc=no
+      else
+       lt_cv_archive_cmds_need_lc=yes
+      fi
+      allow_undefined_flag=$save_allow_undefined_flag
+    else
+      cat conftest.err 1>&5
+    fi
+fi
+
+    echo "$ac_t""$lt_cv_archive_cmds_need_lc" 1>&6
+    ;;
+  esac
+fi
+need_lc=${lt_cv_archive_cmds_need_lc-yes}
+
+# The second clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  :
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  test -f Makefile && make "$ltmain"
+fi
+
+if test -f "$ltmain"; then
+  trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+  $rm -f "${ofile}T"
+
+  echo creating $ofile
+
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS \
+    AR AR_FLAGS CC LD LN_S NM SHELL \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+    postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+    old_striplib striplib file_magic_cmd export_symbols_cmds \
+    deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    global_symbol_to_c_name_address \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case $var in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  cat <<__EOF__ > "${ofile}T"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# 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.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$need_lc
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# The default C compiler.
+CC=$lt_CC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_pic_flag
+pic_mode=$pic_mode
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$lt_compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "${ofile}T"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | os2*)
+    cat <<'EOF' >> "${ofile}T"
+      # This is a source program that is used to create dlls on Windows
+      # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+       # This is a source program that is used to create import libraries
+       # on Windows for dlls which lack them. Don't remove nor modify the
+       # starting and closing comments
+# /* impgen.c starts here */
+# /*   Copyright (C) 1999-2000 Free Software Foundation, Inc.
+#
+#  This file is part of GNU libtool.
+#
+#  This program 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, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  */
+#
+# #include <stdio.h>           /* for printf() */
+# #include <unistd.h>          /* for open(), lseek(), read() */
+# #include <fcntl.h>           /* for O_RDONLY, O_BINARY */
+# #include <string.h>          /* for strdup() */
+#
+# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+# #ifndef O_BINARY
+# #define O_BINARY 0
+# #endif
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+#      int fd;
+#      int offset;
+# {
+#   unsigned char b[2];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 2);
+#   return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+#     int fd;
+#     int offset;
+# {
+#   unsigned char b[4];
+#   lseek (fd, offset, SEEK_SET);
+#   read (fd, b, 4);
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+#      void *ptr;
+# {
+#   unsigned char *b = ptr;
+#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+#     int argc;
+#     char *argv[];
+# {
+#     int dll;
+#     unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+#     unsigned long export_rva, export_size, nsections, secptr, expptr;
+#     unsigned long name_rvas, nexp;
+#     unsigned char *expdata, *erva;
+#     char *filename, *dll_name;
+#
+#     filename = argv[1];
+#
+#     dll = open(filename, O_RDONLY|O_BINARY);
+#     if (dll < 1)
+#      return 1;
+#
+#     dll_name = filename;
+#
+#     for (i=0; filename[i]; i++)
+#      if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
+#          dll_name = filename + i +1;
+#
+#     pe_header_offset = pe_get32 (dll, 0x3c);
+#     opthdr_ofs = pe_header_offset + 4 + 20;
+#     num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+#     if (num_entries < 1) /* no exports */
+#      return 1;
+#
+#     export_rva = pe_get32 (dll, opthdr_ofs + 96);
+#     export_size = pe_get32 (dll, opthdr_ofs + 100);
+#     nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+#     secptr = (pe_header_offset + 4 + 20 +
+#            pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+#     expptr = 0;
+#     for (i = 0; i < nsections; i++)
+#     {
+#      char sname[8];
+#      unsigned long secptr1 = secptr + 40 * i;
+#      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+#      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+#      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+#      lseek(dll, secptr1, SEEK_SET);
+#      read(dll, sname, 8);
+#      if (vaddr <= export_rva && vaddr+vsize > export_rva)
+#      {
+#          expptr = fptr + (export_rva - vaddr);
+#          if (export_rva + export_size > vaddr + vsize)
+#              export_size = vsize - (export_rva - vaddr);
+#          break;
+#      }
+#     }
+#
+#     expdata = (unsigned char*)malloc(export_size);
+#     lseek (dll, expptr, SEEK_SET);
+#     read (dll, expdata, export_size);
+#     erva = expdata - export_rva;
+#
+#     nexp = pe_as32 (expdata+24);
+#     name_rvas = pe_as32 (expdata+32);
+#
+#     printf ("EXPORTS\n");
+#     for (i = 0; i<nexp; i++)
+#     {
+#      unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+#      printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+#     }
+#
+#     return 0;
+# }
+# /* impgen.c ends here */
+
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+
+  mv -f "${ofile}T" "$ofile" || \
+    (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+  chmod +x "$ofile"
+fi
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+
+
+#dnl Replace `main' with a function in -ldl:
+#AC_CHECK_LIB(dl, main)
+#dnl Replace `main' with a function in -lpthread:
+#AC_CHECK_LIB(pthread, main)
+
+#CPPFLAGS="$CPPFLAGS -I/usr/include/postgresql"
+#LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+echo $ac_n "checking for getopt_long in -lgnugetopt""... $ac_c" 1>&6
+echo "configure:6010: checking for getopt_long in -lgnugetopt" >&5
+ac_lib_var=`echo gnugetopt'_'getopt_long | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lgnugetopt  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6018 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char getopt_long();
+
+int main() {
+getopt_long()
+; return 0; }
+EOF
+if { (eval echo configure:6032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -lgnugetopt"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
+echo "configure:6054: checking how to run the C++ preprocessor" >&5
+if test -z "$CXXCPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+  CXXCPP="${CXX-g++} -E"
+  cat > conftest.$ac_ext <<EOF
+#line 6067 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CXXCPP=/lib/cpp
+fi
+rm -f conftest*
+  ac_cv_prog_CXXCPP="$CXXCPP"
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+fi
+fi
+CXXCPP="$ac_cv_prog_CXXCPP"
+echo "$ac_t""$CXXCPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:6097: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6102 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6110: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 6127 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 > conftest.$ac_ext <<EOF
+#line 6145 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 > conftest.$ac_ext <<EOF
+#line 6166 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#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)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:6180: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h getopt.h limits.h strings.h sys/time.h syslog.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:6207: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6212 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:6245: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6250 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:6278: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6283 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:6292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_time=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+  cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:6313: checking whether struct tm is in sys/time.h or time.h" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6318 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:6326: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_struct_tm=time.h
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+  cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+
+echo $ac_n "checking whether setvbuf arguments are reversed""... $ac_c" 1>&6
+echo "configure:6348: checking whether setvbuf arguments are reversed" >&5
+if eval "test \"`echo '$''{'ac_cv_func_setvbuf_reversed'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6356 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#include <stdio.h>
+/* If setvbuf has the reversed format, exit 0. */
+main () {
+  /* This call has the arguments reversed.
+     A reversed system may check and see that the address of main
+     is not _IOLBF, _IONBF, or _IOFBF, and return nonzero.  */
+  if (setvbuf(stdout, _IOLBF, (char *) main, BUFSIZ) != 0)
+    exit(1);
+  putc('\r', stdout);
+  exit(0);                     /* Non-reversed systems segv here.  */
+}
+EOF
+if { (eval echo configure:6373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_setvbuf_reversed=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_setvbuf_reversed=no
+fi
+rm -fr conftest*
+fi
+
+rm -f core core.* *.core
+fi
+
+echo "$ac_t""$ac_cv_func_setvbuf_reversed" 1>&6
+if test $ac_cv_func_setvbuf_reversed = yes; then
+  cat >> confdefs.h <<\EOF
+#define SETVBUF_REVERSED 1
+EOF
+
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:6397: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6402 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:6419: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_type_signal=void
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for strftime""... $ac_c" 1>&6
+echo "configure:6438: checking for strftime" >&5
+if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6443 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strftime(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char strftime();
+
+int main() {
+
+/* 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_strftime) || defined (__stub___strftime)
+choke me
+#else
+strftime();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6469: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_strftime=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_strftime=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+else
+  echo "$ac_t""no" 1>&6
+# strftime is in -lintl on SCO UNIX.
+echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
+echo "configure:6491: checking for strftime in -lintl" >&5
+ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lintl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6499 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char strftime();
+
+int main() {
+strftime()
+; return 0; }
+EOF
+if { (eval echo configure:6513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+LIBS="-lintl $LIBS"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_func in gethostname gettimeofday mkdir mktime select socket strerror
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6542: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6547 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* 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_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+
+# #
+# # Check if we have libresolv. XXX If we do not have libresolv then we
+# # cannot build the 'resolver'. Is it possible to remove that target
+# # conditionally?
+# #
+# 
+# AC_CHECK_LIB(resolv, res_mkquery, RESOLV_LIBS="-l resolv")
+# AC_MSG_CHECKING("for resolver library")
+# if test -f /usr/lib/libresolv.so -o -f /lib/libresolv.o
+# then
+#   AC_MSG_RESULT("yes")
+#   LIBS="$LIBS -lresolv"
+# else
+#   AC_MSG_RESULT("no")
+# fi
+
+#
+# Check for libresolv
+#
+
+my_save_LIBS="$LIBS"
+LIBS=""
+echo $ac_n "checking for res_mkquery in -lresolv""... $ac_c" 1>&6
+echo "configure:6623: checking for res_mkquery in -lresolv" >&5
+ac_lib_var=`echo resolv'_'res_mkquery | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lresolv  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6631 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char res_mkquery();
+
+int main() {
+res_mkquery()
+; return 0; }
+EOF
+if { (eval echo configure:6645: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo resolv | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lresolv $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+LIBRESOLV=$LIBS
+LIBS="$my_save_LIBS"
+
+
+#
+# Check for libdl
+#
+
+my_save_LIBS="$LIBS"
+LIBS=""
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:6683: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6691 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:6705: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo dl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-ldl $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+LIBDL=$LIBS
+LIBS="$my_save_LIBS"
+
+
+
+#
+# The following code checks for the right pthreads library and linker
+# flags. It was taken from MySQL, so we should have the same platform
+# support as they have.
+#
+# XXX Dit is nog niet correct. Als dit matched dan moet de rest van de
+# XXX thread checks niet. Fixen als we solaris hebben.
+#
+
+#AC_MSG_CHECKING("for Solaris threads")
+#if test -f /usr/lib/libpthread.so -a -f /usr/lib/libthread.so
+#then
+#  with_named_thread="-lpthread -lthread"
+#  AC_MSG_RESULT("yes")
+#else
+#  AC_MSG_RESULT("no")
+#fi
+
+# pthread_create is in standard libraries (As in BSDI 3.0)
+echo $ac_n "checking "for pthread_create in -libc"""... $ac_c" 1>&6
+echo "configure:6757: checking "for pthread_create in -libc"" >&5;
+cat > conftest.$ac_ext <<EOF
+#line 6759 "configure"
+#include "confdefs.h"
+#include <pthread.h>
+int main() {
+ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); 
+; return 0; }
+EOF
+if { (eval echo configure:6766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  with_posix_threads=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  with_posix_threads=no
+fi
+rm -f conftest*
+echo "$ac_t"""$with_posix_threads"" 1>&6
+if test "$with_posix_threads" = "no"
+then
+  echo $ac_n "checking "for pthread_create in -lpthread"""... $ac_c" 1>&6
+echo "configure:6780: checking "for pthread_create in -lpthread"" >&5;
+  ac_save_LIBS="$LIBS"
+  LIBS="$LIBS -lpthread"
+  cat > conftest.$ac_ext <<EOF
+#line 6784 "configure"
+#include "confdefs.h"
+#include <pthread.h>
+int main() {
+ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); 
+; return 0; }
+EOF
+if { (eval echo configure:6791: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  with_posix_threads=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  with_posix_threads=no
+fi
+rm -f conftest*
+  echo "$ac_t"""$with_posix_threads"" 1>&6
+  if test "$with_posix_threads" = "no"
+  then
+    LIBS=" $ac_save_LIBS -lpthreads"
+    echo $ac_n "checking "for pthread_create in -lpthreads"""... $ac_c" 1>&6
+echo "configure:6806: checking "for pthread_create in -lpthreads"" >&5;
+    cat > conftest.$ac_ext <<EOF
+#line 6808 "configure"
+#include "confdefs.h"
+#include <pthread.h>
+int main() {
+ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); 
+; return 0; }
+EOF
+if { (eval echo configure:6815: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  with_posix_threads=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  with_posix_threads=no
+fi
+rm -f conftest*
+    echo "$ac_t"""$with_posix_threads"" 1>&6
+    if test "$with_posix_threads" = "no"
+    then
+         # This is for FreeBSD
+         LIBS="$ac_save_LIBS -pthread"
+         echo $ac_n "checking "for pthread_create in -pthread"""... $ac_c" 1>&6
+echo "configure:6831: checking "for pthread_create in -pthread"" >&5;
+         cat > conftest.$ac_ext <<EOF
+#line 6833 "configure"
+#include "confdefs.h"
+#include <pthread.h>
+int main() {
+ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); 
+; return 0; }
+EOF
+if { (eval echo configure:6840: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  with_posix_threads=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  with_posix_threads=no
+fi
+rm -f conftest*
+      echo "$ac_t"""$with_posix_threads"" 1>&6
+      if test "$with_posix_threads" = "no"
+         then
+           with_mit_threads="yes"
+           LIBS="$ac_save_LIBS"
+         fi
+       fi
+  fi
+fi
+
+case "$host_os" in
+solaris2*) cat >> confdefs.h <<\EOF
+#define NEED_POSIX_TYPEDEF 1
+EOF
+
+       ;;
+*)
+       ;;
+esac
+
+ac_safe=`echo "sstream" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for sstream""... $ac_c" 1>&6
+echo "configure:6872: checking for sstream" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 6877 "configure"
+#include "confdefs.h"
+#include <sstream>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6882: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  dontneedstl=1
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test "$dontneedstl" != "1" 
+then
+
+# Check whether --with-stl-includes or --without-stl-includes was given.
+if test "${with_stl_includes+set}" = set; then
+  withval="$with_stl_includes"
+   if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_INCLUDES="-I$withval"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+fi
+
+
+
+# Check whether --with-stl-libs or --without-stl-libs was given.
+if test "${with_stl_libs+set}" = set; then
+  withval="$with_stl_libs"
+   if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_LIBS="$LIBS -L$withval -lstlport_gcc"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+fi
+
+
+
+
+
+
+if test x"$search_stl" != x"0"; then
+   echo $ac_n "checking "location of sstream"""... $ac_c" 1>&6
+echo "configure:6948: checking "location of sstream"" >&5
+   if test x"$search_stl" != x"0"; then
+    if test -f "/usr/include/sstream"; then
+      echo "$ac_t"""found in /usr/include"" 1>&6
+      STL_LIBS="-lstlport_gcc"
+      STL_INCLUDES=""
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+   if test x"$search_stl" != x"0"; then
+    if test -f "/usr/include/stlport/sstream"; then
+      echo "$ac_t"""found in /usr/include/stlport"" 1>&6
+      STL_LIBS="-lstlport_gcc"
+      STL_INCLUDES="-I/usr/include/stlport"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+   if test x"$search_stl" != x"0"; then
+    if test -f "/usr/local/include/sstream"; then
+      echo "$ac_t"""found in /usr/local"" 1>&6
+      STL_LIBS="-L/usr/local/lib -lstlport_gcc"
+      STL_INCLUDES="-I/usr/local/include"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+   if test x"$search_stl" != x"0"; then
+    if test -f "/usr/local/include/stl/sstream"; then
+      echo "$ac_t"""found in /usr/local/include/stl"" 1>&6
+      STL_LIBS="-L/usr/local/lib -L/usr/local/lib/stl -lstlport_gcc"
+      STL_INCLUDES="-I/usr/local/include/stl"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+   if test x"$search_stl" != x"0"; then
+    if test -f "/home/ahu/download/STLport-4.0/stlport/sstream"; then
+      echo "$ac_t"""found in /home/ahu/download/STLport-4.0/stlport"" 1>&6
+      STL_LIBS="-L/home/ahu/download/STLport-4.0/lib/ -lstlport_gcc"
+      STL_INCLUDES="-I/home/ahu/download/STLport-4.0/stlport/"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+   if test x"$search_stl" != x"0"; then
+    if test -f "$HOME/STLport-4.0/stlport/sstream"; then
+      echo "$ac_t"""found in $HOME/STLport-4.0/stlport"" 1>&6
+      STL_LIBS="-L$HOME/STLport-4.0/lib/ -lstlport_gcc"
+      STL_INCLUDES="-I$HOME/STLport-4.0/stlport/"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+
+
+fi
+
+if test x"$has_stl" = x"1"; then
+       echo Found sstream include file, assuming working and compliant STL
+else
+       echo
+       echo Did not find sstream include file, this probably means that your STL is not
+       echo compliant - the default gcc libstdc++ isn\'t. Download STLport-4.0 from
+       echo http://www.stlport.org, or use --with-stl-includes and --with-stl-libs
+       echo to specify the location of your STL.
+       echo
+       exit 1 
+fi
+
+CPPFLAGS="$CPPFLAGS $STL_INCLUDES"
+LIBS="$LIBS $STL_LIBS" 
+fi
+
+echo $ac_n "checking whether we will be doing verbose logging""... $ac_c" 1>&6
+echo "configure:7029: checking whether we will be doing verbose logging" >&5
+# Check whether --enable-verbose-logging or --disable-verbose-logging was given.
+if test "${enable_verbose_logging+set}" = set; then
+  enableval="$enable_verbose_logging"
+  enable_verbose_logging=yes 
+else
+  enable_verbose_logging=no
+fi
+
+
+if test $enable_verbose_logging = yes; then cat >> confdefs.h <<\EOF
+#define VERBOSELOG 1
+EOF
+fi
+echo "$ac_t""$enable_verbose_logging" 1>&6
+
+echo $ac_n "checking whether we should build static binaries""... $ac_c" 1>&6
+echo "configure:7047: checking whether we should build static binaries" >&5
+# Check whether --enable-static-binaries or --disable-static-binaries was given.
+if test "${enable_static_binaries+set}" = set; then
+  enableval="$enable_static_binaries"
+  enable_static_binaries=yes 
+else
+  enable_static_binaries=no
+fi
+
+
+if test $enable_static_binaries = yes; 
+then 
+       LDFLAGS="-all-static $LD_FLAGS"
+fi
+echo "$ac_t""$enable_static_binaries" 1>&6
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# 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.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile codedocs/Makefile backends/bind/Makefile \
+backends/Makefile \
+pdns.conf-dist buildroot.sh \
+showvar pdns mkbindist config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@EXEEXT@%$EXEEXT%g
+s%@OBJEXT@%$OBJEXT%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@AMTAR@%$AMTAR%g
+s%@install_sh@%$install_sh%g
+s%@INSTALL_STRIP_PROGRAM@%$INSTALL_STRIP_PROGRAM%g
+s%@AWK@%$AWK%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@AMDEP_TRUE@%$AMDEP_TRUE%g
+s%@AMDEP_FALSE@%$AMDEP_FALSE%g
+s%@AMDEPBACKSLASH@%$AMDEPBACKSLASH%g
+s%@DEPDIR@%$DEPDIR%g
+s%@CC@%$CC%g
+s%@am__include@%$am__include%g
+s%@am__quote@%$am__quote%g
+s%@CCDEPMODE@%$CCDEPMODE%g
+s%@CXX@%$CXX%g
+s%@CXXDEPMODE@%$CXXDEPMODE%g
+s%@YACC@%$YACC%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@CPP@%$CPP%g
+s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+s%@LN_S@%$LN_S%g
+s%@ECHO@%$ECHO%g
+s%@RANLIB@%$RANLIB%g
+s%@STRIP@%$STRIP%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@CXXCPP@%$CXXCPP%g
+s%@LIBRESOLV@%$LIBRESOLV%g
+s%@LIBDL@%$LIBDL%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile codedocs/Makefile backends/bind/Makefile \
+backends/Makefile \
+pdns.conf-dist buildroot.sh \
+showvar pdns mkbindist"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #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.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+am_indx=1
+for am_file in config.h; do
+  case " \$CONFIG_HEADERS " in
+  *" \$am_file "*)
+    am_dir=\`echo \$am_file |sed 's%:.*%%;s%[^/]*\$%%'\`
+    if test -n "\$am_dir"; then
+      am_tmpdir=\`echo \$am_dir |sed 's%^\(/*\).*\$%\1%'\`
+      for am_subdir in \`echo \$am_dir |sed 's%/% %'\`; do
+        am_tmpdir=\$am_tmpdir\$am_subdir/
+        if test ! -d \$am_tmpdir; then
+          mkdir \$am_tmpdir
+        fi
+      done
+    fi
+    echo timestamp > "\$am_dir"stamp-h\$am_indx
+    ;;
+  esac
+  am_indx=\`expr \$am_indx + 1\`
+done
+AMDEP_TRUE="$AMDEP_TRUE"
+ac_aux_dir="$ac_aux_dir"
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp >     stamp-h
+
+test x"$AMDEP_TRUE" != x"" ||
+for mf in $CONFIG_FILES; do
+  case "$mf" in
+  Makefile) dirpart=.;;
+  */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;;
+  *) continue;;
+  esac
+  grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue
+  # Extract the definition of DEP_FILES from the Makefile without
+  # running `make'.
+  DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n -e '/^U = / s///p' < "$mf"`
+  test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
+  # We invoke sed twice because it is the simplest approach to
+  # changing $(DEPDIR) to its actual value in the expansion.
+  for file in `sed -n -e '
+    /^DEP_FILES = .*\\\\$/ {
+      s/^DEP_FILES = //
+      :loop
+       s/\\\\$//
+       p
+       n
+       /\\\\$/ b loop
+      p
+    }
+    /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`echo "$file" | sed -e 's|/[^/]*$||'`
+    $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/pdns/configure.in b/pdns/configure.in
new file mode 100644 (file)
index 0000000..f2731c6
--- /dev/null
@@ -0,0 +1,252 @@
+dnl intro
+AC_INIT(receiver.cc)
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE(pdns, 2.9)
+AM_CONFIG_HEADER(config.h)
+CXXFLAGS="-Wall -pthread -O2"
+
+AC_PREFIX_DEFAULT(/opt/pdns)
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_YACC
+AM_PROG_LEX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AM_PROG_LIBTOOL 
+AC_LANG_CPLUSPLUS
+
+
+#dnl Replace `main' with a function in -ldl:
+#AC_CHECK_LIB(dl, main)
+#dnl Replace `main' with a function in -lpthread:
+#AC_CHECK_LIB(pthread, main)
+
+#CPPFLAGS="$CPPFLAGS -I/usr/include/postgresql"
+#LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+AC_CHECK_LIB(gnugetopt,getopt_long,LIBS="$LIBS -lgnugetopt")
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h getopt.h limits.h strings.h sys/time.h syslog.h unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+AC_FUNC_SETVBUF_REVERSED
+AC_TYPE_SIGNAL
+AC_FUNC_STRFTIME
+AC_CHECK_FUNCS(gethostname gettimeofday mkdir mktime select socket strerror)
+
+
+
+# #
+# # Check if we have libresolv. XXX If we do not have libresolv then we
+# # cannot build the 'resolver'. Is it possible to remove that target
+# # conditionally?
+# #
+# 
+# AC_CHECK_LIB(resolv, res_mkquery, RESOLV_LIBS="-l resolv")
+# AC_MSG_CHECKING("for resolver library")
+# if test -f /usr/lib/libresolv.so -o -f /lib/libresolv.o
+# then
+#   AC_MSG_RESULT("yes")
+#   LIBS="$LIBS -lresolv"
+# else
+#   AC_MSG_RESULT("no")
+# fi
+
+#
+# Check for libresolv
+#
+
+my_save_LIBS="$LIBS"
+LIBS=""
+AC_CHECK_LIB(resolv,res_mkquery)
+LIBRESOLV=$LIBS
+LIBS="$my_save_LIBS"
+AC_SUBST(LIBRESOLV)
+
+#
+# Check for libdl
+#
+
+my_save_LIBS="$LIBS"
+LIBS=""
+AC_CHECK_LIB(dl,dlopen)
+LIBDL=$LIBS
+LIBS="$my_save_LIBS"
+AC_SUBST(LIBDL)
+
+
+#
+# The following code checks for the right pthreads library and linker
+# flags. It was taken from MySQL, so we should have the same platform
+# support as they have.
+#
+# XXX Dit is nog niet correct. Als dit matched dan moet de rest van de
+# XXX thread checks niet. Fixen als we solaris hebben.
+#
+
+#AC_MSG_CHECKING("for Solaris threads")
+#if test -f /usr/lib/libpthread.so -a -f /usr/lib/libthread.so
+#then
+#  with_named_thread="-lpthread -lthread"
+#  AC_MSG_RESULT("yes")
+#else
+#  AC_MSG_RESULT("no")
+#fi
+
+# pthread_create is in standard libraries (As in BSDI 3.0)
+AC_MSG_CHECKING("for pthread_create in -libc");
+AC_TRY_LINK(
+[#include <pthread.h>],
+[ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
+with_posix_threads=yes, with_posix_threads=no)
+AC_MSG_RESULT("$with_posix_threads")
+if test "$with_posix_threads" = "no"
+then
+  AC_MSG_CHECKING("for pthread_create in -lpthread");
+  ac_save_LIBS="$LIBS"
+  LIBS="$LIBS -lpthread"
+  AC_TRY_LINK(
+  [#include <pthread.h>],
+  [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
+  with_posix_threads=yes, with_posix_threads=no)
+  AC_MSG_RESULT("$with_posix_threads")
+  if test "$with_posix_threads" = "no"
+  then
+    LIBS=" $ac_save_LIBS -lpthreads"
+    AC_MSG_CHECKING("for pthread_create in -lpthreads");
+    AC_TRY_LINK(
+    [#include <pthread.h>],
+    [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
+    with_posix_threads=yes, with_posix_threads=no)
+    AC_MSG_RESULT("$with_posix_threads")
+    if test "$with_posix_threads" = "no"
+    then
+         # This is for FreeBSD
+         LIBS="$ac_save_LIBS -pthread"
+         AC_MSG_CHECKING("for pthread_create in -pthread");
+         AC_TRY_LINK(
+         [#include <pthread.h>],
+         [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
+         with_posix_threads=yes, with_posix_threads=no)
+      AC_MSG_RESULT("$with_posix_threads")
+      if test "$with_posix_threads" = "no"
+         then
+           with_mit_threads="yes"
+           LIBS="$ac_save_LIBS"
+         fi
+       fi
+  fi
+fi
+
+case "$host_os" in
+solaris2*) AC_DEFINE(NEED_POSIX_TYPEDEF)
+       ;;
+*)
+       ;;
+esac
+
+AC_CHECK_HEADER(sstream,dontneedstl=1)
+
+if test "$dontneedstl" != "1" 
+then
+
+AC_ARG_WITH(stl-includes, [  --with-stl-includes=PATH Specify location of STL headers],
+[ if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_INCLUDES="-I$withval"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+
+AC_ARG_WITH(stl-libs, [  --with-stl-libs=PATH    Specify location of STL libs],
+[ if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_LIBS="$LIBS -L$withval -lstlport_gcc"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+AC_DEFUN(AC_CHECK_STL,
+[ if test x"$search_stl" != x"0"; then
+    if test -f "$1/$2"; then
+      AC_MSG_RESULT($5)
+      STL_LIBS="$3"
+      STL_INCLUDES="$4"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+AC_DEFUN(AC_SEARCH_STL,
+[ AC_MSG_CHECKING("location of sstream")
+  AC_CHECK_STL(/usr/include, sstream, -lstlport_gcc,, "found in /usr/include")
+  AC_CHECK_STL(/usr/include/stlport, sstream, -lstlport_gcc, -I/usr/include/stlport, "found in /usr/include/stlport")
+  AC_CHECK_STL(/usr/local/include, sstream, -L/usr/local/lib -lstlport_gcc, -I/usr/local/include, "found in /usr/local")
+  AC_CHECK_STL(/usr/local/include/stl, sstream, -L/usr/local/lib -L/usr/local/lib/stl -lstlport_gcc, -I/usr/local/include/stl, "found in /usr/local/include/stl")
+  AC_CHECK_STL(/home/ahu/download/STLport-4.0/stlport, sstream,-L/home/ahu/download/STLport-4.0/lib/ -lstlport_gcc, -I/home/ahu/download/STLport-4.0/stlport/, "found in /home/ahu/download/STLport-4.0/stlport")
+  AC_CHECK_STL($HOME/STLport-4.0/stlport, sstream,-L$HOME/STLport-4.0/lib/ -lstlport_gcc, -I$HOME/STLport-4.0/stlport/, "found in $HOME/STLport-4.0/stlport")
+])
+
+if test x"$search_stl" != x"0"; then
+  AC_SEARCH_STL()
+fi
+
+if test x"$has_stl" = x"1"; then
+       echo Found sstream include file, assuming working and compliant STL
+else
+       echo
+       echo Did not find sstream include file, this probably means that your STL is not
+       echo compliant - the default gcc libstdc++ isn\'t. Download STLport-4.0 from
+       echo http://www.stlport.org, or use --with-stl-includes and --with-stl-libs
+       echo to specify the location of your STL.
+       echo
+       exit 1 
+fi
+
+CPPFLAGS="$CPPFLAGS $STL_INCLUDES"
+LIBS="$LIBS $STL_LIBS" 
+fi
+
+AC_MSG_CHECKING(whether we will be doing verbose logging)
+AC_ARG_ENABLE(verbose-logging, 
+ [  --enable-verbose-logging   Do verbose logging],enable_verbose_logging=yes ,enable_verbose_logging=no)
+
+if test $enable_verbose_logging = yes; then AC_DEFINE(VERBOSELOG, 1) 
+fi
+AC_MSG_RESULT($enable_verbose_logging)
+
+AC_MSG_CHECKING(whether we should build static binaries)
+AC_ARG_ENABLE(static-binaries, 
+ [  --enable-static-binaries   Build static binaries],enable_static_binaries=yes ,enable_static_binaries=no)
+
+if test $enable_static_binaries = yes; 
+then 
+       LDFLAGS="-all-static $LD_FLAGS"
+fi
+AC_MSG_RESULT($enable_static_binaries)
+
+
+
+AC_OUTPUT(Makefile codedocs/Makefile backends/bind/Makefile \
+backends/Makefile \
+pdns.conf-dist buildroot.sh \
+showvar pdns mkbindist)
diff --git a/pdns/debian/changelog b/pdns/debian/changelog
new file mode 100644 (file)
index 0000000..8db0cf8
--- /dev/null
@@ -0,0 +1,367 @@
+pdns (1:2.8-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 3 Nov 2002 15:22:25 +0100
+
+
+pdns (1:2.7.1-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Fri, 1 Nov 2002 15:22:25 +0100
+
+pdns (1:2.7-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 28 Oct 2002 15:22:25 +0100
+
+pdns (1:2.6.1-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 16 Oct 2002 15:22:25 +0100
+
+pdns (1:2.6-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Fri, 14 Oct 2002 15:22:25 +0100
+
+pdns (1:2.5.1-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Fri, 4 Oct 2002 15:22:25 +0100
+
+pdns (1:2.5-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 26 Sep 2002 15:22:25 +0100
+
+pdns (1:2.4-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 16 Sep 2002 15:22:25 +0100
+
+pdns (1:2.3-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 16 Sep 2002 15:22:25 +0100
+
+pdns (1:2.2-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 11 Sep 2002 15:22:25 +0100
+
+pdns (1:2.1-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 2 Sep 2002 15:22:25 +0100
+
+pdns (1:2.0.1-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 2 Sep 2002 15:22:25 +0100
+
+pdns (1:2.0-2) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 12 Aug 2002 15:22:25 +0100
+
+pdns (1:2.0-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 12 Aug 2002 15:22:25 +0100
+
+pdns (2.0) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 30 Jul 2002 15:22:25 +0100
+
+pdns (2.0rc2) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 8 Jul 2002 15:22:25 +0100
+
+pdns (2.0rc1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 17 Jun 2002 15:22:25 +0100
+
+pdns (2.0rc1-SNAPSHOT-20020601-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Sat, 1 Jun 2002 15:22:25 +0100
+
+pdns (1.99.12-2) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 22 May 2002 15:22:25 +0100
+
+pdns (1.99.12-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 16 May 2002 15:22:25 +0100
+
+pdns (1.99.11-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Mon, 6 May 2002 15:22:25 +0100
+
+pdns (1.99.10-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Thu, 2 May 2002 15:22:25 +0100
+
+pdns (1.99.9-6) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 18 Apr 2002 15:22:25 +0100
+
+pdns (1.99.9-5) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 15 Apr 2002 14:22:25 +0100
+
+pdns (1.99.9-4) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 15 Apr 2002 14:22:25 +0100
+
+pdns (1.99.9-3) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 15 Apr 2002 14:22:25 +0100
+
+pdns (1.99.9-2) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 15 Apr 2002 14:22:25 +0100
+
+
+pdns (1.99.9-1) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Tue, 9 Apr 2002 14:22:25 +0100
+
+pdns (1.99.8-2) experimental; urgency=low
+
+  * upstream update
+
+ -- bert hubert <bert@powerdns.com>  Tue, 9 Apr 2002 14:22:25 +0100
+
+pdns (1.99.8-1) experimental; urgency=low
+
+  * upstream update
+
+ -- bert hubert <bert@powerdns.com>  Fri, 5 Apr 2002 16:38:25 +0100
+
+pdns (1.99.7-2) experimental; urgency=low
+
+  * upstream update
+
+ -- bert hubert <bert@powerdns.com>  Fri, 29 Mar 2002 15:34:25 +0100
+
+pdns (1.99.7-1) experimental; urgency=low
+
+  * upstream update
+
+ -- bert hubert <bert@powerdns.com>  Fri, 29 Mar 2002 20:34:25 +0100
+
+pdns (1.99.6-8) experimental; urgency=low
+
+  * forgot pdns backend
+
+ -- bert hubert <bert@powerdns.com>  Wed, 27 Mar 2002 20:34:25 +0100
+
+pdns (1.99.6-7) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 27 Mar 2002 17:34:25 +0100
+
+pdns (1.99.6-6) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 27 Mar 2002 16:34:25 +0100
+
+pdns (1.99.6-5) experimental; urgency=low
+
+  * upstream
+
+ -- bert hubert <bert@powerdns.com>  Wed, 27 Mar 2002 12:34:25 +0100
+
+pdns (1.99.6-4) experimental; urgency=low
+
+  * added documentation
+
+ -- bert hubert <bert@powerdns.com>  Wed, 27 Mar 2002 12:34:25 +0100
+
+pdns (1.99.6-3) experimental; urgency=low
+
+  * add gpgsql backend
+
+ -- bert hubert <bert@powerdns.com>  Tue, 26 Mar 2002 16:34:25 +0100
+
+pdns (1.99.6-2) experimental; urgency=low
+
+  * better preinst
+
+ -- bert hubert <bert@powerdns.com>  Mon, 25 Mar 2002 23:17:25 +0100
+
+pdns (1.99.6-1) experimental; urgency=low
+
+  * Upstream update
+
+ -- bert hubert <bert@powerdns.com>  Mon, 25 Mar 2002 23:17:25 +0100
+
+pdns (1.99.5-7) experimental; urgency=low
+
+  * Upstream update
+
+ -- bert hubert <bert@powerdns.com>  Mon, 25 Mar 2002 15:25:25 +0100
+
+pdns (1.99.5-6) experimental; urgency=low
+
+  * Upstream update
+
+ -- bert hubert <bert@powerdns.com>  Mon, 25 Mar 2002 15:25:25 +0100
+
+pdns (1.99.5-5) experimental; urgency=low
+
+  * Speedups in TCP code, now with timeouts
+
+ -- bert hubert <bert@powerdns.com>  Sun, 24 Mar 2002 21:53:55 +0100
+
+pdns (1.99.5-4) experimental; urgency=low
+
+  * fixed large memory leaks in TCP listener & AXFR code
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 20:49:55 +0100
+
+pdns (1.99.5-3) experimental; urgency=low
+
+  * wrong compiler chosen for backend :-(
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 20:49:55 +0100
+
+pdns (1.99.5-2) experimental; urgency=low
+
+  * wrong compiler chosen for backend :-(
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 20:49:55 +0100
+
+pdns (1.99.5-1) experimental; urgency=low
+
+  * zone2sql fixed
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 20:49:55 +0100
+
+pdns (1.99.4-4) experimental; urgency=low
+
+  * upstream released
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 20:49:55 +0100
+
+pdns (1.99.4-3) experimental; urgency=low
+
+  * Small upstream update
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 16:04:55 +0100
+
+pdns (1.99.4-2) experimental; urgency=low
+
+  * Small upstream update
+
+ -- bert hubert <bert@powerdns.com>  Thu, 22 Mar 2002 13:24:55 +0100
+
+pdns (1.99.4-1) experimental; urgency=low
+
+  * Small upstream update
+
+ -- bert hubert <bert@powerdns.com>  Thu, 21 Mar 2002 13:24:55 +0100
+
+pdns (1.99.3-4) experimental; urgency=low
+
+  * Small upstream update
+
+ -- bert hubert <bert@powerdns.com>  Wed, 20 Mar 2002 14:17:55 +0100
+
+pdns (1.99.3-4) experimental; urgency=low
+
+  * Did not include the libraries
+
+ -- bert hubert <bert@powerdns.com>  Wed, 20 Mar 2002 14:17:55 +0100
+
+pdns (1.99.3-3) experimental; urgency=low
+
+  * Accidentally compiled with gcc 3
+
+ -- bert hubert <bert@powerdns.com>  Wed, 20 Mar 2002 14:03:55 +0100
+
+pdns (1.99.3-2) experimental; urgency=low
+
+  * init.d script should be a configuration file
+
+ -- bert hubert <bert@powerdns.com>  Wed, 20 Mar 2002 13:20:55 +0100
+
+pdns (1.99.3-1) experimental; urgency=low
+
+  * new upstream version
+
+ -- bert hubert <bert@powerdns.com>  Wed, 20 Mar 2002 13:14:55 +0100
+
+pdns (1.99.2-4) experimental; urgency=low
+
+  * make install script add pdns user
+
+ -- bert hubert <bert@powerdns.com>  Wed, 15 Mar 2002 23:53:55 +0100
+
+pdns (1.99.2-3) experimental; urgency=low
+
+  * zone2sql fixes
+
+ -- bert hubert <bert@powerdns.com>  Wed, 15 Mar 2002 18:24:55 +0100
+
+pdns (1.99.2-2) experimental; urgency=low
+
+  * First release by ahu
+
+ -- bert hubert <bert@powerdns.com>  Wed, 14 Mar 2002 01:24:55 +0100
+
+pdns (1.99.2-1) experimental; urgency=low
+
+  * First release
+  * Remove bashism from pdns.in
+  * Handle already existing LD_LIBRARY_PATH in the installer (otherwise
+    fakeroot will break)
+  * Add force-reload to pdns.in
+  * Add download location to LICENSE so we don't need a seperate copyright
+    file
+
+ -- Wichert Akkerman <wichert@deephackmode.org>  Wed, 13 Mar 2002 23:57:55 +0100
diff --git a/pdns/debian/conffiles b/pdns/debian/conffiles
new file mode 100644 (file)
index 0000000..52ba056
--- /dev/null
@@ -0,0 +1,2 @@
+/etc/powerdns/pdns.conf
+/etc/init.d/pdns
diff --git a/pdns/debian/control b/pdns/debian/control
new file mode 100644 (file)
index 0000000..d31663b
--- /dev/null
@@ -0,0 +1,17 @@
+Source: pdns
+Section: net
+Priority: extra
+Build-Depends: libmysqlclient10-dev
+Maintainer: PowerTeam <debian@powerdns.com>
+Bugs: mailto:debian@powerdns.com
+Origin: powerdns
+Build-Depends: file, flex, bison, docbook-utils, openjade, jade
+
+Package: pdns
+Architecture: i386
+Depends: ${shlibs:Depends}
+Description: extremely powerful and versatile nameserver
+ PowerDNS is a versatile nameserver which supports a large number
+ of different backends ranging from simple zonefiles to relational
+ databases and load balancing/failover algorithms.
+
diff --git a/pdns/debian/postinst b/pdns/debian/postinst
new file mode 100644 (file)
index 0000000..79bf8cf
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" != "configure" ] ; then
+       exit 0
+fi
+
+update-rc.d pdns defaults > /dev/null
+
+if [ -n "$2" ] ; then
+       /etc/init.d/pdns restart
+else
+       /etc/init.d/pdns start
+fi
+
+exit 0
+
diff --git a/pdns/debian/postrm b/pdns/debian/postrm
new file mode 100644 (file)
index 0000000..63686d2
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "purge" ] ; then
+       update-rc.d pdns remove > /dev/null
+       userdel pdns
+fi
+
+# TODO: check if we need to remove files from /var/run
+
+exit 0
+
diff --git a/pdns/debian/preinst b/pdns/debian/preinst
new file mode 100644 (file)
index 0000000..c5e7510
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+id pdns > /dev/null 2> /dev/null
+if [ $? = 1 ]
+then
+       adduser --no-create-home --group --system pdns
+fi
diff --git a/pdns/debian/prerm b/pdns/debian/prerm
new file mode 100644 (file)
index 0000000..b1647cc
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "remove" ] ; then
+       /etc/init.d/pdns stop
+fi
+
+exit 0
+
diff --git a/pdns/debian/rules b/pdns/debian/rules
new file mode 100755 (executable)
index 0000000..01680cd
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/make -f
+
+clean:
+       rm -rf debian/tmp docs/html docs/pdns
+       rm -f debian/files debian/substvars
+       -make distclean
+
+build:
+       CXXFLAGS="-g -O2 -D_GNU_SOURCE" ./configure \
+               --prefix=/usr \
+               --mandir='$${prefix}'/share/man \
+               --libexecdir='$${prefix}'/lib \
+               --sysconfdir=/etc
+       
+       set -e ; cd docs ; db2html -o html pdns.sgml
+
+binary: binary-arch binary-indep
+
+binary-indep:
+       @echo No binary-independent packages
+
+binary-arch:
+       test `id -u` = 0
+       rm -rf debian/tmp
+       install -d -m 755 -o root -g root debian/tmp
+       chmod g-s debian/tmp
+       make DESTDIR=$(shell pwd)/debian/tmp install
+
+       install -d -m 755 -o root -g root debian/tmp/usr/share/doc/pdns/html
+       cp -p docs/html/* debian/tmp/usr/share/doc/pdns/html/
+
+       chmod -R g-w debian/tmp
+
+       rm -f debian/tmp/etc/*
+       install -d -m 755 -o root -g root debian/tmp/etc/powerdns
+       install -p -m 644 -o root -g root debian/pdns.conf \
+               debian/tmp/etc/powerdns/
+
+       -strip --strip-unneeded --remove-section=.comment \
+               --remove-section=.note \
+               debian/tmp/usr/sbin/* debian/tmp/usr/bin/*
+
+       install -d -m 755 -o root -g root debian/tmp/etc/init.d
+       install -p -m 755 -o root -g root debian/init.d \
+               debian/tmp/etc/init.d/pdns
+
+       install -d -m 755  -o root -g root debian/tmp/usr/share/doc/pdns
+       install -p -m 644 -o root -g root debian/changelog \
+               debian/tmp/usr/share/doc/pdns/changelog.Debian
+       gzip -9f debian/tmp/usr/share/doc/pdns/[^h]*
+       install -p -m 644 -o root -g root debian/copyright \
+               debian/tmp/usr/share/doc/pdns/
+       install -p -m 644 -o root -g root README \
+               debian/tmp/usr/share/doc/pdns/README
+
+       install -d -m 755 -o root -g root debian/tmp/DEBIAN
+       install -p -m 644 -o root -g root debian/conffiles debian/tmp/DEBIAN/
+       install -p -m 755 -o root -g root debian/preinst debian/tmp/DEBIAN/
+       install -p -m 755 -o root -g root debian/postinst debian/tmp/DEBIAN/
+       install -p -m 755 -o root -g root debian/postrm debian/tmp/DEBIAN/
+       install -p -m 755 -o root -g root debian/prerm debian/tmp/DEBIAN/
+
+       dpkg-shlibdeps debian/tmp/usr/sbin/* debian/tmp/usr/bin/[^p]*
+       dpkg-gencontrol -isp
+       dpkg --build debian/tmp ..
+
+
+.PHONY: clean build binary binary-arch binary-indep
+
diff --git a/pdns/depcomp b/pdns/depcomp
new file mode 100755 (executable)
index 0000000..6589965
--- /dev/null
@@ -0,0 +1,411 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+
+# This program 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, 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# 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 Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  This file always lives in the current directory.
+  # Also, the AIX compiler puts `$object:' at the start of each line;
+  # $object doesn't have directory information.
+  stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  outname="$stripped.o"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+tru64)
+   # The Tru64 AIX compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+
+   tmpdepfile1="$object.d"
+   tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` 
+   if test "$libtool" = yes; then
+      "$@" -Wc,-MD
+   else
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2"
+      exit $stat
+   fi
+
+   if test -f "$tmpdepfile1"; then
+      tmpdepfile="$tmpdepfile1"
+   else
+      tmpdepfile="$tmpdepfile2"
+   fi
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a space and a tab in the [].
+      sed -e 's,^.*\.[a-z]*:[  ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  test -z "$dashmflag" && dashmflag=-M
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*) # this is libtool, let us make it quiet
+      for arg
+      do # cycle over the arguments
+        case "$arg" in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" $dashmflag | sed 's:^[^:]*\:[         ]*:'"$object"'\: :' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  # X makedepend
+  (
+    shift
+    cleared=no
+    for arg in "$@"; do
+      case $cleared in no)
+        set ""; shift
+       cleared=yes
+      esac
+      case "$arg" in
+        -D*|-I*)
+         set fnord "$@" "$arg"; shift;;
+       -*)
+         ;;
+       *)
+         set fnord "$@" "$arg"; shift;;
+      esac
+    done
+    obj_suffix="`echo $object | sed 's/^.*\././'`"
+    touch "$tmpdepfile"
+    ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tail +3 "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::   \1 \\:p' >> "$depfile"
+  echo "       " >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
diff --git a/pdns/distributor.hh b/pdns/distributor.hh
new file mode 100644 (file)
index 0000000..5b68020
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+\r
+#ifndef DISTRIBUTOR_HH\r
+#define DISTRIBUTOR_HH\r
+\r
+\r
+#include <string>
+#include <deque>
+#include <queue>
+#include <vector>
+#include <pthread.h>
+#include <semaphore.h>\r
+\r
+#ifndef WIN32
+# include <unistd.h>\r
+#endif // WIN32\r
+
+#include "logger.hh"
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "ahuexception.hh"
+
+
+/** the Distributor template class enables you to multithread slow question/answer 
+    processes. 
+    
+    Generally, you will run 2 threads. One that inserts questions and one that handles
+    the answers.
+*/
+
+
+template<class Answer, class Question, class Backend> class Distributor
+{
+public:
+  Distributor(int n=10); //!< Create a new Distributor with \param n threads
+  struct AnswerData
+  {
+    Answer *A;
+    time_t created;
+  };  
+  int question(Question *, void (*)(const AnswerData &)=0); //!< Submit a question to the Distributor
+  Answer *answer(void); //!< Wait for any answer from the Distributor
+  Answer *wait(Question *); //!< wait for an answer to a specific question
+  int timeoutWait(int id, Answer *, int); //!< wait for a specific answer, with timeout
+  static void* makeThread(void *); //!< helper function to create our n threads
+  void getQueueSizes(int &questions, int &answers); //!< Returns length of question queue
+
+
+  //! This function can run in a separate thread to output statistics on the queues
+  static void* doStats(void *p)
+  {
+    Distributor *us=static_cast<Distributor *>(p);
+    for(;;)
+      {
+       sleep(1);
+       int qcount, acount;
+
+  us->numquestions.getvalue( &qcount );\r
+  us->numanswers.getvalue( &acount );\r
+
+       L <<"queued questions: "<<qcount<<", pending answers: "<<acount<<endl;
+      }
+  }
+
+  int getNumBusy()
+  {
+    return d_num_threads-d_idle_threads;
+  }
+
+
+
+
+  struct QuestionData
+  {
+    Question *Q;
+    time_t created;
+    void (*callback)(const AnswerData &);
+    int id;
+  };
+
+
+  typedef pair<QuestionData, AnswerData> tuple_t;
+  
+private:
+  queue<QuestionData> questions;
+  pthread_mutex_t q_lock;
+
+  
+  deque<tuple_t> answers;
+  pthread_mutex_t a_lock;
+
+  Semaphore numquestions;
+  Semaphore numanswers;
+
+  pthread_mutex_t to_mut;
+  pthread_cond_t to_cond;
+
+  int nextid;
+  time_t d_last_started;
+  int d_num_threads;
+  int d_idle_threads;
+  Backend *b;
+};
+
+
+//template<class Answer, class Question, class Backend>::nextid;
+
+template<class Answer, class Question, class Backend>Distributor<Answer,Question,Backend>::Distributor(int n)
+{
+  b=0;
+  d_idle_threads=0;
+  d_last_started=time(0);
+//  sem_init(&numquestions,0,0);
+  pthread_mutex_init(&q_lock,0);
+
+//  sem_init(&numanswers,0,0);
+  pthread_mutex_init(&a_lock,0);
+
+  pthread_mutex_init(&to_mut,0);
+  pthread_cond_init(&to_cond,0);
+
+  pthread_t tid;
+  
+  d_num_threads=n;
+
+  L<<Logger::Warning<<"About to create "<<n<<" backend threads"<<endl;
+
+  for(int i=0;i<n;i++) {
+    pthread_create(&tid,0,&makeThread,static_cast<void *>(this));
+    Utility::usleep(50000); // we've overloaded mysql in the past :-)
+  }
+
+  L<<"Done launching threads, ready to distribute questions"<<endl;
+}
+
+// start of a new thread
+template<class Answer, class Question, class Backend>void *Distributor<Answer,Question,Backend>::makeThread(void *p)
+{
+  try {
+    Backend *b=new Backend(); // this will answer our questions
+    Distributor *us=static_cast<Distributor *>(p);
+    int qcount;
+
+    // this is so gross
+#ifndef SMTPREDIR 
+    int queuetimeout=arg().asNum("queue-limit"); 
+#endif 
+    // ick ick ick!
+
+    for(;;) {
+      us->d_idle_threads++;
+\r
+      us->numquestions.getValue( &qcount );
+
+      us->numquestions.wait();\r
+
+      us->d_idle_threads--;
+      pthread_mutex_lock(&us->q_lock);
+
+      QuestionData QD=us->questions.front();
+
+      Question *q=QD.Q;
+      
+      us->questions.pop();
+      
+      pthread_mutex_unlock(&us->q_lock);
+      Answer *a;      
+
+
+#ifndef SMTPREDIR
+      if(queuetimeout && q->d_dt.udiff()>queuetimeout*1000) {
+        delete q;
+        S.inc("timedout-packets");
+        continue;
+      }        
+#endif  
+      // this is the only point where we interact with the backend (synchronous)
+      try {
+        a=b->question(q); // a can be NULL!
+        delete q;
+      }
+      catch(const AhuException &e) {
+        L<<Logger::Error<<"Backend error: "<<e.reason<<endl;
+       delete b;
+        return 0;
+      }
+      catch(...) {
+        L<<Logger::Error<<Logger::NTLog<<"Caught unknown exception in Distributor thread "<<(unsigned long)pthread_self()<<endl;
+       delete b;
+        return 0;
+      }
+
+      AnswerData AD;
+      AD.A=a;
+      AD.created=time(0);
+      tuple_t tuple(QD,AD);
+
+      if(QD.callback) {
+       QD.callback(AD);
+      }
+      else {
+       pthread_mutex_lock(&us->a_lock);
+
+       us->answers.push_back(tuple);
+       pthread_mutex_unlock(&us->a_lock);
+      
+       //        L<<"We have an answer to send! Trying to get to to_mut lock"<<endl;
+       pthread_mutex_lock(&us->to_mut); 
+       // L<<"Yes, we got the lock, we can transmit! First we post"<<endl;
+       us->numanswers.post();
+       // L<<"And now we broadcast!"<<endl;
+       pthread_cond_broadcast(&us->to_cond); // for timeoutWait(); 
+       pthread_mutex_unlock(&us->to_mut);
+      }
+    }
+    
+    delete b;
+  }
+  catch(const AhuException &AE) {
+    L<<Logger::Error<<Logger::NTLog<<"Distributor caught fatal exception: "<<AE.reason<<endl;
+  }
+  catch(...) {
+    L<<Logger::Error<<Logger::NTLog<<"Caught an unknown exception when creating backend, probably"<<endl;
+  }
+  return 0;
+}
+
+template<class Answer, class Question, class Backend>int Distributor<Answer,Question,Backend>::question(Question* q, void (*callback)(const AnswerData &))
+{
+  if(d_num_threads==1 && callback) {  // short circuit
+    if(!b) {
+      L<<Logger::Error<<"Engaging bypass - now operating unthreaded"<<endl;
+      b=new Backend;
+    }
+    Answer *a;
+
+    a=b->question(q);
+
+    AnswerData AD;
+    AD.A=a;
+    AD.created=time(0);
+    callback(AD); 
+    return 0;
+  }
+  else {
+    q=new Question(*q);
+  }
+
+  DLOG(L<<"Distributor has "<<Backend::numRunning()<<" threads available"<<endl);
+  if(Backend::numRunning()<d_num_threads && time(0)-d_last_started>5) { // add one
+    d_last_started=time(0);
+    L<<"Distributor misses a thread ("<<Backend::numRunning()<<"<"<<d_num_threads<<"), spawning new one"<<endl;
+    pthread_t tid;
+    pthread_create(&tid,0,&makeThread,static_cast<void *>(this));
+  }
+
+  pthread_mutex_lock(&q_lock);
+  QuestionData QD;
+  QD.Q=q;
+  QD.id=nextid++;
+  QD.callback=callback;
+  questions.push(QD);
+  pthread_mutex_unlock(&q_lock);
+\r
+  numquestions.post();
+\r
+  if(!(nextid%50)) {
+    int val;
+    numquestions.getValue( &val );
+    if(val>arg().asNum("max-queue-length")) {
+      L<<Logger::Error<<val<<" questions waiting for database attention. Limit is "<<arg().asNum("max-queue-length")<<", respawning"<<endl;
+      exit(1);
+    }
+  }\r
+
+  return QD.id;
+}
+
+template<class Answer, class Question,class Backend>Answer* Distributor<Answer,Question,Backend>::answer()
+{
+  numanswers.wait();
+  tuple_t tuple;
+
+  pthread_mutex_lock(&a_lock);
+  tuple=answers.front();
+  answers.pop_front();
+  pthread_mutex_unlock(&a_lock);
+  return tuple.second.A;
+}
+
+//! Wait synchronously for the answer of the question just asked. For this to work, no answer() functions must be called
+template<class Answer, class Question,class Backend>Answer* Distributor<Answer,Question,Backend>::wait(Question *q)
+{
+  for(;;)
+    {
+      numanswers.wait();
+      pthread_mutex_lock(&a_lock);
+      
+      // search if the answer is there
+      tuple_t tuple=answers.front();
+      if(tuple.first==q)
+       {
+         answers.pop_front();
+         pthread_mutex_unlock(&a_lock);
+         return tuple.second.A;
+       }
+      // if not, loop again
+      pthread_mutex_unlock(&a_lock);
+      numanswers.post();
+    }
+  // FIXME: write this
+}
+
+template<class Answer, class Question,class Backend>void Distributor<Answer,Question,Backend>::getQueueSizes(int &questions, int &answers)
+{\r
+  numquestions.getValue( &questions );\r
+  numanswers.getValue( &answers );
+}
+
+//! Wait synchronously for the answer of the question just asked. For this to work, no answer() functions must be called
+template<class Answer, class Question,class Backend>int Distributor<Answer,Question,Backend>::timeoutWait(int id, Answer *a, int timeout)
+{
+  struct timeval now;
+  struct timespec then;
+
+  Utility::gettimeofday(&now,0);
+
+  then.tv_sec=now.tv_sec+timeout;  
+  then.tv_nsec=150*1000000+now.tv_usec*1000; // 150ms
+
+  int rc;
+
+  //  L<<"About to acquire to_mut - new broadcasts will then be corked"<<endl;
+  pthread_mutex_lock(&to_mut);  // start the lock to prevent races
+
+  for(;;)
+    {
+      //      L<<"Acquired the to_mut lock - checking to see if there are already answers"<<endl;
+
+      int val;
+      rc=numanswers.getvalue( &val); // are there answers?
+      //      L<<"Now "<<val<<" answers according to the semaphore"<<endl;
+
+      if(val)
+       {
+         DLOG(L<<"There are some answers! Is the one we want among them?"<<endl);
+         DLOG(L<<"numanswers: "<<val<<", rc="<<rc<<", errno="<<errno<<endl);
+
+         pthread_mutex_lock(&a_lock);
+         
+         DLOG(L<<"deque contains: "<<answers.size()<<endl);
+         // search if the answer is there
+         
+         bool found=false;
+         int rc;
+         
+         for(typename deque<tuple_t>::iterator tuple=answers.begin();
+             tuple!=answers.end();
+             tuple++)
+           {
+             if(!found && tuple->first.id==id)
+               {
+                 numanswers.wait(); // remove from the semaphore
+                 DLOG(L<<"found the answer tuple ("<<tuple->first.id<<") - may be empty answer"<<endl);
+                 
+                 found=true;
+                 
+                 if(!tuple->second.A)
+                   rc=-1;
+                 else
+                   {
+                     *a=*tuple->second.A;
+                     rc=0;
+                   }
+                 
+                 answers.erase(tuple);
+                 tuple=answers.begin(); // restart
+                 if(tuple==answers.end())break;
+                 
+               }
+             else  // an answer, but not the right one
+               {
+                 if(time(0)-tuple->second.created>5) // delete after 5 seconds
+                   {
+                     L<<"Deleted unclaimed answer "<<tuple->first.id<<" due to age"<<endl;
+                     answers.erase(tuple);
+                     tuple=answers.begin(); // restart
+                     if(tuple==answers.end())break;
+                     numanswers.wait();
+                   }
+               }
+           }
+         pthread_mutex_unlock(&a_lock);
+
+         if(!found)
+           L<<"Right answer was NOT found - we should now sleep and recheck whenever there are new answers"<<endl;
+         else 
+           {
+             pthread_mutex_unlock(&to_mut);
+             return 0;
+           }
+       }
+      else
+       L<<"No answers!"<<endl;
+
+
+      DLOG(L<<"starting wait on condition, to see if there are new answers"<<endl);
+
+      // this first lets go of the to_mut lock, which will 'uncork' the pending pthread_cond_broadcasts
+      rc=pthread_cond_timedwait(&to_cond, &to_mut, &then);
+      // and then it atomically reacquires the lock
+
+      if(rc==ETIMEDOUT)
+       {
+         L<<Logger::Error<<"Timeout waiting for data"<<endl;
+         pthread_mutex_unlock(&to_mut);
+         return -ETIMEDOUT;
+       }
+      L<<"We received a broadcast that there is new data, checking"<<endl;
+
+    }
+
+  return -1; // timeout or whatever
+  // FIXME: write this
+}
+
+\r
+#endif // DISTRIBUTOR_HH\r
+
diff --git a/pdns/dns.hh b/pdns/dns.hh
new file mode 100644 (file)
index 0000000..132a069
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: dns.hh,v 1.1 2002/11/27 15:18:31 ahu Exp $ 
+/* (C) 2002 POWERDNS.COM BV */
+#ifndef DNS_HH
+#define DNS_HH
+\r
+#include "utility.hh"
+#include "qtype.hh"
+#include <time.h>
+#include <sys/types.h>
+class DNSBackend;
+
+struct SOAData
+{
+  string qname;
+  string nameserver;
+  string hostmaster;
+  u_int32_t ttl;
+  u_int32_t serial;
+  u_int32_t refresh;
+  u_int32_t retry;
+  u_int32_t expire;
+  u_int32_t default_ttl;
+  int domain_id;
+  DNSBackend *db;
+};
+
+
+class RCode
+{
+public:
+  enum { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5 };
+};
+
+class Opcode
+{
+public:
+  enum { Query=0, IQuery=1, Status=2, Notify=4, Update=5 };
+};
+
+
+//! This class represents a resource record
+class DNSResourceRecord
+{
+public:
+  DNSResourceRecord() : d_place(ANSWER){};
+  ~DNSResourceRecord(){};
+
+  string serialize() const;
+  int unSerialize(const string &str);
+
+  // data
+  
+  QType qtype; //!< qtype of this record, ie A, CNAME, MX etc
+  string qname; //!< the name of this record, for example: www.powerdns.com
+  string content; //!< what this record points to. Example: 10.1.2.3
+  u_int16_t priority; //!< For qtype's that support a priority or preference. Currently only MX
+  u_int32_t ttl; //!< Time To Live of this record
+  int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in
+  time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in
+  enum Place {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning of a DNSResourceRecord within, say, a DNSPacket
+  Place d_place; //!< This specifies where a record goes within the packet
+
+private:
+  string escape(const string &str) const;
+};
+
+#define L theL()
+extern time_t s_starttime;
+
+#endif
diff --git a/pdns/dnsbackend.cc b/pdns/dnsbackend.cc
new file mode 100644 (file)
index 0000000..d9e5375
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "dnsbackend.hh"
+#include "arguments.hh"
+#include "ueberbackend.hh"
+#include "logger.hh"
+
+#include <sys/types.h>
+#include "dnspacket.hh"
+
+string DNSResourceRecord::serialize() const
+{
+  ostringstream ostr;
+  ostr<<escape(qname)<<"|"<<qtype.getName()<<"|"<<escape(content)<<"|"<<ttl<<"|"<<priority<<"|"<<domain_id
+     <<"|"<<last_modified;
+  return ostr.str();
+}
+
+string DNSResourceRecord::escape(const string &name) const
+{
+  string a;
+
+  for(string::const_iterator i=name.begin();i!=name.end();++i)
+    if(*i=='|' || *i=='\\'){
+      a+='\\';
+      a+=*i;
+    }
+    else
+      a+=*i;
+
+  return a;
+}
+
+int DNSResourceRecord::unSerialize(const string &source)
+{
+  // qname|qtype|content|ttl|priority|domain_id|last_modified;
+  string chunk;
+  unsigned int m=0;
+  for(int n=0;n<7;++n) {
+    chunk="";
+    for(;m<source.size();++m) {
+      if(source[m]=='\\' && m+1<source.size()) 
+       chunk.append(1,source[++m]);
+      else if(source[m]=='|') {
+       ++m;
+       break;
+      }
+      else 
+       chunk.append(1,source[m]);
+    }
+    switch(n) {
+    case 0:
+      qname=chunk;
+      break;
+    case 1:
+      qtype=chunk;
+      break;
+    case 2:
+      content=chunk;
+      break;
+    case 3:
+      ttl=atoi(chunk.c_str());
+      break;
+    case 4:
+      priority=atoi(chunk.c_str());
+      break;
+    case 5:
+      domain_id=atoi(chunk.c_str());
+      break;
+    case 6:
+      last_modified=atoi(chunk.c_str());
+      break;
+    }
+  }
+  return m;
+}
+
+string DNSBackend::getRemote(DNSPacket *p)
+{
+  return p->getRemote();
+}
+
+bool DNSBackend::getRemote(DNSPacket *p, struct sockaddr *sa, Utility::socklen_t *len)
+{
+  if(p->d_socklen<*len)
+    return false;
+  *len=p->d_socklen;
+  memcpy(sa,&p->remote,*len);
+  return true;
+}
+
+
+
+void DNSBackend::setArgPrefix(const string &prefix)
+{
+  d_prefix=prefix;
+}
+
+bool DNSBackend::mustDo(const string &key)
+{
+  return arg().mustDo(d_prefix+"-"+key);
+}
+
+const string &DNSBackend::getArg(const string &key)
+{
+  return arg()[d_prefix+"-"+key];
+}
+
+int DNSBackend::getArgAsNum(const string &key)
+{
+  return arg().asNum(d_prefix+"-"+key);
+}
+
+void BackendFactory::declare(const string &suffix, const string &param, const string &help, const string &value)
+{
+  string fullname=d_name+"-"+suffix+param;
+  arg().set(fullname,help)=value;
+}
+
+const string &BackendFactory::getName() const
+{
+  return d_name;
+}
+
+BackendMakerClass &BackendMakers()
+{
+  static BackendMakerClass bmc;
+  return bmc;
+}
+
+void BackendMakerClass::report(BackendFactory *bf)
+{
+  d_repository[bf->getName()]=bf;
+}
+
+
+vector<string> BackendMakerClass::getModules() 
+{
+  load_all();
+  vector<string> ret;
+  //  copy(d_repository.begin(), d_repository.end(),back_inserter(ret));
+  for(d_repository_t::const_iterator i=d_repository.begin();i!=d_repository.end();++i)
+    ret.push_back(i->first);
+  return ret;
+}
+
+void BackendMakerClass::load_all()
+{\r
+  // TODO: Implement this?\r
+#ifndef WIN32
+  DIR *dir=opendir(arg()["module-dir"].c_str());
+  if(!dir) {
+    L<<Logger::Error<<"Unable to open module directory '"<<arg()["module-dir"]<<"'"<<endl;
+    return;
+  }
+  struct dirent *entry;
+  while((entry=readdir(dir))) {
+    if(!strncmp(entry->d_name,"lib",3) && 
+       entry->d_name[strlen(entry->d_name)-1]=='o' && 
+       entry->d_name[strlen(entry->d_name)-2]=='s' &&
+       entry->d_name[strlen(entry->d_name)-3]=='.')
+      load(entry->d_name);
+  }
+  closedir(dir);\r
+#endif // WIN32
+}
+
+void BackendMakerClass::load(const string &module)
+{
+  int res;
+
+  if(module.find(".")==string::npos)
+    res=UeberBackend::loadmodule(arg()["module-dir"]+"/lib"+module+"backend.so");
+  else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.'))    // absolute or current path
+    res=UeberBackend::loadmodule(module);
+  else
+    res=UeberBackend::loadmodule(arg()["module-dir"]+"/"+module);
+  
+  if(res==false) {
+    L<<Logger::Error<<"Unable to load module "<<module<<endl;
+    exit(1);
+  }
+}
+
+void BackendMakerClass::launch(const string &instr)
+{
+  //    if(instr.empty())
+  // throw ArgException("Not launching any backends - nameserver won't function");
+  
+  vector<string> parts;
+  stringtok(parts,instr,", ");
+  
+  for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
+    const string &part=*i;
+    
+    string module, name;
+    vector<string>pparts;
+    stringtok(pparts,part,": ");
+    module=pparts[0];
+    if(pparts.size()>1)
+      name=pparts[1]+"-";
+      
+    if(d_repository.find(module)==d_repository.end()) {
+      // this is *so* userfriendly
+      load(module);
+      if(d_repository.find(module)==d_repository.end())
+       throw ArgException("Trying to launch unknown backend '"+module+"'");
+    }
+    
+    d_repository[module]->declareArguments(name);
+    d_instances.push_back(make_pair(module,name));
+  }
+}
+
+int BackendMakerClass::numLauncheable()
+{
+  return d_instances.size();
+}
+
+vector<DNSBackend *>BackendMakerClass::all()
+{
+  vector<DNSBackend *>ret;
+  if(d_instances.empty())
+    throw AhuException("No database backends configured for launch, unable to function");
+
+  try {
+    for(vector<pair<string,string> >::const_iterator i=d_instances.begin();i!=d_instances.end();++i) {
+      DNSBackend *made=d_repository[i->first]->make(i->second);
+      if(!made)
+       throw AhuException("Unable to launch backend '"+i->first+"'");
+
+      ret.push_back(made);
+    }
+  }
+  catch(...) {
+    // and cleanup
+    for(vector<DNSBackend *>::const_iterator i=ret.begin();i!=ret.end();++i)
+      delete *i;
+    throw;
+  }
+  
+  return ret;
+}
+
+bool DNSBackend::getSOA(const string &domain, SOAData &sd)
+{
+  this->lookup(QType(QType::SOA),domain,0);
+  
+  DNSResourceRecord rr;
+
+  int hits=0;
+
+  while(this->get(rr)) {
+    hits++;
+    DNSPacket::fillSOAData(rr.content, sd);
+    sd.domain_id=rr.domain_id;
+    sd.ttl=rr.ttl;
+  }
+  
+  if(!hits)
+    return false;
+
+  if(sd.nameserver.empty())
+    sd.nameserver=arg()["default-soa-name"];
+  
+  if(sd.hostmaster.empty())
+    sd.hostmaster="hostmaster."+domain;
+
+  if(!sd.serial) { // magic time!
+    DLOG(L<<Logger::Warning<<"Doing soa serialnumber autocalculation for "<<rr.qname<<endl);
+
+    // we do this by listing the domain and taking the maximum last modified timestamp
+
+    DNSResourceRecord i;
+    time_t newest=0;
+
+    if(!(this->list(sd.domain_id))) 
+      throw AhuException("Backend error trying to determine magic serial number of zone '"+domain+"'");
+  
+    while(this->get(i)) {
+      if(i.last_modified>newest)
+       newest=i.last_modified;
+    }
+
+    sd.serial=newest;
+    DLOG(L<<"autocalculated soa serialnumber for "<<rr.qname<<" is "<<newest<<endl);
+
+  }
+  sd.db=this;
+  return true;
+}
+
diff --git a/pdns/dnsbackend.hh b/pdns/dnsbackend.hh
new file mode 100644 (file)
index 0000000..b859da2
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: dnsbackend.hh,v 1.1 2002/11/27 15:18:32 ahu Exp $
+/* (C) 2002 POWERDNS.COM BV  */
+   
+#ifndef DNSBACKEND_HH
+#define DNSBACKEND_HH
+
+class DNSPacket;\r
+\r
+#include "utility.hh"
+#include <string>
+#include <vector>
+#include <map>
+#include <sys/types.h>
+#include <set>\r
+\r
+#ifndef WIN32\r
+# include <sys/socket.h>\r
+# include <dirent.h>\r
+#endif // WIN32\r
+
+#include "qtype.hh"
+#include "dns.hh"
+using namespace std;
+
+/** This virtual base class defines the interface for backends for the ahudns. To create a backend,
+    inherit from this class and implement functions for all virtual methods.
+*/
+  
+class DNSBackend;  
+struct DomainInfo
+{
+  u_int32_t id;
+  string zone;
+  string master;
+  u_int32_t serial;
+  u_int32_t notified_serial;
+  time_t last_check;
+  enum {Master,Slave,Native} kind;
+  DNSBackend *backend;
+};
+
+class DNSPacket;
+class DNSBackend
+{
+public:
+  virtual void lookup(const QType &qtype, const string &qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0; 
+  virtual bool get(DNSResourceRecord &)=0;
+  virtual bool list(int domain_id)=0; 
+
+  virtual ~DNSBackend(){};
+
+  static void reconfigure(const string &);
+
+  virtual bool getSOA(const string &name, SOAData &soadata);
+
+  virtual bool isMaster(const string &name, const string &ip)
+  {
+    return false;
+  }
+  
+  virtual bool startTransaction(const string &qname, int id=-1)
+  {
+    return false;
+  }
+
+  virtual bool commitTransaction()
+  {
+    return false;
+  }
+
+  virtual bool abortTransaction()
+  {
+    return false;
+  }
+
+  virtual void reload()
+  {
+  }
+
+  virtual void rediscover()
+  {
+  }
+
+  virtual bool feedRecord(const DNSResourceRecord &rr)
+  {
+    return false; // no problem!
+  }
+  virtual bool getDomainInfo(const string &domain, DomainInfo &di)
+  {
+    return false;
+  }
+  virtual void getUnfreshSlaveInfos(vector<DomainInfo>* domains)
+  {
+  }
+
+  virtual void alsoNotifies(const string &domain, set<string> *ips)
+  {
+  }
+  virtual void getUpdatedMasters(vector<DomainInfo>* domains)
+  {
+  }
+  virtual DNSBackend *getBackendAndID(const string &qdomain, u_int32_t *id)
+  {
+    return 0;
+  }
+  virtual void setFresh(u_int32_t domain_id)
+  {
+
+  }
+  virtual void setNotified(u_int32_t id, u_int32_t serial)
+  {
+  }
+
+  void setArgPrefix(const string &prefix);
+  virtual bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
+  {
+    return false;
+  }
+  virtual bool createSlaveDomain(const string &ip, const string &domain, const string &account)
+  {
+    return false;
+  }
+
+protected:
+  bool mustDo(const string &key);
+  const string &getArg(const string &key);
+  int getArgAsNum(const string &key);
+  string getRemote(DNSPacket *p);
+  bool getRemote(DNSPacket *p, struct sockaddr *in, Utility::socklen_t *len);
+
+private:
+  string d_prefix;
+};
+
+class BackendFactory
+{
+public:
+  BackendFactory(const string &name) : d_name(name) {}
+  virtual ~BackendFactory(){}
+  virtual DNSBackend *make(const string &suffix)=0;
+  virtual void declareArguments(const string &suffix=""){}
+  const string &getName() const;
+  
+protected:
+  void declare(const string &suffix, const string &param, const string &explanation, const string &value);
+
+private:
+  const string d_name;
+};
+
+class BackendMakerClass
+{
+public:
+  void report(BackendFactory *bf);
+  void launch(const string &instr);
+  vector<DNSBackend *>all();
+  void load(const string &module);
+  int numLauncheable();
+  vector<string> getModules();
+
+private:
+  void load_all();
+  typedef map<string,BackendFactory *>d_repository_t;
+  d_repository_t d_repository;
+  vector<pair<string,string> >d_instances;
+};
+
+extern BackendMakerClass &BackendMakers();
+
+class BackendException
+{};
+
+#endif
diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc
new file mode 100644 (file)
index 0000000..d28548e
--- /dev/null
@@ -0,0 +1,1461 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: dnspacket.cc,v 1.1 2002/11/27 15:18:31 ahu Exp $
+#include "utility.hh"
+#include <cstdio>
+
+#include <cstdlib>
+#include <sys/types.h>
+
+#include <iostream>  
+
+#include <string>
+#include <errno.h>
+
+#include <algorithm>
+
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "ahuexception.hh"
+#include "dnspacket.hh"
+#include "logger.hh"
+#include "arguments.hh"
+
+
+DNSPacket::DNSPacket() 
+{
+  d_wrapped=false;
+  d_compress=true;
+}
+
+
+string DNSPacket::getString()
+{
+  return stringbuffer;
+}
+
+
+string DNSPacket::getRemote() const
+{
+  return sockAddrToString((struct sockaddr_in *)remote, d_socklen);
+}
+
+
+
+// Make s lowercase:
+void lowercase(string& s) {
+  for(unsigned int i = 0; i < s.length(); i++)
+    s[i] = tolower(s[i]);
+}
+
+void DNSPacket::trim()
+{
+  rrs.clear();
+  qdomain=""; // .clear();
+  string(stringbuffer).swap(stringbuffer); // kudos Scott
+}
+
+DNSPacket::DNSPacket(const DNSPacket &orig)
+{
+  DLOG(L<<"DNSPacket copy constructor called!"<<endl);
+  d_socket=orig.d_socket;
+  memcpy(remote, orig.remote, sizeof(remote));
+  len=orig.len;
+  d_qlen=orig.d_qlen;
+  d_dt=orig.d_dt;
+  d_socklen=orig.d_socklen;
+  d_compress=orig.d_compress;
+  qtype=orig.qtype;
+  qclass=orig.qclass;
+  qdomain=orig.qdomain;
+
+  rrs=orig.rrs;
+
+  d_wrapped=orig.d_wrapped;
+
+  stringbuffer=orig.stringbuffer;
+  d=orig.d;
+
+}
+
+int DNSPacket::expand(const char *begin, const char *end, string &expanded, int depth)
+{
+  if(depth>10)
+    throw AhuException("Looping label when parsing a packet");
+
+  unsigned int n;
+  const char *p=begin;
+
+  while((n=*(unsigned char *)p++)) {
+    char tmp[256];
+      if((n & 0xc0) == 0xc0 ) { 
+       unsigned int labelOffset=(n&~0xc0)*256+ (int)*(unsigned char *)p;
+       expand(stringbuffer.c_str()+labelOffset,end,expanded,depth++);
+       return 1+p-begin;
+      }
+
+      if(p+n>=end) { // this is a bogus packet, references beyond the end of the buffer
+       throw AhuException("Label claims to be longer than packet");
+      }
+      strncpy(tmp,p,n);
+
+      if(*(p+n)) { // add a ., except at the end
+         tmp[n]='.';
+         tmp[n+1]=0;
+      }
+      else
+       tmp[n]=0;
+
+      expanded+=tmp;
+
+      p+=n;
+    }
+    
+  // lowercase(qdomain); (why was this?)
+
+  return p-begin;
+
+}
+
+/** copies the question into our class
+ *  and returns offset of question type & class. Returns -1 in case of an error
+ */
+int DNSPacket::getq()
+{
+  const char *orig=stringbuffer.c_str()+12;
+  const char *end=orig+(stringbuffer.length()-12);
+  qdomain="";
+  try {
+    return expand(orig,end,qdomain);
+  }
+  catch(AhuException &ae) {
+    L<<Logger::Error<<"On retrieving question of packet, encountered error: "<<ae.reason<<endl;
+  }
+  return -1;
+}
+
+/*
+                                    1  1  1  1  1  1
+      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                      ID                       |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    QDCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    ANCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    NSCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    ARCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+*/
+
+void DNSPacket::setRcode(int v)
+{
+  d.rcode=v;
+}
+
+void DNSPacket::setAnswer(bool b)
+{
+  if(b) {
+    stringbuffer.assign(12,(char)0);
+    memset((void *)&d,0,sizeof(d));
+    
+    d.qr=b;
+  }
+}
+
+void DNSPacket::setA(bool b)
+{
+  d.aa=b;
+}
+
+void DNSPacket::setID(u_int16_t id)
+{
+  d.id=id;
+}
+
+void DNSPacket::setRA(bool b)
+{
+  d.ra=b;
+}
+
+void DNSPacket::setRD(bool b)
+{
+  d.rd=b;
+}
+
+
+void DNSPacket::setOpcode(u_int16_t opcode)
+{
+  d.opcode=opcode;
+}
+
+const char *DNSPacket::getRaw(void)
+{
+  return stringbuffer.data();
+}
+
+void DNSPacket::setRaw(char *mesg, int length)
+{
+  stringbuffer.assign(mesg,length); 
+}
+
+void DNSPacket::addARecord(const DNSResourceRecord &rr)
+{
+  DLOG(L<<"Adding an A record to the packet!"<<endl);
+  addARecord(rr.qname, htonl(inet_addr(rr.content.c_str())), rr.ttl, rr.d_place);
+}
+
+void DNSPacket::addRecord(const DNSResourceRecord &rr)
+{
+  if(d_compress)
+    for(vector<DNSResourceRecord>::const_iterator i=rrs.begin();i!=rrs.end();++i) 
+      if(rr.qname==i->qname && rr.qtype==i->qtype && rr.content==i->content)
+       return;
+
+  rrs.push_back(rr);
+}
+
+void DNSPacket::addARecord(const string &name, u_int32_t ip, u_int32_t ttl, DNSResourceRecord::Place place)
+{
+  string piece1;
+  toqname(name, &piece1);
+
+  char p[14];
+
+  p[0]=0;  
+  p[1]=1; // A
+  p[2]=0;
+  p[3]=1; // IN
+
+  u_int32_t *ttlp=(u_int32_t *)(p+4);
+
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+  p[8]=0;
+  p[9]=4; // length of data
+
+  p[10]=(ip>>24)&0xff;
+  p[11]=(ip>>16)&0xff;
+  p[12]=(ip>>8)&0xff;
+  p[13]=ip&0xff;
+  
+  stringbuffer.append(piece1);
+  stringbuffer.append(p,14);
+
+  if(place==DNSResourceRecord::ADDITIONAL)
+    d.arcount++;
+  else
+    d.ancount++;
+}
+
+void DNSPacket::addAAAARecord(const DNSResourceRecord &rr)
+{
+  DLOG(L<<"Adding an AAAA record to the packet!"<<endl);
+  unsigned char addr[16];
+
+  if( Utility::inet_pton( AF_INET6, rr.content.c_str(), static_cast< void * >( addr )))
+    addAAAARecord(rr.qname, addr, rr.ttl);
+  else
+    L<<Logger::Error<<"Unable to convert IPv6 TEXT '"<<rr.content<<"' into binary for record '"<<rr.qname<<"': "
+     <<endl;
+}
+
+
+
+void DNSPacket::addAAAARecord(const string &name, unsigned char addr[16], u_int32_t ttl)
+{
+  string piece1;
+  toqname(name.c_str(),&piece1);
+
+  char p[26];
+
+  p[0]=0;  
+  p[1]=28; // AAAA
+  p[2]=0;
+  p[3]=1; // IN
+
+  u_int32_t *ttlp=(u_int32_t *)(p+4);
+
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+  p[8]=0;
+  p[9]=16; // length of data
+
+  for(int n=0;n<16;n++)
+    p[10+n]=addr[n];
+
+  stringbuffer.append(piece1);
+  stringbuffer.append(p,26);
+
+  d.ancount++;
+}
+
+
+void DNSPacket::addMXRecord(const DNSResourceRecord &rr)
+{
+  addMXRecord(rr.qname, rr.content, rr.priority, rr.ttl);
+}
+
+void DNSPacket::addMXRecord(const string &domain, const string &mx, int priority, u_int32_t ttl)
+{
+  string piece1;
+
+  toqname(domain,&piece1);
+
+  char piece2[12];
+
+  piece2[0]=0;
+
+  piece2[1]=15; // MX
+  piece2[2]=0;
+  piece2[3]=1; // IN
+
+  u_int32_t *ttlp=(u_int32_t *)(piece2+4);
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+  piece2[8]=0;
+  piece2[9]=0;  // need to fill this in
+
+  // start of payload for which we need to specify the length in 8 & 9
+
+  piece2[10]=(priority>>8)&0xff;
+  piece2[11]=priority&0xff;
+  
+  string piece3;
+  toqname(mx,&piece3);
+  // end of payload
+
+  piece2[9]=piece3.length()+2; // fill in length
+
+  stringbuffer+=piece1;
+  stringbuffer.append(piece2,12);
+  stringbuffer+=piece3;
+
+  d.ancount++;
+}
+
+string &DNSPacket::attodot(string &str)
+{
+   if(str.find_first_of("@")==string::npos)
+      return str;
+
+   for (unsigned int i = 0; i < str.length(); i++)
+   {
+      if (str[i] == '@') {
+         str[i] = '.';
+         break;
+      } else if (str[i] == '.') {
+         str.insert(i++, "\\");
+      }
+   }
+
+   return str;
+}
+
+void DNSPacket::fillSOAData(const string &content, SOAData &data)
+{
+  // content consists of fields separated by spaces:
+  //  nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
+
+  // fill out data with some plausible defaults:
+  // 10800 3600 604800 3600
+  data.serial=0;
+  data.refresh=10800;
+  data.retry=3600;
+  data.expire=604800;
+  data.default_ttl=arg().asNum("soa-minimum-ttl");
+
+  vector<string>parts;
+  stringtok(parts,content);
+  int pleft=parts.size();
+
+  //  cout<<"'"<<content<<"'"<<endl;
+
+  if(pleft)
+    data.nameserver=parts[0];
+
+  if(pleft>1) 
+    data.hostmaster=attodot(parts[1]); // ahu@ds9a.nl -> ahu.ds9a.nl, piet.puk@ds9a.nl -> piet\.puk.ds9a.nl
+
+  if(pleft>2)
+    data.serial=atoi(parts[2].c_str());
+
+  if(pleft>3)
+    data.refresh=atoi(parts[3].c_str());
+
+  if(pleft>4)
+    data.retry=atoi(parts[4].c_str());
+
+
+  if(pleft>5)
+    data.expire=atoi(parts[5].c_str());
+
+  if(pleft>6)
+    data.default_ttl=atoi(parts[6].c_str());
+
+}
+
+
+string DNSPacket::serializeSOAData(const SOAData &d)
+{
+  ostringstream o;
+
+  //  nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
+
+  o<<d.nameserver<<" "<< d.hostmaster <<" "<< d.serial <<" "<< d.refresh << " "<< d.retry << " "<< d.expire << " "<< d.default_ttl;
+
+  return o.str();
+
+}
+
+  /* the hostmaster is encoded as two parts - the bit UNTIL the first unescaped '.'
+     is encoded as a TXT string, the rest as a domain 
+
+     we might encounter escaped dots in the first part though: bert\.hubert.powerdns.com for example should be
+     11bert.hubert7powerdns3com0 */
+
+/* Very ugly btw, this needs to be better */
+const string DNSPacket::makeSoaHostmasterPiece(const string &hostmaster)
+{
+  string ret;
+  string first;
+  string::size_type i;
+
+  for(i=0;i<hostmaster.length();++i) {
+    if(hostmaster[i]=='.') {
+      break;
+    }
+    if(hostmaster[i]=='\\' && i+1<hostmaster.length()) {
+      ++i;
+      first.append(1,hostmaster[i]);
+      continue;
+    }
+    first.append(1,hostmaster[i]);
+  }
+
+  ret.resize(1);
+  ret[0]=first.length();
+  ret+=first;
+  
+  string second;
+  if(i+1<hostmaster.length())
+     toqname(hostmaster.substr(i+1),&second); 
+  else {
+     second.resize(1);
+     second[0]=0;
+  }
+
+  return ret+second;
+}
+
+void DNSPacket::addSOARecord(const DNSResourceRecord &rr)
+{
+  addSOARecord(rr.qname, rr.content, rr.ttl, rr.d_place);
+}
+
+void DNSPacket::addSOARecord(const string &domain, const string & content, u_int32_t ttl,DNSResourceRecord::Place place)
+{
+  SOAData soadata;
+  fillSOAData(content, soadata);
+
+  string piece1;
+  toqname(domain, &piece1);
+
+  char p[10];
+  
+  p[0]=0;
+  p[1]=6; // SOA
+  p[2]=0;
+  p[3]=1; // IN
+  
+  
+  u_int32_t *ttlp=(u_int32_t *)(p+4);
+  cout<<"adding ttl: "<<ttl<<endl;
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+  
+  p[8]=0;
+  p[9]=0;  // need to fill this in (length)
+  
+  string piece3;  
+  toqname(soadata.nameserver,&piece3, false);
+  
+  string piece4=makeSoaHostmasterPiece(soadata.hostmaster);
+
+  char piece5[20];
+  
+  u_int32_t *i_p=(u_int32_t *)piece5;
+  
+  u_int32_t soaoffset;
+  if(soadata.serial && (soaoffset=arg().asNum("soa-serial-offset")))
+    if(soadata.serial<soaoffset)
+      soadata.serial+=soaoffset; // thank you DENIC
+
+  *i_p++=htonl(soadata.serial ? soadata.serial : time(0));
+  *i_p++=htonl(soadata.refresh);
+  *i_p++=htonl(soadata.retry);
+  *i_p++=htonl(soadata.expire);
+  *i_p++=htonl(soadata.default_ttl);
+  
+  
+  p[9]=piece3.length()+piece4.length()+20; 
+
+  stringbuffer+=piece1;
+  stringbuffer.append(p,10);
+  stringbuffer+=piece3;
+  stringbuffer+=piece4;
+  stringbuffer.append(piece5,20);
+  if(place==DNSResourceRecord::ANSWER)
+    d.ancount++;
+  else
+    d.nscount++;
+}
+
+
+
+void DNSPacket::addCNAMERecord(const DNSResourceRecord &rr)
+{
+  addCNAMERecord(rr.qname, rr.content, rr.ttl);
+}
+
+void DNSPacket::addCNAMERecord(const string &domain, const string &alias, u_int32_t ttl)
+{
+ string piece1;
+
+ //xtoqname(domain.c_str(),&piece1); 
+ toqname(domain.c_str(),&piece1);
+ char p[10];
+ p[0]=0;
+ p[1]=5; // CNAME
+ p[2]=0;
+ p[3]=1; // IN
+ u_int32_t *ttlp=(u_int32_t *)(p+4);
+ *ttlp=htonl(ttl); // 4, 5, 6, 7
+ p[8]=0;
+ p[9]=0;  // need to fill this in
+ string piece3;
+ //xtoqname(alias,&piece3);
+ toqname(alias,&piece3);
+ p[9]=piece3.length();
+
+ stringbuffer+=piece1;
+ stringbuffer.append(p,10);
+ stringbuffer+=piece3;
+
+ d.ancount++;
+}
+
+
+void DNSPacket::addRPRecord(const DNSResourceRecord &rr)
+{
+  addRPRecord(rr.qname, rr.content, rr.ttl);
+}
+
+void DNSPacket::addRPRecord(const string &domain, const string &content, u_int32_t ttl)
+{
+ string piece1;
+
+ //xtoqname(domain.c_str(),&piece1);
+ toqname(domain.c_str(),&piece1);
+ char p[10];
+ p[0]=0;
+ p[1]=17; // RP
+ p[2]=0;
+ p[3]=1; // IN
+ u_int32_t *ttlp=(u_int32_t *)(p+4);
+ *ttlp=htonl(ttl); // 4, 5, 6, 7
+ p[8]=0;
+ p[9]=0;  // need to fill this in
+ // content contains: mailbox-name more-info-domain (Separated by a space)
+ unsigned int pos;
+ if((pos=content.find(" "))==string::npos)
+   {
+     L<<Logger::Warning<<"RP record for domain '"<<domain<<"' has malformed content field"<<endl;
+     return;
+   }
+
+ string mboxname=content.substr(0,pos);
+ string moreinfo=content.substr(pos+1);
+
+ string piece3;
+ //xtoqname(mboxname,&piece3);
+ toqname(mboxname,&piece3);
+
+ string piece4;
+ //xtoqname(moreinfo,&piece4);
+ toqname(moreinfo,&piece4);
+ p[9]=(piece3.length()+piece4.length())%256;
+ p[10]=(piece3.length()+piece4.length())/256;
+
+ stringbuffer+=piece1;
+ stringbuffer.append(p,10);
+ stringbuffer+=piece3;
+ stringbuffer+=piece4;
+
+ // done
+ d.ancount++;
+}
+
+
+
+
+void DNSPacket::addNAPTRRecord(const DNSResourceRecord &rr)
+{
+  addNAPTRRecord(rr.qname, rr.content, rr.ttl);
+}
+
+
+
+void DNSPacket::addNAPTRRecord(const string &domain, const string &content, u_int32_t ttl)
+{
+  string piece1;
+
+  //xtoqname(domain.c_str(),&piece1);
+  toqname(domain.c_str(),&piece1);
+  char p[10];
+  
+  p[0]=0;
+  p[1]=QType::NAPTR; 
+  p[2]=0;
+  p[3]=1; // IN
+  u_int32_t *ttlp=(u_int32_t *)(p+4);
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+  
+  p[8]=0;
+  p[9]=0;  // need to fill this in
+  // content contains: 100  100  "s"   "http+I2R"   ""    _http._tcp.foo.com.
+
+  vector<string> parts;
+  stringtok(parts,content);
+  if(parts.size()<2) 
+    return;
+
+  int order=atoi(parts[0].c_str());
+  int pref=atoi(parts[1].c_str());
+
+  vector<string::const_iterator>poss;
+  string::const_iterator i;
+  for(i=content.begin();i!=content.end();++i)
+    if(*i=='"')
+      poss.push_back(i);
+
+  if(poss.size()!=6)
+    return;
+  string flags, services, regex;
+  insert_iterator<string> flagsi(flags, flags.begin());
+  copy(poss[0]+1,poss[1],flagsi);
+  insert_iterator<string> servicesi(services, services.begin());
+  copy(poss[2]+1,poss[3],servicesi);
+  insert_iterator<string> regexi(regex, regex.begin());
+  copy(poss[4]+1,poss[5],regexi);
+  
+  for(i=poss[5]+1;i<content.end() && isspace(*i);++i); // skip spaces
+  string replacement;
+  insert_iterator<string> replacementi(replacement,replacement.begin());
+  copy(i,content.end(),replacementi);
+
+/* 
+ The packet format for the NAPTR record is:
+
+                                          1  1  1  1  1  1
+            0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          |                     ORDER                     |
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          |                   PREFERENCE                  |
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          /                     FLAGS                     /
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          /                   SERVICES                    /
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          /                    REGEXP                     /
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          /                  REPLACEMENT                  /
+          /                                               /
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+         (jeez)
+*/
+
+
+  string piece3;
+  piece3.resize(4);
+  piece3[0]=(order>>8)&0xff;
+  piece3[1]=(order)&0xff;
+
+  piece3[2]=(pref>>8)&0xff;
+  piece3[3]=(pref)&0xff;
+
+  piece3.append(1,flags.length());
+  piece3.append(flags);
+  piece3.append(1,services.length());
+  piece3.append(services);
+  piece3.append(1,regex.length());
+  piece3.append(regex);
+
+  string piece4;
+  toqname(replacement,&piece4);
+  p[9]=(piece3.length()+piece4.length())%256;
+  p[10]=(piece3.length()+piece4.length())/256;
+
+  stringbuffer+=piece1;
+  stringbuffer.append(p,10);
+  stringbuffer+=piece3;
+  stringbuffer+=piece4;
+  
+  // done
+  d.ancount++;
+}
+void DNSPacket::addPTRRecord(const DNSResourceRecord &rr)
+{
+  addPTRRecord(rr.qname, rr.content, rr.ttl);
+}
+
+void DNSPacket::addPTRRecord(const string &domain, const string &alias, u_int32_t ttl)
+{
+ string piece1;
+
+ //xtoqname(domain,&piece1);
+ toqname(domain,&piece1);
+ char p[10];
+ p[0]=0;
+ p[1]=12; // PTR
+ p[2]=0;
+ p[3]=1; // IN
+ u_int32_t *ttlp=(u_int32_t *)(p+4);
+ *ttlp=htonl(ttl); // 4, 5, 6, 7
+ p[8]=0;
+ p[9]=0;  // need to fill this in
+
+ string piece3;
+ //xtoqname(alias,&piece3);
+ toqname(alias,&piece3);
+ p[9]=piece3.length();
+ stringbuffer+=piece1;
+ stringbuffer.append(p,10);
+ stringbuffer+=piece3;
+
+ d.ancount++;
+}
+
+
+
+void DNSPacket::addTXTRecord(const DNSResourceRecord& rr)
+{
+  addTXTRecord(rr.qname, rr.content, rr.ttl);
+}
+
+void DNSPacket::addTXTRecord(string domain, string txt, u_int32_t ttl)
+{
+ string piece1;
+ //xtoqname(domain, &piece1);
+ toqname(domain, &piece1);
+ char p[10];
+ p[0]=0;
+ p[1]=16; // TXT
+ p[2]=0;
+ p[3]=1; // IN
+
+ u_int32_t *ttlp=(u_int32_t *)(p+4);
+ *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+ p[8]=0;
+ p[9]=0; // need to fill this in
+
+ string piece3;
+ piece3.reserve(txt.length()+1);
+ piece3.append(1,txt.length());
+ piece3.append(txt);
+
+ p[8]=0;
+ p[9]=piece3.length();
+
+ stringbuffer+=piece1;
+ stringbuffer.append(p,10);
+ stringbuffer+=piece3;
+
+ d.ancount++;
+}
+
+void DNSPacket::addHINFORecord(const DNSResourceRecord& rr)
+{
+  addHINFORecord(rr.qname, rr.content, rr.ttl);
+}
+
+/** First word of content is the CPU */
+void DNSPacket::addHINFORecord(string domain, string content, u_int32_t ttl)
+{
+ string piece1;
+ toqname(domain, &piece1);
+ char p[10];
+ p[0]=0;
+ p[1]=13; // HINFO
+ p[2]=0;
+ p[3]=1; // IN
+
+ u_int32_t *ttlp=(u_int32_t *)(p+4);
+ *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+ p[8]=0;
+ p[9]=0; // need to fill this in
+
+ unsigned int offset=content.find(" ");
+ string cpu, host;
+ if(offset==string::npos) {
+   cpu=content;
+ } else {
+   cpu=content.substr(0,offset);
+   host=content.substr(offset);
+ }
+
+ string piece3;
+ piece3.reserve(cpu.length()+1);
+ piece3.append(1,cpu.length());
+ piece3.append(cpu);
+
+ string piece4;
+ piece4.reserve(host.length()+1);
+ piece4.append(1,host.length());
+ piece4.append(host);
+
+
+ p[8]=0;
+ p[9]=piece3.length()+piece4.length();
+
+ stringbuffer+=piece1;
+ stringbuffer.append(p,10);
+ stringbuffer+=piece3;
+ stringbuffer+=piece4;
+
+ d.ancount++;
+}
+
+
+
+void DNSPacket::addNSRecord(const DNSResourceRecord &rr)
+{
+  addNSRecord(rr.qname, rr.content, rr.ttl, rr.d_place);
+}
+
+void DNSPacket::addNSRecord(string domain, string server, u_int32_t ttl, DNSResourceRecord::Place place)
+{
+  string piece1;
+  toqname(domain, &piece1);
+
+  char p[10];
+
+  p[0]=0;
+  p[1]=2; // NS
+  p[2]=0;
+  p[3]=1; // IN
+
+  u_int32_t *ttlp=(u_int32_t *)(p+4);
+
+  *ttlp=htonl(ttl); // 4, 5, 6, 7
+
+  p[8]=0;
+  p[9]=0;  // need to fill this in
+
+  string piece3;
+  string::size_type pos=server.find('@'); // chop off @
+  if(pos!=string::npos)
+    server.resize(pos);
+
+  toqname(server,&piece3);
+
+  p[9]=piece3.length();;
+
+  stringbuffer.append(piece1);
+  stringbuffer.append(p,10);
+  stringbuffer.append(piece3);
+
+  if(place==DNSResourceRecord::AUTHORITY)
+    d.nscount++;
+  else
+    d.ancount++;
+
+}
+
+
+static int rrcomp(const DNSResourceRecord &A, const DNSResourceRecord &B)
+{
+  if(A.d_place<B.d_place)
+    return 1;
+
+  return 0;
+}
+
+/** You can call this function to find out if there are any records that need additional processing. 
+    This holds for MX records and CNAME records, where information about the content may need further resolving. */
+bool DNSPacket::needAP()
+{
+  // if speed ever becomes an issue, this function might be implemented in the addRecord() method, which would set a flag
+  // whenever a record that needs additional processing is added
+
+  for(vector<DNSResourceRecord>::const_iterator i=rrs.begin();
+      i!=rrs.end();
+      ++i)
+    {
+      if(i->d_place!=DNSResourceRecord::ADDITIONAL && 
+        ( (i->qtype.getCode()==QType::NS && i->content.find('@')==string::npos) ||  // NS records with @ in them are processed
+         i->qtype.getCode()==QType::MX )) 
+       {
+         return true;
+       }
+    }
+  return false;
+}
+
+vector<DNSResourceRecord> DNSPacket::getAPRecords()
+{
+  vector<DNSResourceRecord> arrs;
+
+  for(vector<DNSResourceRecord>::const_iterator i=rrs.begin();
+      i!=rrs.end();
+      ++i)
+    {
+      if(i->d_place!=DNSResourceRecord::ADDITIONAL && 
+        (i->qtype.getCode()==15 || 
+         i->qtype.getCode()==2 )) // CNAME or MX or NS
+       {
+         arrs.push_back(*i);
+       }
+    }
+
+  return arrs;
+
+}
+
+void DNSPacket::setCompress(bool compress)
+{
+  d_compress=compress;
+  stringbuffer.reserve(65000);
+  rrs.reserve(200);
+}
+
+/** Must be called before attempting to access getData(). This function stuffs all resource
+ *  records found in rrs into the data buffer. It also frees resource records queued for us.
+ */
+void DNSPacket::wrapup(void)
+{
+  if(d_wrapped) {
+    return;
+  }
+  
+  // do embedded-additional processing decapsulation
+  DNSResourceRecord rr;
+  vector<DNSResourceRecord>::iterator pos;
+
+  vector<DNSResourceRecord> additional;
+  for(pos=rrs.begin();pos<rrs.end();++pos) {
+    if(pos->qtype.getCode()==QType::NS) {
+      vector<string>pieces;
+      stringtok(pieces,pos->content,"@");
+      
+      if(pieces.size()>1) { // INSTANT ADDITIONAL PROCESSING!
+       rr.qname=pieces[0];
+       rr.qtype=QType::A;
+       rr.ttl=pos->ttl;
+       rr.content=pieces[1];
+       rr.d_place=DNSResourceRecord::ADDITIONAL;
+       additional.push_back(rr);
+      }
+    }
+  }
+  int ipos=rrs.size();
+  rrs.resize(rrs.size()+additional.size());
+  copy(additional.begin(), additional.end(), rrs.begin()+ipos);
+
+  // we now need to order rrs so that the different sections come at the right place
+  // we want a stable sort, based on the d_place field
+
+  stable_sort(rrs.begin(),rrs.end(),rrcomp);
+
+  d_wrapped=true;
+
+
+  for(pos=rrs.begin();pos<rrs.end();++pos) {
+    rr=*pos;
+    DLOG(L<<"Added to data, RR: " << rr.qname);
+    DLOG(L<<"(" << rr.qtype.getName() << ")" << " " << (int) rr.d_place<< endl);
+
+    switch(rr.qtype.getCode()) {
+    case 1:  // A
+      addARecord(rr);
+      break;
+    case 2:  // NS
+      addNSRecord(rr);
+      break;
+
+    case 5:  // CNAME
+      addCNAMERecord(rr);
+      break;
+
+    case 6:  // SOA
+      addSOARecord(rr);
+      break;
+
+    case 12:  // PTR
+      addPTRRecord(rr);
+      break;
+
+    case 13: // HINFO
+      addHINFORecord(rr);
+      break;
+
+    case 15: // MX
+      addMXRecord(rr);
+      break;
+
+    case 16: // TXT
+      addTXTRecord(rr);
+      break;
+
+    case 17: // RP
+      addRPRecord(rr);
+      break;
+
+
+    case 28: // AAAA
+      addAAAARecord(rr);
+      break;
+
+    case QType::NAPTR:
+      addNAPTRRecord(rr);
+      break;
+
+    case 258: // CURL
+    case 256: // URL
+      addARecord(rr.qname,htonl(inet_addr(arg()["urlredirector"].c_str())),rr.ttl,DNSResourceRecord::ANSWER);   
+      break;
+
+    case 257: // MBOXFW
+      unsigned int pos;
+      pos=rr.qname.find("@");
+      DLOG(L<<Logger::Warning<<"Adding rr.qname: '"<<rr.qname<<"'"<<endl);
+      if(pos!=string::npos)
+       {
+         string substr=rr.qname.substr(pos+1);
+
+         addMXRecord(substr,arg()["smtpredirector"],25,rr.ttl);
+       }
+      break;
+
+    default:
+      L<<Logger::Warning<<"Unable to insert a record of type "<<rr.qtype.getName()<<" for '"<<rr.qname<<"'"<<endl;
+    }
+  }
+  d.ancount=htons(d.ancount);
+  d.qdcount=htons(d.qdcount);
+  d.nscount=htons(d.nscount);
+  d.arcount=htons(d.arcount);
+
+  commitD();
+
+
+  len=stringbuffer.length();
+}
+
+
+/** Truncates a packet that has already been wrapup()-ed, possibly via a call to getData(). Do not call this function
+    before having done this - it will possibly break your packet, or crash your program. 
+
+    This method sets the 'TC' bit in the stringbuffer, and caps the len attributed to new_length.
+*/ 
+
+void DNSPacket::truncate(int new_length)
+{
+  if(new_length>len || !d_wrapped)
+    return;
+
+  DLOG(L<<Logger::Warning<<"Truncating a packet to "<<inet_ntoa( reinterpret_cast< sockaddr_in * >( remote )->sin_addr )<<endl);
+
+  len=new_length;
+  stringbuffer[2]|=2; // set TC
+}
+
+string DNSPacket::compress(const string &qd)
+{
+  // input www.casema.net, output 3www6casema3net
+  // input www.casema.net., output 3www6casema3net
+  string qname = "";
+
+  // Convert the name to a qname
+
+  const char *p = qd.c_str();
+  const char *q = strchr(p, '.');
+  
+  while (p <= (qd.c_str() + qd.length()))
+    {
+      int length = (q == NULL) ? strlen(p) : (q - p);
+      if (length == 0) {
+        break;
+      }
+      qname += (char) length;
+      qname.append(p, length);
+      
+      if (q == NULL) {
+       break;
+      } else {
+       p = q + 1;
+       q = strchr(p, '.');
+      }
+    }
+  
+  qname += (char) 0x00;
+  return qname;
+}
+
+void DNSPacket::setQuestion(int op, const string &qd, int qtype)
+{
+  memset(&d,0,sizeof(d));
+  d.id=Utility::random();
+  d.rd=d.tc=d.aa=false;
+  d.qr=false;
+  d.qdcount=1; // is htons'ed later on
+  d.ancount=d.arcount=d.nscount=0;
+  d.opcode=op;
+
+  string label=compress(qd);
+  stringbuffer.assign((char *)&d,sizeof(d));
+  stringbuffer.append(label);
+  u_int16_t tmp=htons(qtype);
+  stringbuffer.append((char *)&tmp,2);
+  tmp=htons(1);
+  stringbuffer.append((char *)&tmp,2);
+}
+
+
+
+
+/** A DNS answer packets needs to include the original question. This function allows you to
+    paste in a question */
+
+void DNSPacket::pasteQ(const char *question, int length)
+{
+  stringbuffer.replace(12,length,question,length);  // bytes 12 & onward need to become *question
+}
+
+vector<DNSResourceRecord> DNSPacket::getAnswers()
+{
+  vector<DNSResourceRecord> rrs;
+  if(!(d.ancount|d.arcount|d.nscount))
+    return rrs;
+
+  const char *answerp=stringbuffer.c_str()+d_qlen+12;
+  const char *end=stringbuffer.c_str()+len;
+
+  int numanswers=ntohs(d.ancount) + ntohs(d.nscount) + ntohs(d.arcount);
+  int length;
+  int pos=0;
+  while(numanswers--) {
+    string name;  
+    int offset=0;
+    offset=expand(answerp,end,name);
+
+    DNSResourceRecord rr;
+    rr.qname=name;
+    rr.qtype=ntohs(*((short int *)(answerp+offset)));
+    rr.ttl=ntohl(*(u_int32_t*)(answerp+offset+4)); // 4, 5, 6, 7
+    rr.content="";
+    length=ntohs(*(u_int16_t*)(answerp+offset+8));
+
+    const char *datapos=answerp+offset+10;
+    string part;
+    offset=0;
+
+    ostringstream o;
+    int ip;
+
+    switch(rr.qtype.getCode()) {
+
+    case QType::SOA:
+      part=""; offset+=expand(datapos+offset,end,part); rr.content=part;      // mname
+      part=""; offset+=expand(datapos+offset,end,part); rr.content+=" "+part;  // hostmaster
+
+      rr.content+=" ";rr.content+=itoa(ntohl(*(unsigned int *)(datapos+offset)));
+      rr.content+=" ";rr.content+=itoa(ntohl(*(unsigned int *)(datapos+offset+4)));
+      rr.content+=" ";rr.content+=itoa(ntohl(*(unsigned int *)(datapos+offset+8)));
+      rr.content+=" ";rr.content+=itoa(ntohl(*(unsigned int *)(datapos+offset+12)));
+      rr.content+=" ";rr.content+=itoa(ntohl(*(unsigned int *)(datapos+offset+16)));
+
+      break;
+
+    case QType::A:
+      ip = ntohl(*((int *)datapos));
+
+      o.clear();
+      o<<((ip>>24)&0xff)<<".";
+      o<<((ip>>16)&0xff)<<".";
+      o<<((ip>>8)&0xff)<<".";
+      o<<((ip>>0)&0xff);
+      
+      rr.content=o.str();
+      break;
+      
+    case QType::MX:
+      rr.priority=(datapos[0] << 8) + datapos[1];
+      expand(datapos+2,end,rr.content);
+
+      break;
+
+    case QType::CNAME:
+    case QType::NS:
+    case QType::PTR:
+      expand(datapos+offset,end,rr.content);
+      break;
+
+    case QType::AAAA:
+      if(length!=16)
+       throw AhuException("Wrong length AAAA record returned from remote");
+      char tmp[128];
+       
+      if(!Utility::inet_ntop(AF_INET6, datapos, tmp, sizeof(tmp)-1))
+       throw AhuException("Unable to translate record of type AAAA in resolver");
+
+      rr.content=tmp;
+      break;
+
+    default:
+      throw AhuException("Unknown type number "+itoa(rr.qtype.getCode())+" for: '"+rr.qname+"'");
+    }
+    if(pos<ntohs(d.ancount))
+      rr.d_place=DNSResourceRecord::ANSWER;
+    else if(pos<ntohs(d.ancount)+ntohs(d.nscount))
+      rr.d_place=DNSResourceRecord::AUTHORITY;
+    else
+      rr.d_place=DNSResourceRecord::ADDITIONAL;
+      
+    rrs.push_back(rr);    
+    pos++;
+    //    cout<<"Added '"<<rr.qname<<"' '"<<rr.content<<"' "<<rr.qtype.getName()<<endl;
+    //    cout<<"Advancing "<<length<<" bytes"<<endl;
+    answerp=datapos+length; 
+  }
+  return rrs;
+  
+}
+
+/** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
+DNSPacket *DNSPacket::replyPacket() const
+{
+  DNSPacket *r=new DNSPacket;
+  r->setSocket(d_socket);
+
+
+  r->setRemote((struct sockaddr *)remote, d_socklen);
+  r->setAnswer(true);  // this implies the allocation of the header
+  r->setA(true); // and we are authoritative
+  r->setRA(0); // no recursion available
+  r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it (we don't do it)
+  r->setID(d.id);
+  r->setOpcode(d.opcode);
+
+  // reserve some space
+  r->stringbuffer.reserve(d_qlen+12);
+  // copy the question in
+  r->pasteQ(stringbuffer.c_str()+12,d_qlen);
+  r->d.qdcount=1;
+  
+  r->d_dt=d_dt;
+
+  return r;
+}
+
+int DNSPacket::findlabel(string &label)
+{
+  const char *data = stringbuffer.data();
+  const char *p = data + 12;
+
+  // Look in the question section
+   
+  for (unsigned int i = 0; i < d.qdcount; i++) {
+    while (*p != 0x00) {
+      // Skip compressed labels
+      if ((*p & 0xC0) == 0xC0) {
+       p += 1;
+       break;
+      }
+      else {
+       if (strcmp(p, label.data()) == 0)
+         return (p - data);
+       p += (*p + 1);
+      }
+    }
+      
+    // Skip the tailing zero
+    p++;
+    
+    // Skip the header
+    p += 4;
+  }
+
+  //
+  // Look in the answer sections
+  //
+
+  for (unsigned int i = 0; i < d.ancount + d.nscount + d.arcount; i++) {
+    while (*p != 0x00) {
+      // Skip compressed labels - means the end
+      if ((*p & 0xC0) == 0xC0)
+       {
+         p += 1;
+         break;
+       }
+      else
+       {
+         if (strcmp(p, label.data()) == 0)
+           {
+             return (p - data);
+           }
+         
+         p += (*p + 1);
+       }
+    }
+    
+    // Skip the trailing zero or other half of the ptr
+       
+    p++;
+
+    // Skip the header and data
+    
+    short int dataLength = ntohs(*(short int*) (p + 8));
+    short int type = ntohs(*(short int*) (p));
+
+    p += 10;
+    
+    // Check for NS, CNAME, PTR and MX records
+    
+    if (type == QType::NS || type == QType::CNAME || type == QType::PTR || type == QType::MX) {
+      // For MX records, skip the preference field
+      if (type == QType::MX){
+       p += 2;
+      }
+
+      while (*p != 0x00) {
+       //
+       // Skip compressed labels
+       //
+       
+       if ((*p & 0xC0) == 0xC0) {
+         p += 1;
+         break;
+       }
+       else {
+
+         if (strcmp(p, label.data()) == 0) {
+           return (p - data);
+         }
+                  
+         p += (*p + 1);
+       }
+      }
+          
+      // Skip the trailing zero or the last byte of a compresed label
+      p++;      
+    }
+    else {
+      p += dataLength;
+    }
+  }
+  
+  return -1;
+}
+
+int DNSPacket::toqname(const char *name, string &qname, bool comp)
+{
+  qname = compress(name);
+
+  if (d_compress && comp) {
+    // Now find a previous declared label. We work through the complete
+    // name from left to right like this:
+    //  ns1.norad.org
+    //  norad.org
+    //  org
+    
+    int i = 0;
+    
+    while (qname[i] != 0x00) {
+      // Get a portion of the name
+      
+      string s = qname.substr(i);
+
+      // Did we see this before?
+      int offset = findlabel(s);
+      
+      if ( offset != -1) {
+
+       qname[i + 0] = (char) (((offset | 0xC000) & 0x0000FF00) >> 8);
+       qname[i + 1] = (char)  ((offset | 0xC000) & 0x000000FF);
+       qname = qname.substr(0, i + 2); // XX setlength() ?
+       // qname now consists of unique prefix+known suffix (on location 'offset')
+       break;
+      }
+      // Move to the next label
+      i += (qname[i] + 1); // doesn't quite handle very long labels
+    }
+  }
+  
+  return qname.length();
+}
+
+int DNSPacket::toqname(const string &name, string &qname, bool compress)
+{
+   return toqname(name.c_str(), qname, compress);
+}
+
+int DNSPacket::toqname(const string &name, string *qname, bool compress)
+{
+   return toqname(name.c_str(), *qname, compress);
+}
+
diff --git a/pdns/dnspacket.hh b/pdns/dnspacket.hh
new file mode 100644 (file)
index 0000000..50c529f
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: dnspacket.hh,v 1.1 2002/11/27 15:18:32 ahu Exp $
+#ifndef DNSPACKET_HH
+#define DNSPACKET_HH
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>\r
+\r
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <unistd.h>\r
+#include <arpa/inet.h>\r
+\r
+#endif // WIN32
+
+#include <iostream>
+#include <string>
+
+#include <vector>
+#include "qtype.hh"
+#include "dns.hh"
+#include "misc.hh"
+#include "utility.hh"
+#include "logger.hh"
+#include "ahuexception.hh"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+
+
+#ifdef NEED_POSIX_TYPEDEF
+typedef unsigned short int u_int16_t;
+#endif
+
+class DNSBackend;
+
+//! This class represents DNS packets, either received or to be sent.
+class DNSPacket
+{
+public:
+  DNSPacket();
+  DNSPacket(const DNSPacket &orig);
+
+  int expand(const char *begin, const char *end, string &expanded, int depth=0);
+  inline int parse(const char *mesg, int len); //!< parse a raw UDP or TCP packet and suck the data inward
+  string getString();
+
+  //! the raw DNS header
+  struct dnsheader 
+  {
+    unsigned int id:16;  //!< id of this query/response
+#if BYTE_ORDER == BIG_ENDIAN
+    unsigned int qr:1;      //!< 1 if this is a query, 0 if response
+    unsigned int opcode:4;  //!< the opcode
+    unsigned int aa:1;   //!< packet contains authoritative data
+    unsigned int tc:1;   //!< packet is truncated
+    unsigned int rd:1;   //!< this packets wants us to recurse
+    unsigned int ra:1;     //!< ??
+    unsigned int unused:1; //!< 
+    unsigned int ad:1;     //!< authentic data
+    unsigned int cd:1;     //!< checking disabled by resolver
+    unsigned int rcode:4;  //!< ??
+#else
+    unsigned int rd:1;   //!< this packets wants us to recurse
+    unsigned int tc:1;   //!< packet is truncated
+    unsigned int aa:1;   //!< packet contains authoritative data
+    unsigned int opcode:4;  //!< the opcode
+    unsigned int qr:1;      //!< 1 if this is a query, 0 if response
+
+    /////////// 
+
+    unsigned int rcode:4;  //!< ??
+    unsigned int cd:1;     //!< checking disabled by resolver
+    unsigned int ad:1;     //!< authentic data
+    unsigned int unused:1; //!< 
+    unsigned int ra:1;     //!< ??
+#endif
+    ////////////////
+    
+    unsigned int qdcount:16;  //!< number of questions
+    unsigned int ancount:16;  //!< number of answers
+    unsigned int nscount:16;  //!< number of authoritative nameservers included in answer
+    unsigned int arcount:16;  //!< number of additional resource records
+  };
+
+  inline void setRemote(const struct sockaddr *a, Utility::socklen_t socklen);
+  string getRemote() const;
+  void setA(bool); //!< make this packet authoritative
+  void setRA(bool); //!< set the Recursion Available flag
+  void setRD(bool); //!< set the Recursion Desired flag
+  void setAnswer(bool); //!< Make this packet an answer
+  void setID(u_int16_t); //!< set the DNS id of this packet
+  void setOpcode(u_int16_t);  //!< set the Opcode of this packet
+  void setRcode(int v); //!< set the Rcode of this packet
+
+
+  /** Add a DNSResourceRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions, 
+      Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the
+      DNSResourceRecord d_place field */
+  void addRecord(const DNSResourceRecord &); 
+
+
+  /** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
+  static void fillSOAData(const string &content, SOAData &data);
+
+  /** for use by DNSPacket, converts a SOAData class to a ascii line again */
+  static string serializeSOAData(const SOAData &data);
+  void setQuestion(int op, const string &qdomain, int qtype);
+  vector<DNSResourceRecord> getAnswers();
+private:
+  string compress(const string &qd);
+  void addARecord(const string&, u_int32_t, u_int32_t ttl, DNSResourceRecord::Place place); //!< add an A record to the packet
+  void addARecord(const DNSResourceRecord &); //!< add an A record to the packet
+
+  void addAAAARecord(const string &, unsigned char addr[16], u_int32_t ttl); //!< add an A record to the packet
+  void addAAAARecord(const DNSResourceRecord &); //!< add an A record to the packet
+
+
+  void addMXRecord(const string &domain, const string &mx, int priority, u_int32_t ttl); //!< add an MX record to the packet
+  void addMXRecord(const DNSResourceRecord &); //!< add an MX record to the packet
+
+  void addCNAMERecord(const string &domain, const string &alias, u_int32_t ttl); //!< add a CNAME record to the packet
+  void addCNAMERecord(const DNSResourceRecord &); //!< add a CNAME record to the packet
+
+  void addRPRecord(const string &domain, const string &content, u_int32_t ttl); //!< add a RP record to the packet
+  void addRPRecord(const DNSResourceRecord &); //!< add a RP record to the packet
+
+  void addNAPTRRecord(const string &domain, const string &content, u_int32_t ttl); //!< add a RP record to the packet
+  void addNAPTRRecord(const DNSResourceRecord &); //!< add a RP record to the packet
+
+
+  void addPTRRecord(const string &domain, const string &alias, u_int32_t ttl); //!< add a PTR record to the packet
+  void addPTRRecord(const DNSResourceRecord &); //!< add a PTR record to the packet
+
+
+  /** Adds a SOA record to the packet. The SOA record is very special because we have a lot of default values, 
+      that may be overridden by the contents of the database. Content can have a variety of content:
+      
+      (nothing)
+      hostmaster
+      hostmaster serial-number
+      hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
+
+      Suggested values are: 
+
+      10800           ;refresh every three hours
+      300             ;retry every 5 min
+      604800          ;expire after a week
+      86400           ;default ttl 
+
+      An empty field means that we supply hostmaster+@+domain name as hostmaster. An empty serial number is replaced by the 
+      number of seconds since 1 jan 1970 (unix timestamp). The other values are substituted as indicated
+
+  */
+
+
+  void addSOARecord(const string &domain, const string &content, u_int32_t ttl, DNSResourceRecord::Place place); 
+  void addSOARecord(const DNSResourceRecord &); //!< add a SOA record to the packet
+
+
+  void addTXTRecord(string domain, string, u_int32_t ttl); //!< add a TXT record to the packet
+  void addTXTRecord(const DNSResourceRecord &); //!< add a TXT record to the packet
+
+  void addHINFORecord(string domain, string, u_int32_t ttl); //!< add a HINFO record to the packet
+  void addHINFORecord(const DNSResourceRecord &); //!< add a HINFO record to the packet
+
+  void addNSRecord(string domain, string server, u_int32_t ttl, DNSResourceRecord::Place place); //!< add an NS record to the packet
+  void addNSRecord(const DNSResourceRecord &); //!< add an NS record to the packet
+
+  static string &attodot(string &str);  //!< for when you need to insert an email address in the SOA
+
+public:
+
+  DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer
+  void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies
+  void trim();
+  void wrapup(void); 
+  inline const char *getData(void); //!< get binary representation of packet
+  void setRaw(char *mesg, int length);
+  const char *getRaw(void);
+  inline void spoofID(u_int16_t id); //!< change the ID of an existing packet. Useful for fixing up packets returned from the PacketCache
+  inline void spoofQuestion(const string &qd); //!< paste in the exact right case of the question. Useful for PacketCache
+  void truncate(int new_length); // has documentation in source
+
+  bool needAP(); //!< query this to find out if this packet needs additional processing
+  vector<DNSResourceRecord> getAPRecords(); //!< get a vector with DNSResourceRecords that need additional processing
+  void setCompress(bool compress);
+
+  DNSPacket *replyPacket() const; //!< convenience function that creates a virgin answer packet to this question
+  Utility::sock_t getSocket() const
+  {
+    return d_socket;
+  }
+  inline void setSocket(Utility::sock_t sock);
+  inline void commitD();
+  static bool isRD(const string &buffer)
+  {
+    return ((struct dnsheader *)buffer.c_str())->rd;
+  }
+
+  //////// DATA !
+
+  char remote[28];
+  Utility::socklen_t d_socklen; // 4
+  u_int16_t len; //!< length of the raw binary packet 2
+  u_int16_t qclass;  //!< class of the question - should always be INternet 2
+  struct dnsheader d; //!< dnsheader at the start of the databuffer 12
+
+  QType qtype;  //!< type of the question 8
+
+  string qdomain;  //!< qname of the question 4
+
+
+private:
+  bool d_wrapped; // 1
+  bool d_compress; // 1
+  u_int16_t d_qlen; // length of the question (including class & type) in this packet 2
+
+  int d_socket; // 4
+  int findlabel(string &label);
+  int toqname(const char *name, string &qname, bool compress = true);
+  int toqname(const string &name, string &qname, bool compress = true);
+  int toqname(const string &name, string *qname, bool compress = true); 
+  const string makeSoaHostmasterPiece(const string &hostmaster);
+
+  int domprint();
+  int getq();
+
+  // MORE DATA!
+
+  string stringbuffer; // this is where everything lives 4
+
+  vector<DNSResourceRecord> rrs; // 4
+};
+
+
+inline void DNSPacket::spoofQuestion(const string &qd)
+{
+  string label=compress(qd);
+  for(string::size_type i=0;i<label.size();++i)
+    stringbuffer[i+sizeof(d)]=label[i];
+  d_wrapped=true; // if we do this, don't later on wrapup
+}
+
+/** This function takes data from the network, possibly received with recvfrom, and parses
+    it into our class. Results of calling this function multiple times on one packet are
+    unknown. Returns -1 if the packet cannot be parsed.
+*/
+int DNSPacket::parse(const char *mesg, int length)
+{
+  stringbuffer.assign(mesg,length); 
+  len=length;
+  if(length < 12) { 
+    L << Logger::Warning << "Ignoring packet: too short from "
+      << getRemote() << endl;
+    return -1;
+  }
+
+  memcpy((void *)&d,(const void *)stringbuffer.c_str(),12);
+
+  int offset=0;
+  d_qlen=0;
+  if(ntohs(d.qdcount)) {
+    offset = getq(); // also sets this->qdomain!
+    if(offset < 0) {
+      //    L << Logger::Warning << "Ignoring packet: invalid label in question from "
+      //  << inet_ntoa(remote.sin_addr) << endl;
+      return -1;
+    }
+    d_qlen=offset+4; // this points to the start of any answers
+  }
+
+
+  const char *p=(stringbuffer.c_str()+12+offset);
+  const unsigned short int *i=(const unsigned short int *)p;
+  qtype=ntohs(*i++);
+  qclass=ntohs(*i);
+
+
+  return 0;
+}
+
+//! Use this to set where this packet was received from or should be sent to
+inline void DNSPacket::setRemote(const struct sockaddr *s, Utility::socklen_t socklen)
+{
+  if(socklen>(Utility::socklen_t)sizeof(remote))
+    throw AhuException("Address too long for storage: "+itoa(socklen));
+
+  memcpy((void *)remote,(void *)s,socklen);
+  d_socklen=socklen;
+}
+
+inline void DNSPacket::spoofID(u_int16_t id)
+{
+  stringbuffer[1]=(id>>8)&0xff; 
+  stringbuffer[0]=id&0xff;
+  d.id=id;
+}
+
+inline void DNSPacket::setSocket(Utility::sock_t sock)
+{
+  d_socket=sock;
+}
+
+inline void DNSPacket::commitD()
+{
+  stringbuffer.replace(0,12,(char *)&d,12); // copy in d
+}
+
+inline const char *DNSPacket::getData(void)
+{
+  if(!d_wrapped)
+    wrapup();
+
+  return stringbuffer.data();
+}
+
+
+#endif
diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc
new file mode 100644 (file)
index 0000000..716e921
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "dnsproxy.hh"
+#include "ahuexception.hh"
+#include <sys/types.h>
+#include <errno.h>
+#include "dns.hh"
+#include "logger.hh"
+#include "statbag.hh"
+#include "packetcache.hh"
+
+extern StatBag S;
+extern PacketCache PC;
+
+DNSProxy::DNSProxy(const string &remote)
+{
+  ServiceTuple st;
+  st.port=53;
+  parseService(remote,st);
+
+  pthread_mutex_init(&d_lock,0);
+  d_resanswers=S.getPointer("recursing-answers");
+  d_resquestions=S.getPointer("recursing-questions");
+  d_udpanswers=S.getPointer("udp-answers");
+  if((d_sock=socket(AF_INET, SOCK_DGRAM,0))<0)
+    throw AhuException(string("socket: ")+strerror(errno));
+  struct sockaddr_in sin;
+  memset((char *)&sin, 0, sizeof(sin));
+  
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = INADDR_ANY;
+  int n=0;
+  for(;n<10;n++) {
+    sin.sin_port = htons(10000+( Utility::random()%50000));
+    
+    if(bind(d_sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 
+      break;
+  }
+  if(n==10) {
+    Utility::closesocket(d_sock);
+    d_sock=-1;
+    throw AhuException(string("binding dnsproxy socket: ")+strerror(errno));
+  }
+
+  struct sockaddr_in toaddr;
+  struct in_addr inp;
+  Utility::inet_aton(st.host.c_str(),&inp);
+  toaddr.sin_addr.s_addr=inp.s_addr;
+
+  toaddr.sin_port=htons(st.port);
+  toaddr.sin_family=AF_INET;
+
+  if(connect(d_sock, (sockaddr *)&toaddr, sizeof(toaddr))<0) 
+    throw AhuException("Unable to UDP connect to remote nameserver "+st.host+" ("+itoa(st.port)+"): "+stringerror());
+
+  d_xor=Utility::random()&0xffff;
+  L<<Logger::Error<<"DNS Proxy launched, local port "<<ntohs(sin.sin_port)<<", remote "<<st.host<<":"<<st.port<<endl;
+} 
+
+void DNSProxy::go()
+{
+  pthread_t tid;
+  pthread_create(&tid,0,&launchhelper,this);
+}
+
+
+void DNSProxy::onlyFrom(const string &ips)
+{
+  vector<string>parts;
+  stringtok(parts,ips,", \t");
+  for(vector<string>::const_iterator i=parts.begin();
+      i!=parts.end();++i)
+    d_ng.addMask(*i);
+  
+}
+
+/** returns false if p->remote is not allowed to recurse via us */
+bool DNSProxy::sendPacket(DNSPacket *p)
+{
+  if(!d_ng.empty() && !d_ng.match((struct sockaddr_in *)&p->remote))
+    return false;
+
+  int id;
+  {
+    Lock l(&d_lock);
+    id=getID_locked();
+
+    ConntrackEntry ce;
+    ce.id       = p->d.id;
+    memcpy((void *)&ce.remote,(void *)&p->remote, p->d_socklen);
+    ce.addrlen  = p->d_socklen;
+    ce.outsock  = p->getSocket();
+    ce.created  = time( NULL );
+
+    d_conntrack[id]=ce;
+  }
+  p->spoofID(id^d_xor);
+
+  char *buffer=const_cast<char *>(p->getRaw());
+  int len=p->len;
+  if(send(d_sock,buffer,len,0)<0) { // zoom
+    L<<Logger::Error<<"Unable to send a packet to our recursing backend: "<<stringerror()<<endl;
+  }
+  (*d_resquestions)++;
+  return true;
+
+}
+/** This finds us an unused or stale ID. Does not actually clean the contents */
+int DNSProxy::getID_locked()
+{
+  map_t::iterator i;
+  for(int n=0;;++n) {
+    i=d_conntrack.find(n);
+    if(i==d_conntrack.end()) {
+      return n;
+    }
+    else if(i->second.created<time(0)-60) {
+      if(i->second.created)
+       L<<Logger::Warning<<"Recursive query for remote "<<
+         sockAddrToString((struct sockaddr_in *)&i->second.remote, i->second.addrlen)<<" with internal id "<<n<<
+         " was not answered by backend within timeout, reusing id"<<endl;
+      
+      return n;
+    }
+  }
+}
+
+void DNSProxy::mainloop(void)
+{
+  try {
+    char buffer[1500];
+    int len;
+
+    for(;;) {
+      len=recv(d_sock, buffer, sizeof(buffer),0); // answer from our backend
+      if(len<12) {
+       if(len<0)
+         L<<Logger::Error<<"Error receiving packet from recursor backend: "<<stringerror()<<endl;
+       else if(len==0)
+         L<<Logger::Error<<"Error receiving packet from recursor backend, EOF"<<endl;
+       else
+         L<<Logger::Error<<"Short packet from recursor backend, "<<len<<" bytes"<<endl;
+       
+       continue;
+      }
+      (*d_resanswers)++;
+      (*d_udpanswers)++;
+      DNSPacket::dnsheader *d=reinterpret_cast<DNSPacket::dnsheader *>(buffer);
+      {
+       Lock l(&d_lock);
+       map_t::iterator i=d_conntrack.find(d->id^d_xor);
+       if(i==d_conntrack.end()) {
+         L<<Logger::Error<<"Discarding untracked packet from recursor backend with id "<<(d->id^d_xor)<<
+           ". Contrack table size="<<d_conntrack.size()<<endl;
+         continue;
+       }
+       else if(i->second.created==0) {
+         L<<Logger::Error<<"Received packet from recursor backend with id "<<(d->id^d_xor)<<" which is a duplicate"<<endl;
+         continue;
+       }
+       d->id=i->second.id;
+       sendto(i->second.outsock,buffer,len,0,(struct sockaddr*)&i->second.remote,i->second.addrlen);
+
+       DNSPacket p,q;
+       p.parse(buffer,len);
+       q.parse(buffer,len);
+
+       PC.insert(&q, &p);
+       i->second.created=0;
+      }
+    }
+  }
+  catch(AhuException &ae) {
+    L<<Logger::Error<<"Fatal error in DNS proxy: "<<ae.reason<<endl;
+  }
+  catch(exception &e) {
+    L<<Logger::Error<<"Communicator thread died because of STL error: "<<e.what()<<endl;
+  }
+  catch( ... )
+  {
+    L << Logger::Error << "Caught unknown exception." << endl;
+  }
+  L<<Logger::Error<<"Exiting because DNS proxy failed"<<endl;
+  exit(1);
+}
diff --git a/pdns/dnsproxy.hh b/pdns/dnsproxy.hh
new file mode 100644 (file)
index 0000000..244c2f4
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_DNSPROXY
+#define PDNS_DNSPROXY
+#include <pthread.h>
+#include <map>
+\r
+#ifndef WIN32\r
+# include <sys/socket.h>\r
+# include <netinet/in.h>\r
+# include <arpa/inet.h>\r
+#endif // WIN32\r
+\r
+#include "dnspacket.hh"
+#include "lock.hh"
+#include "iputils.hh"
+
+using namespace std;
+
+/**
+
+how will this work.
+
+This is a thread that just throws packets around. Should handle ~1000 packets/second.
+
+Consists of a thread receiving packets back from the backend and retransmitting them to the original client.
+
+Furthermore, it provides a member function that reports the packet to the connection tracker and actually sends it out. 
+
+The sending happens from a source port that is determined by the constructor, but IS random. Furthermore, the ID is XOR-ed with a random value
+to make sure outside parties can't spoof us.
+
+To fix: how to remove the stale entries that will surely accumulate
+*/
+
+class DNSProxy
+{
+public:
+  DNSProxy(const string &ip); //!< creates socket
+  void go(); //!< launches the actual thread
+  void onlyFrom(const string &ips); //!< Only these netmasks are allowed to recurse via us
+  bool sendPacket(DNSPacket *p);    //!< send out a packet and make a conntrack entry to we can send back the answer
+
+  void mainloop();                  //!< this is the main loop that receives reply packets and sends them out again
+  static void *launchhelper(void *p)
+  {
+    static_cast<DNSProxy *>(p)->mainloop();
+    return 0;
+  }
+
+private:
+  NetmaskGroup d_ng;
+  int d_sock;
+  int* d_resanswers;
+  int* d_udpanswers;
+  int* d_resquestions;
+  pthread_mutex_t d_lock;
+  u_int32_t d_xor;
+  int getID_locked();
+  struct ConntrackEntry
+  {
+    u_int16_t id;
+    struct sockaddr_in6 remote;
+    socklen_t addrlen;
+    int outsock;
+    time_t created;
+  };
+
+  typedef map<int,ConntrackEntry> map_t;
+  map_t d_conntrack;
+};
+
+#endif
diff --git a/pdns/docs/Makefile b/pdns/docs/Makefile
new file mode 100644 (file)
index 0000000..4353bdb
--- /dev/null
@@ -0,0 +1,23 @@
+# $Id: Makefile,v 1.1 2002/11/27 15:18:34 ahu Exp $ 
+
+all: pdns.txt pdns.pdf html/index.html html.tar.gz
+
+
+clean:
+       rm -rf *.dvi *.pdf *.tex *.toc *.aux *.txt *.ps *.bak *.tmp *~ *.log html
+
+html/index.html: pdns.sgml
+       db2html -o html $<
+
+html.tar.gz: html/index.html
+       tar czf html.tar.gz html/
+
+%.txt: %.sgml
+       docbook2txt $<
+
+%.pdf: %.sgml
+       docbook2pdf $<
+
+publish:
+       rsync --copy-links --delete -avrze ssh ./html pdns.txt pdns.pdf \
+       spoon.powerdns.com:/opt/websites/downloads.powerdns.com/www/documentation/
\ No newline at end of file
diff --git a/pdns/docs/gslb-operations.sgml b/pdns/docs/gslb-operations.sgml
new file mode 100644 (file)
index 0000000..e15e1fd
--- /dev/null
@@ -0,0 +1,99 @@
+<!doctype linuxdoc system>
+
+<article>
+
+<!-- Title information -->
+<title>The case for PowerDNS</title>
+<author>PowerDNS BV (bert hubert &lt;bert@trilab.com&gt;) &nl;
+Trilab BV</author>
+<date>v1.0 $Date: 2002/11/27 15:18:34 $</date>
+<abstract>
+This document describes what Global Server Load Balancing is, and how
+PowerDNS can be employed in a GSLB configuration
+</abstract>
+<toc>
+<sect>GSLB
+<p>
+GSLB, short for Global Server Load Balancing, isr the act of distributing
+server traffic to different locations. Although not necessary, this is
+almost always done using a smart nameserver.
+<sect1>Typical GSLB implementation
+<p>
+A user enters the name of a site ('www.thesite.com') in his or her browser.
+This causes the operating system, often Windows, to send out a request to
+the ISP of the user, asking for the IP address of www.thesite.com. If the
+nameserver of the ISP doesn't know this address, it asks the nameserver of
+thesite.com.
+<p>
+This nameserver then contains the GSLB smartness. Based on the IP Address of
+the nameserver of the ISP, it determines which of the 'www.thesite.com'
+servers is closest.
+
+A multitude of algoritms is in use for determining which server is closest.
+Some of them employ the Border Gateway Protocol, BGP, which is used for
+global internet routing. Some use 'ICMP Ping' measurements, some use
+modified DNS Queries. The simplest algorithm is to use IP Netmasks, which
+are an easy rule of thumb for determining who assigned an IP Address, which
+also gives it probable location.
+
+<sect>IP Netmasks and Location
+<p>
+IP Addresses are asigned by only a few entities worldwide, the foremost
+being ARIN, RIPE and APNIC, who respectively manage North- and South
+America, Europe and surrounding areas, and the Asian Pacific Region.
+
+This allows for coarse grained identification of location. While not very
+precise, it is very robust and guaranteed to work. It can be likened to a
+very good rule-of-thumb. Other methods employ complicated and fragile
+techniques for determining the 'internet distance' to a site.
+
+For example, ICMP Ping measurements are becoming less and less valid. The
+advent of Distributed Denial of Service attacks has lead many internet
+providers to block or limit these packets. The aforementioned BGP router
+protocol gives distance in 'AS Hops' which are no longer a valid measure of
+distance, as many Autonomous Subsystems now spread the globe.
+
+<sect1>IP Netmasks Configuration
+<p>
+PowerDNS comes preconfigured with a reasonable set of IP Rules. These may
+need some maintainance over time. It is adviseable to get a Subscription with
+PowerDNS so as to receive updates.
+
+These rules come in several levels. The lowest level is based on who
+assigned the IP Addresses, ARIN, RIPE or APNIC. The second level contains
+exceptions to these major rules. Change is expected especially in this
+second level.
+
+<sect>GSLB Concepts
+<p>
+A number of concepts are used in the PowerDNS GSLB configuration:
+
+<descrip>
+<tag>Netblock</tag>
+A netblock is a range of IP Addresses. A number of Netblocks together are
+grouped in a Region.
+<tag>Region</tag>
+A Region might be called 'ARIN' or 'Surfnet', and consists of a limited
+number of Netmasks.
+<tag>Target</tag>
+A Target describes a set of servers in a single location. Target names might
+be 'UUnet Amsterdam', 'Level3 Amsterdam' or 'Genuity'.
+<tag>Route</tag>
+A Route assigns a certain Region to a Target. A sample Route might be:
+Assign all ARIN IP Addresses to Genuity.
+<tag>Schema</tag>
+A set of Routes, Regions, Netblocks and Targets is called a Schema. Many
+different domains may be assigned to this Schema, which then only needs to
+be defined once.
+</descrip>
+
+<sect>DNS Configuration
+<p>
+In order to Load Balance a domain it must be pointed at the GSLB Schema.
+This is typically done using a DNS CNAME on the nameserver of the domain
+that needs to be balanced.
+
+In order for this to work, the Schema name must resolve to the IP Address of
+PowerDNS.
+</article>
+
diff --git a/pdns/docs/pdns.sgml b/pdns/docs/pdns.sgml
new file mode 100644 (file)
index 0000000..1b84a76
--- /dev/null
@@ -0,0 +1,6535 @@
+<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<Book>
+  
+  <BookInfo>
+    
+    <Title>PowerDNS manual</Title>
+    <AUTHOR>
+      <affiliation>
+        <orgname>PowerDNS BV</orgname>
+        <address>
+          <email>pdns@powerdns.com</email>
+        </address>
+       
+      </affiliation>
+    </author>
+    
+    <PubDate>v2.1 $Date: 2002/11/27 15:18:37 $</PubDate>
+    
+    <Abstract>
+       <para>  
+       <blockquote>
+         <LITERALLAYOUT>
+           It is a book about a Spanish guy called Manual. You should read it.
+              -- Dilbert
+         </LITERALLAYOUT>
+
+       </BLOCKQUOTE>
+      </para>
+    </Abstract>
+
+    
+  </BookInfo>
+  
+  <Chapter id="powerdns">
+    <Title>The PowerDNS dynamic nameserver</Title>
+
+    <Para>
+      The PowerDNS daemon is a versatile nameserver which supports a large number
+      of backends. These backends can either be <link linkend="bindbackend">plain zonefiles</link> or be 
+      <link linkend="pipebackend">more dynamic</link> in nature. 
+    </Para>
+    
+    <Para>
+      Prime examples of backends include relational databases, but also
+      loadbalancing and failover algorithms. 
+    </Para>
+    <para>
+      The company is called PowerDNS BV, the nameserver daemon is called PDNS.
+    </para>
+
+    <sect1 id="function-design"><title>Function &amp; design of PDNS</title>
+      <para>
+       PDNS is an authoritative only nameserver. It will answer questions about domains it knows about, 
+       but will not go out on the net to resolve queries about other domains. However, it can use a 
+       <link linkend="recursion">recursing backend</link> to provide that functionality.
+      </para>
+      <para>
+       When PDNS answers a question, it comes out of the database, and can be trusted as being authoritative. There is
+       no way to pollute the cache or to confuse the daemon. 
+      </para>
+      <para>
+       PDNS has been designed to serve both the needs of small installations by being easy to setup, as well as 
+       for serving very large query volumes on large numbers of domains.
+      </para>
+      <para>
+       Another prime goal is <link linkend="security">security</link>. By the use of language features, the PDNS source code 
+       is very small (in the order of  10.000 lines) which makes auditing easy. In the same way, library features have been used 
+       to mitigate the risks of buffer overflows.
+      </para>
+      <para>
+       Finally, PDNS is able to give a lot of <link linkend="monitoring">statistics</link> on its operation which is both helpful in 
+       determining the scalability of an installation as well as for spotting problems.
+      </para>
+    </sect1>
+    <sect1 id="about"><title>About this document</title>
+      <para>
+       If you are reading this document from disk, you may want to check <ulink url="http://doc.powerdns.com">http://doc.powerdns.com</ulink>
+       for updates. The PDF version is available on <ulink url="http://doc.powerdns.com/pdf">http://doc.powerdns.com/pdf</ulink>, a text file is
+       on <ulink url="http://doc.powerdns.com/txt">http://doc.powerdns.com/txt/</ulink>. 
+      </para>
+    <sect1 id="changelog">
+      <title>Release notes</title>
+      <para>
+       Before proceeding, it is advised to check the release notes for your PDNS version, as specified in the name of the distribution
+       file.
+      </para>
+      <sect2 id="changelog-2-8"><title>Version 2.8</title>     
+       <para>
+         From this release onwards, we'll concentrate on stabilising for the 3.0 release. So if you have any must-have features,
+         let us know soonest. The 2.8 release fixes a bunch of small stability issues and add two new features. In the spirit of the move to 
+         stability, this release has already been running 24 hours on our servers before release. 
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               pipe backend gains the ability to restricts its invocation to a limited number of requests. This allows a very busy nameserver
+               to still serve packets from a slow perl backend. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               pipe backend now honors query-logging, which also documents which queries were blocked by the regex.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               pipe backend now has its own backend chapter.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               An incoming AXFR timeout at the wrong moment had the ability to crash the binary, forcing a reload. Thanks to our bug spotting
+               champions Mike Benoit and Simon Kirby of NetNation for reporting this.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-7"><title>Version 2.7 and 2.7.1</title>   
+       <para>
+         This version fixes some very long standing issues and adds a few new features. If you are still running 2.6, upgrade yesterday. If you
+         were running 2.6.1, an upgrade is still strongly advised.
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               The controlsocket is now readable and writable by the 'setgid' user. This allows for non-root
+               access to PDNS which is nice for mrtg or cricket graphs.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               MySQL backend (the non-generic one) gains the ability to read from a different table using the
+               <command>mysql-table</command> setting.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               pipe backend now has a configurable timeout using the <command>pipe-timeout</command> setting. Thanks fo Steve Bromwich
+               for pointing out the need for this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Experimental backtraces. If PowerDNS crashes, it will log a lot of numbers and sometimes more to the syslog.
+               If you see these, please report them to us. Only available under Linux.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs:
+         <itemizedlist>
+           <listitem>
+             <para>
+               2.7 briefly broke the mysql backend, so don't use it if you use that. 2.7.1 fixes this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               SOA records could sometimes have the wrong TTL. Thanks to Jonas Daugaard for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               An ANY query might lead to duplicate SOA records being returned under exceptional circumstances. 
+               Thanks to Jonas Daugaard for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Underlying the above bug, packet compression could sometimes suddenly be turned off, leading to
+               overly large responses and non-removal of duplicate records.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               The <command>allow-axfr-ips</command> setting did not accept IP ranges (1.2.3.0/24) which the 
+               documentation claimed it did (thanks to Florus Both of Ascio technologies for being sufficiently persistent in reporting this).
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Killed backends were not being respawned, leading to suboptimal behaviour on intermittent database errors. Thanks to Steve Bromwich for
+               reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Corrupt packets during an incoming AXFR when acting as a slave would cause a PowerDNS reload instead of just failing that AXFR. 
+               Thanks to Mike Benoit and Simon Kirby of NetNation for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Label compression in incoming AXFR had problems with large offsets, causing the above mentioned errors. Thanks to Mike Benoit
+               and Simon Kirby of NetNation for reporting this.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+             
+      <sect2 id="changelog-2-6-1"><title>Version 2.6.1</title> 
+       <para>
+         Quick fix release for a big cache problem. 
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-6"><title>Version 2.6</title>
+       <para>
+         Performance release. A lot of work has been done to raise PDNS performance to staggering levels in order to take part
+         in benchmarketing efforts. Together with our as yet unnamed partner, PDNS has been benchmarked at 60.000 mostly cached queries/second
+         on off the shelf PC hardware. Uncached performance was 17.000 uncached DNS queries/second on the .ORG domain.
+       </para>
+       <para>
+         Performance has been increased by both making PDNS itself quicker but also by lowering the number of backend queries typically needed. Operators
+         will typically see PDNS taking less CPU and the backend seeing less load.
+       </para>
+       <para>
+         Furthermore, some real bugs were fixed. A couple of undocumented performance switches may appear in --help output but you are advised to stay
+         away from these.
+       </para>
+       <para>
+         Developers: this version needs the pdns-2.5.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         Performance:
+         <itemizedlist>
+           <listitem>
+             <para>
+               A big error in latency calculations - cached packets were weighed 50 times less, leading to inflated latency reporting. Latency calculations
+               are now correct and way lower - often in the microseconds range.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               It is now possible to run with 0 second cache TTLs. This used to cause very frequent cache cleanups, leading
+               to performance degradation.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Many tiny performance improvements, removing duplicate cache key calculations, etc. The cache itself has also been reworked 
+               to be more efficient.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               First 'CNAME' backend query replaced by an 'ANY' query, which most of the time returns the actual record,
+               preventing the need for a separate CNAME lookup, halving query load.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Much of the same for same-level-NS records on queries needing delegation.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Incidentally, the cache count would show 'unknown' packets, which was harmless but confusing. Thanks to Mike and Simon of
+               NetNation for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               SOA hostmaster with a . in the local-part would be cached wrongly, leading to a stray backslash
+               in case of multiple successively SOA queries. Thanks to Ascio Techologies for spotting this bug.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql did not parse Verisign zonefiles correctly as these contained a $TTL statement in mid-record.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Sometimes packets would not be accounted, leading to 'udp-queries' and 'udp-answers' divergence.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               'cricket' command added to init.d scripts that provides unadorned output for parsing by 'Cricket'.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-5-1"><title>Version 2.5.1</title>
+       <para>
+         <ulink url="http://www.tuxedo.org/~esr/jargon/html/entry/brown-paper-bag-bug.html">Brown paper bag</ulink> release fixing 
+           a huge memory leak in the new Query Cache.
+       </para>
+       <para>
+         Developers: this version needs the new pdns-2.5.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         And some small changes:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Added support for RFC2038 compliant negative-answer caching. This allows remotes to cache the fact that 
+               a domain does not exist and will not exist for a while. Thanks to Chris Thompson for <ulink url="http://ops.ietf.org/lists/namedroppers/namedroppers.2002/msg01697.html">pointing out how tiny our minds are</ulink>. This feature may cause a noticeable reduction
+               in query load.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Small speedup to non-packet-cached queries, incidentally fixing the huge memory leak.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>pdns_control ccounts</command> command outputs statistics on what is in the cache, which is
+               useful to help optimize your caching strategy.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-5"><title>Version 2.5</title>
+       <para>
+         An important release which has seen quite a lot of trial and error testing. As a result, PDNS can now run with a huge cache
+         and concurrent invalidations. This is useful when running of a slower database or under high traffic load with a fast database.
+       </para>
+       <para>
+         Furthermore, the gpgsql2 backend has been validated for use and will soon supplant the gpgsql backend entirely. This also bodes 
+         well for the gmysql backend which is the same code.
+       </para>
+       <para>
+         Also, a large amount of issues biting large scale slave operators were addressed. Most of these issues would only show up 
+         after prolonged uptime.
+       </para>
+       <para>
+         New features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Query cache. The old Packet Cache only cached entire questions and their answers. This is very CPU efficient but
+               does not lead to maximum hitrate. Two packets both needing to resolve smtp.you.com internally would not benefit 
+               from any caching. Furthermore, many different DNS queries lead to the same backend queries, like 'SOA for .COM?'.
+             </para>
+             <para>
+               PDNS now also caches backend queries, but only those having no answer (the majority) and those having one answer 
+               (almost the rest). 
+             </para>
+             <para>
+               In tests, these additional caches appear to halve the database backend load numerically and perhaps even more in terms
+               of CPU load. Often, queries with no answer are more expensive than those having one.
+             </para>
+             <para>
+               The default <command>ttl</command>s for the query-cache and negquery-cache are set to safe values (20 and 60 seconds
+               respectively), you should be seeing an improvement in behaviour without sacrificing a lot in terms of quick updates.
+             </para>
+             <para>
+               The webserver also displays the efficiency of the new Query Cache.
+             </para>
+             <para>
+               The old Packet Cache is still there (and useful) but see <xref linkend="performance"> for more details.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               There is now the ability to shut off some logging at a very early stage. High performance sites doing thousands of 
+               queries/second may in fact spend most of their CPU time on attempting to write out logging, even though it is ignored
+               by syslog. The new flag <command>log-dns-details</command>, on by default, allows the operator to kill most 
+               informative-only logging before it takes any cpu.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Flags which can be switched 'on' and 'off' can now also be set to 'off' instead of only to 'no' to turn them off.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Packet Cache is now case insensitive, leading to a higher hitrate because identical queries only differing in case
+               now both match. Care is taken to restore the proper case in the answer sent out.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Packet Cache stores packets more efficiently now, savings are estimated at 50%. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               The Packet Cache is now asynchronous which means that PDNS continues to answer questions while the cache
+               is busy being purged or queried. Incidentally this will mean a cache miss where previously the question would
+               wait until the cache became available again. 
+             </para>
+             <para>
+               The upshot of this is that operators can call <command>pdns_control purge</command> as often as desired without
+               fearing performance loss. Especially the full, non-specific, purge was speeded up tremendously. 
+             </para>
+             <para>
+               This optimization is of little merit for small sites but is very important when running with a large packetcache, such
+               as when using recursion under high load.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               AXFR log messages now all contain the word 'AXFR' to ease grepping.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Linux static version now compiled with gcc 3.2 which is known to output better and faster code than the previously
+               used 3.0.4.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Packetcache would sometimes send packets back with slightly modified flags if these differed from the flags
+               of the cached copy.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Resolver code did bad things with filedescriptors leading to fd exhaustion after prolonged uptimes and many slave
+               SOA currency checks. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Resolver code failed to properly log some errors, leading to operator uncertainty regarding to AXFR problems with
+               remote masters.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               After prolonged uptime, slave code would try to use privileged ports for originating queries, leading to bad
+               replication efficiency.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Masters sending back answers in differing case from questions would lead to bogus 
+               'Master tried to sneak in out-of-zone data' errors and failing AXFRs.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-4"><title>Version 2.4</title>
+       <para>
+         Developers: this version is compatible with the pdns-2.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         This version fixes some stability issues with malformed or malcrafted packets. An upgrade is advised. Furthermore, there are interesting new 
+         features.
+       </para>
+       <para>
+         New features:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               Recursive queries are now also cached, but in a separate namespace so non-recursive queries don't get recursed answers and
+               vice versa. This should mean way lower database load for sites running with the current default lazy-recursion. Up to now,
+               each and every recursive query would lead to a large amount of SQL queries.
+             </para>
+             <para>
+               To prevent the packetcache from becoming huge, a separate <command>recursive-cache-ttl</command> can be specified.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               The ability to change parameters at runtime was added. Currently, only the new <command>query-logging</command> flag
+               can be changed.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Added <command>query-logging</command> flag which hints a backend that it should output a textual representation of queries
+               it receives. Currently only gmysql and gpgsql2 honor this flag.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Gmysql backend can now also talk to PgSQL, leading to less code. Currently, the old postgresql driver ('gpgsql') is still the default,
+               the new driver is available as 'gpgsql2' and has the benefit that it does query logging. In the future, gpgsql2 will become the default
+               gpgsql driver.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               DNS recursing proxy is now more verbose in logging odd events which may be caused by buggy recursing backends.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Webserver now displays peak queries/second 1 minute average.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Failure to connect to database in master/slave communicator thread could lead to an unclean reload, fixed.
+             </para>
+           </listitem>
+         </itemizedlist>
+       <para>
+         Documentation: added details for <command>strict-rfc-axfrs</command>. This feature can be used if very old clients need to be able
+         to do zone transfers with PDNS. Very slow.
+       </para>
+       
+      </sect2>
+      <sect2 id="changelog-2-3"><title>Version 2.3</title>
+       <para>
+         Developers: this version is compatible with the pdns-2.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         This release adds the Generic MySQL backend which allows full master/slave semantics with MySQL and InnoDB tables (or other tables that support
+         transactions). See <xref linkend="generic-mypgsql-backends">.
+       </para>
+       <para>
+         Other new features:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               Improved error messages in master/slave communicator will help down track problems.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>slave-cycle-interval</command> setting added. Very large sites with thousands of slave domains may need to raise this value
+               above the default of 60. Every cycle, domains in undeterminate state are checked for their condition. Depending on the health of the masters,
+               this may entail many SOA queries or attempted AXFRs.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               'pdns_control purge <userinput>domain</userinput>' and  'pdns_control purge <userinput>domain$</userinput>' were broken in version 2.2 and 
+               did not in fact purge the cache. There is a slight risk that domain-specific purge commands could force a reload in previous version.
+               Thanks to Mike Benoit of NetNation for discovering this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Master/slave communicator thread got confused in case of delayed answers from slow masters. While not causing harm, this caused inefficient 
+               behaviour when testing large amounts of slave domains because additional 'cycles' had to pass before all domains would have their status
+               ascertained. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Backends implementing special SOA semantics (currently only the undocumented 'pdns express backend', or homegrown backends) would 
+               under some circumstances not answer the SOA record in case of an ANY query. This should put an end to the last DENIC problems. Thanks to
+               DENIC for helping us find the problem.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-2"><title>Version 2.2</title>
+       <para>
+         Developers: this version is compatible with the pdns-2.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         Again a big release. PowerDNS is seeing some larger deployments in more demanding environments and these are helping shake out remaining issues,
+         especially with recursing backends.
+       </para>
+       <para>
+         The big news is that wildcard CNAMEs are now supported, an oft requested feature and nearly the only part in which PDNS differed from BIND in 
+         authoritative capabilities.
+       </para>
+       <para>
+         If you were seeing signal 6 errors in PDNS causing reloads and intermittent service disruptions, please upgrade to this version.
+       </para>
+       <para>
+         For operators of PowerDNS Express trying to host .DE domains, the very special <command>soa-serial-offset</command> feature has been added
+         to placate the new DENIC requirement that the SOA serial be at least six digits. PowerDNS Express uses the SOA serial as an actual serial and 
+         not to insert dates and hence often has single digit soa serial numbers, causing big problems with .DE redelegations.
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Malformed or shortened TCP recursion queries would cause a signal 6 and a reload. Same for EOF from the TCP recursing backend.
+               Thanks to Simon Kirby and Mike Benoit of NetNation for helping debug this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Timeouts on the TCP recursing backend were far too long, leading to possible exhaustion of TCP resolving threads.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>pdns_control purge domain</command> accidentally cleaned all packets with that name as a prefix. Thanks to Simon Kirby 
+               for spotting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Improved exception error logging - in some circumstances PDNS would not properly log the cause of an exception, which hampered problem
+               resolution.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para> 
+       <para>
+         New features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Wildcard CNAMEs now work as expected!
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>pdns_control purge</command> can now also purge based on suffix, allowing operators to 
+               purge an entire domain from the packet cache instead of only specific records. See also <xref linkend="pdnscontrol">
+               Thanks to Mike Benoit for this suggestion. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>soa-serial-offset</command> for installations with small SOA serial numbers wishing to register .DE domains
+               with DENIC which demands six-figure SOA serial numbers. See also <xref linkend="all-settings">.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-1"><title>Version 2.1</title>
+       <para>
+         This is a somewhat bigger release due to pressing demands from customers. An upgrade is advised for installations using Recursion. 
+         If you are using recursion, it is vital that you are aware of changes in semantics. Basically, local data will now override data in your
+         recursing backend under most circumstances. Old behaviour can be restored by turning <command>lazy-recursion</command> off.
+       </para>
+       <para>
+         Developers: this version has a new pdns-2.1 development kit, available on <ulink url="http://downloads.powerdns.com/releases/dev">
+           http://downloads.powerdns.com/releases/dev</ulink>. See also <xref linkend="backend-writers-guide">.
+       </para>
+       <para>
+         <warning>
+           <para>
+             Most users will run a static version of PDNS which has no dependencies on external libraries. However, some may need to run the dynamic version.
+             This warning applies to these users.
+           </para>
+           <para>
+             To run the dynamic version of PDNS, which is needed for backend drivers which are only available in source form, gcc 3.0 is required.
+             RedHat 7.2 comes with gcc 3.0 as an optional component, RedHat 7.3 does not. However, the RedHat 7.2 Update gcc rpms install just fine
+             on RedHat 7.3. For Debian, we suggest running 'woody' and installing the g++-3.0 package. We expect to release a FreeBSD dynamic version
+             shortly.
+           </para>
+         </warning>
+       </para>
+             
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               RPM releases sometimes overwrote previous configuration files. Thanks to Jorn Ekkelenkamp of Hubris/ISP Services for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               TCP recursion sent out overly large responses due to a byteorder mistake, confusing some clients.  Thanks to the capable engineers 
+               of NetNation for bringing this to our attention.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               TCP recursion in combination with a recursing backend on a non-standard port did not work, leading to a
+               non-functioning TCP listener. Thanks to the capable engineers of NetNation for bringing this to our attention.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Unexpected behaviour:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Wildcard URL records where not implemented because they are a performance penalty. To turn these on, enable 
+               <command>wildcard-url</command> in the configuration.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Unlike other nameservers, local data did not override the internet for recursing queries. This has mostly been brought into conformance
+               with user expectations. If a recursive question can be answered entirely from local data, it is. To restore old behaviour, disable
+               <command>lazy-recursion</command>. Also see <xref linkend="recursion">.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Oracle support has been tuned, leading to the first public release of the Oracle backend. Zone2sql now outputs better SQL
+               and the backend is now fully documented. Furthermore, the queries are compatible with the PowerDNS XML-RPC product, allowing 
+               PowerDNS express to run off Oracle. See <xref linkend="oracle">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql now accepts --transactions to wrap zones in a transaction for PostgreSQL and Oracle output. This is a major speedup and also
+               makes for better isolation of inserts. See <xref linkend="zone2sql">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>pdns_control</command> now has the ability to purge the PowerDNS cache or parts of it. This enables operators to 
+               raise the TTL of the Packet Cache to huge values and only to invalidate the cache when changes are made. See also <xref linkend="performance"> and
+               <xref linkend="pdnscontrol">.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-0-1"><title>Version 2.0.1</title>
+       <para>
+         Maintenance release, fixing three small issues.
+       </para>
+       <para>
+         Developers: this version is compatible with 1.99.11 backends.
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               PowerDNS ignored the <command>logging-facility</command> setting unless it was specified on the commandline. 
+               Thanks to Karl Obermayer from WebMachine Technologies for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql neglected to preserve 'slaveness' of domains when converting to the slave capable PostgreSQL backend. Thanks
+               to Mike Benoit of NetNation for reporting this. Zone2sql now has a <command>--slave</command> option.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               SOA Hostmaster addresses with dots in them before the @-sign were mis-encoded on the wire.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-0"><title>Version 2.0</title>
+       <para>
+         Two bugfixes, one stability/security related. No new features.
+       </para>
+       <para>
+         Developers: this version is compatible with 1.99.11 backends.
+       </para>
+       <para>
+         Bugfixes:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               zone2sql refused to work under some circumstances, taking 100% cpu and not functioning. Thanks to Andrew Clark and Mike Benoit 
+               for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Fixed a stability issue where malformed packets could force PDNS to reload. Present in all earlier 2.0 versions.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-0-rc2"><title>Version 2.0 Release Candidate 2</title>
+       <para>
+         Mostly bugfixes, no really new features.
+       </para>
+       <para>
+         Developers: this version is compatible with 1.99.11 backends.
+       </para>
+       <para>
+         Bugs fixed:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               chroot() works again - 2.0rc1 silently refused to chroot. Thanks to Hub Dohmen for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               setuid() and setgid() security features were silently not being performed in 2.0rc1. Thanks to Hub Dohmen for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               MX preferences over 255 now work as intended. Thanks to Jeff Crowe for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               IPv6 clients can now also benefit from the recursing backend feature. Thanks to Andy Furnell for proving beyond any doubt that this
+               did not work.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Extremely bogus code removed from DNS notification reception code - please test! Thanks to Jakub Jermar for working with us
+               in figuring out just how broken this was.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               AXFR code improved to handle more of the myriad different zonetransfer dialects available. Specifically, interoperability 
+               with Bind 4 was improved, as well as Bind 8 in 'strict rfc conformance' mode. Thanks again for Jakub Jermar for running many tests for us.
+               If your transfers failed with 'Unknown type 14!!' or words to that effect, this was it.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Win32 version now has a zone2sql tool.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Win32 version now has support for specifying how urgent messages should be before they go to the NT event log.
+             </para>     
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Remaining issues:
+         <itemizedlist>
+           <listitem>
+             <para>
+               One persistent report of the default 'chroot=./' configuration not working.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               One report of disable-axfr and allow-axfr-ips not working as intended.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Support for relative paths in zones and in Bind configuration is not bug-for-bug compatible with bind yet.
+             </para>     
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-2-0-rc1"><title>Version 2.0 Release Candidate 1</title>
+       <para>
+         The MacOS X release! A very experimental OS X 10.2 build has been added. Furthermore, the Windows version is now in line with Unix with 
+         respect to capabilities. The ODBC backend now has the code to function as both a master and a slave.
+       </para>
+       <para>
+         Developers: this version is compatible with 1.99.11 backends.
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               Implemented native packet response parsing code, allowing Windows to perform AXFR and NS and SOA queries.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               This is the first version for which we have added support for Darwin 6.0, which is part of the forthcoming Mac OS X 10.2. 
+               Please note that although this version is marked RC1, that we have not done extensive testing yet. Consider this a technology 
+               preview.                                
+             </para>
+             <para>
+               <itemizedlist>
+                 <listitem><para>
+                     The Darwin version has been developed on Mac OS X 10.2 (6C35). Other versions may or may not work. 
+                   </para></listitem>
+                 <listitem><para>
+                     Currently only the random, bind, mysql and pdns backends are included.
+                   </para></listitem>
+
+                 <listitem><para>
+                     The menu based installer script does not work, you will have to edit         pathconfig by hand as outlined in chapter 2.
+                   </para></listitem>
+
+                 <listitem><para>
+                     On Mac OS X Client, PDNS will fail to start because a system service         is already bound to port 53. 
+                   </para></listitem>
+               </itemizedlist>
+             </para>
+             <para>
+               This version is distributed as a compressed tar file. You should follow the generic UNIX installation instructions. 
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Zone2sql PostgreSQL mode neglected to lowercase $ORIGIN. Thanks to Maikel Verheijen of Ladot for spotting this.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql PostgreSQL mode neglected to remove a trailing dot from $ORIGIN if present. 
+               Thanks to Thanks to Maikel Verheijen of Ladot for spotting this.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Zonefile parser was not compatible with bind when $INCLUDING non-absolute filenames. Thanks to Jeff Miller for working out 
+               how this should work. 
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Bind configuration parser was not compatible with bind when including non-absolute filenames. Thanks to Jeff Miller for working out 
+               how this should work. 
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Documentation incorrectly listed the Bind backend as 'slave capable'. This is not yet true, now labeled 'experimental'.
+             </para>     
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Windows changes. We are indebted to Dimitry Andric who educated us in the ways of distributing Windows software.
+         <itemizedlist>
+           <listitem>
+             <para>
+               <filename>pdns.conf</filename> is now read if available.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Console version responds to ^c now.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Default pdns.conf added to distribution
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Uninstaller missed several files, leaving remnants behind
+             </para>     
+           </listitem>
+
+           <listitem>
+             <para>
+               DLLs are now installed locally, with the pdns executable.
+             </para>     
+           </listitem>
+
+           <listitem>
+             <para>
+               pdns_control is now also available on Windows
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               ODBC backend can now act as master and slave. Experimental.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               The example zone missed indexes and had other faults. 
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               A runtime DLL that is present on most windows systems (but not all!) was missing.
+             </para>     
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-1-99-12"><title>Version 1.99.12 Prerelease</title>
+       <para>
+         The Windows release! See <xref linkend="windows">. Beware, windows support is still very fresh and untested. Feedback is very welcome.
+       </para>
+       <para>
+         Developers: this version is compatible with 1.99.11 backends.
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               Windows 2000 codebase merge completed. This resulted in quite some changes on the Unix end of things, so this may impact reliability
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               ODBC backend added for Windows. See <xref linkend="odbc">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               IBM DB2 Universal Database backend available for Linux. See <xref linkend="db2">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql now understands $INCLUDE. Thanks to Amaze Internet for nagging about this
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               The SOA Mininum TTL now has a configurable default (<command>soa-minimum-ttl</command>)value to placate the DENIC requirements.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Added a limit on the simultaneous numbers of TCP connections to accept (<command>max-tcp-connections</command>). Defaults to 10. 
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               When operating in virtual hosting mode (See <xref linkend="virtual">), the additional init.d scripts would not function correctly
+               and interface with other pdns instances.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               PDNS neglected to conserve case on answers. So a query for WwW.PoWeRdNs.CoM would get an answer listing the address of www.powerdns.com. 
+               While this did not confuse resolvers, it is better to conserve case. This has semantical concequences for all backends, which the documentation
+               now spells out.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               PostgreSQL backend was case sensitive and returned only answers in case an exact match was found. The Generic PostgreSQL backend is now 
+               officially all lower case and zone2sql in PostgreSQL mode enforces this.
+               Documentation has been been updated to reflect the case change. Thanks to Maikel Verheijen of Ladot for 
+               spotting this!
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               Documentation bug - postgresql create/index statements created a duplicate index. If you've previously copy pasted the commands and
+               not noticed the error, execute <command>CREATE INDEX rec_name_index ON records(name)</command> to remedy. Thanks to Jeff Miller for reporting 
+               this. This also lead to depressingly slow 'ANY' lookups for those of you doing benchmarks.
+             </para>     
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               pdns_control (see <xref linkend="pdnscontrol">) now opens the local end of its socket in <filename>/tmp</filename> instead of next to the
+               remote socket (by default <filename>/var/run</filename>). This eases the way for allowing non-root access to pdns_control. When running chrooted 
+               (see <xref linkend="security">), the local socket again moves back to <filename>/var/run</filename>.
+             </para>     
+           </listitem>
+           <listitem>
+             <para>
+               pdns_control now has a 'version' command. See <xref linkend="pdnscontrol">.
+             </para>     
+           </listitem>
+         </itemizedlist>
+
+      </sect2>
+      <sect2 id="changelog-1-99-11"><title>Version 1.99.11 Prerelease</title>
+       <para>
+         This release is important because it is the first release which is accompanied by an Open Source Backend Development Kit, allowing external 
+         developers to write backends for PDNS. Furthermore, a few bugs have been fixed:
+       </para>
+       <para>
+         <itemizedlist>
+           <listitem>
+             <para>
+               Lines with only whitespace in zone files confused PDNS (thanks Henk Wevers)
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               PDNS did not properly parse TTLs with symbolic sufixes in zone files, ie 2H instead of 7200 (thanks Henk Wevers)
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-1-99-10"><title>Version 1.99.10 Prerelease</title>
+       <para>
+         IMPORTANT: there has been a tiny license change involving free public webbased dns hosting, check out the changes before deploying!
+       </para>
+       <para>
+         PDNS is now feature complete, or very nearly so. Besides adding features, a lot of 'fleshing out' work is done now. There is an important
+         performance bug fix which may have lead to disappointing benchmarks - so if you saw any of that, please try either this version or 1.99.8 which 
+         also does not have the bug.
+       </para>
+       <para>
+         This version has been very stable for us on multiple hosts, as was 1.99.9.
+       </para>
+       <para>
+         PostgreSQL users should be aware that while 1.99.10 works with the schema as presented in earlier versions, advanced features
+         such as master or slave support will not work unless you create the new 'domains' table as well.
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Wildcard AAAA queries sometimes received an NXDOMAIN error where they should have gotten an empty NO ERROR. Thanks to Jeroen Massar
+               for spotting this on the .TK TLD!
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Do not disable the packetcache for 'recursion desired' packets unless a recursor was configured. Thanks to Greg Schueler for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               A failing backend would not be reinstated. Thanks to 'Webspider' for discovering this problem with PostgreSQL connections that die after
+               prolonged inactivity.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Fixed loads of IPv6 transport problems. Thanks to Marco Davids and others for testing. Considered ready for production now.
+             </para>
+           </listitem>
+
+           <listitem>
+             <para>
+               <command>Zone2sql</command> printed a debugging statement on range $GENERATE commands. Thanks to Rene van Valkenburg for spotting this.
+             </para>
+         </listitem>
+       </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               PDNS can now act as a master, sending out notifications in case of changes and allowing slaves to AXFR. Big rewording of replication support,
+               domains are now either 'native', 'master' or 'slave'. See <xref linkend="replication"> for lots of details.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>Zone2sql</command> in PostgreSQL mode now populates the 'domains' table for easy master, slave or native replication support.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Ability to disable those annoying Windows DNS Dynamic Update messages from appearing in the log. See <function>log-failed-updates</function>
+               in <xref linkend="all-settings">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Ability to run on IPv6 transport only
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Logging can now happen under a 'facility' so all PDNS messages appear in their own file. See <xref linkend="syslog">.
+             </para>
+           </listitem>
+
+           <listitem>
+             <para>
+               Different OS releases of PDNS now get different install path defaults. Thanks to Mark Lastdrager for nagging about this and to Nero Imhard and
+               Frederique Rijsdijk for suggesting saner defaults.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Infrastructure for 'also-notify' statements added.
+             </para>
+           </listitem>
+
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-1-99-9"><title>Version 1.99.9 Early Access Prerelease</title>
+       <para>
+         This is again a feature and an infrastructure release. We are nearly feature complete and will soon start
+         work on the backends to make sure that they are all master, slave and 'superslave' capable.
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               PDNS sometimes sent out duplicate replies for packets passed to the recursing backend. Mostly a problem on SMP systems. Thanks to Mike Benoit
+               for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Out-of-bailiwick CNAMES (ie, a CNAME to a domain not in PDNS) caused a 'ServFail' packet in 1.99.8, indicating failure, leading to hosts not 
+               resolving. Thanks to Martin Gillstrom for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql balked at zones editted under operating sytems terminating files with ^Z (Windows). Thanks Brian Willcott for reporting this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               PostgreSQL backend logged the password used to connect. Now only does so in case of failure to connect. Thanks to 'Webspider' for noticing this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Debian unstable distribution wrongly depended on home compiled PostgreSQL libraries. Thanks to Konrad Wojas for noticing this.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Features:
+         <itemizedlist>
+           <listitem>
+             <para>
+               When operating as a slave, AAAA records are now supported in the zone. They were already supported in master zones.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               IPv6 transport support - PDNS can now listen on an IPv6 socket using the <command>local-ipv6</command> setting.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Very silly randombackend added which appears in the documentation as a sample backend. See <xref linkend="backend-writers-guide">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               When transferring a slave zone from a master, out of zone data is now rejected. Malicious operators might try to insert bad records otherwise.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               'Supermaster' support for automatic provisioning from masters. See <xref linkend="supermaster">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Recursing backend can now live on a non-standard (!=53) port. See <xref linkend="recursion">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Slave zone retrieval is now queued instead of immediate, which scales better and is more resilient to temporary failures.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <command>max-queue-length</command> parameter. If this many packets are queued for database attention, consider the situation hopeless and 
+               respawn.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Internal:
+         <itemizedlist>
+           <listitem>
+             <para>
+               SOA records are now 'special' and each backend can optionally generate them in special ways. PostgreSQL backend does so 
+               when operating as a slave.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Writing backends is now a lot easier. See <xref linkend="backend-writers-guide">.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Added Bindbackend to internal regression tests, confirming that it is compliant.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+      <sect2 id="changelog-1-99-8"><title>Version 1.99.8 Early Access Prerelease</title>
+       <para>
+         A lot of infrastructure work gearing up to 2.0. Some stability bugs fixed and a lot of new features.
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Bindbackend was overly complex and crashed on some systems on startup. Simplified launch code.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               SOA fields were not always properly filled in, causing default values to go out on the wire
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Obscure bug triggered by malicious packets (we know who you are) in SOA finding code fixed.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Magic serial number calculation contained a double free leading to instability.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Standards violation, questions for domains for which PDNS was unauthoritative now get a SERVFAIL answer. 
+               Thanks to the IETF Namedroppers list for helping out with this.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Slowly launching backends were being relaunched at a great rate when queries were coming in while launching backends.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               MySQL-on-unix-domain-socket on SMP systems was overwhelmed by the quick connection rate on launch, inserted a small 50ms delay. 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Some SMP problems appear to be compiler related. Shifted to GCC 3.0.4 for Linux.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Ran ispell on documentation.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Recursing backend. See <xref linkend="recursion">. Allows recursive and authoritative DNS on the same IP address.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               <link linkend="naptr">NAPTR support</link>, which is especially useful for the ENUM/E.164 community.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone transfers can now be allowed per <link linkend="allow-axfr-ips">netmask instead of only per IP address</link>.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Preliminary support for slave operation included. Only for the adventurous right now! See <xref linkend="slave"> 
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               All record types now documented, see <xref linkend="types">.
+             </para>
+           </listitem>
+          </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           Wildcard CNAMES do not work as they do with bind.
+         </para>
+         <para>
+           Recursion sometimes sends out duplicate packets (fixed in 1.99.9 snapshots)
+         </para>
+         <para>
+           Some stability issues which are caught by the guardian
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+         </para>
+       </sect3>
+
+      </sect2>
+      <sect2 id="changelog-1-99-7"><title>Version 1.99.7 Early Access Prerelease</title>
+       <para>
+         Named.conf parsing got a lot of work and many more bind configurations can now be parsed. Furthermore, error reporting was improved.
+         Stability is looking good.
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Bind parser got confused by filenames with underscores and colons.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               Bind parser got confused by spaces in quoted names
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               FreeBSD version now stops and starts when instructed to do so.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               Wildcards were off by default, which violates standards. Now on by default.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               --oracle was broken in zone2sql
+             </para
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Line number counting goes on as it should when including files in named.conf
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Added --no-config to enable users to start the pdns daemon without parsing the configuration file.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql now has --bare for unformatted output which can be used to generate insert statements for different database layouts
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql now has --gpgsql, which is an alias for --mysql, to output in a format useful for the default Generic PgSQL backend
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql is now documented.
+             </para>
+           </listitem>
+          </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           Wildcard CNAMES do not work as they do with bind.
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+         </para>
+       </sect3>
+
+      </sect2>
+      <sect2><title>Version 1.99.6 Early Access Prerelease</title>
+       <para>
+         This version is now running on dns-eu1.powerdns.net and working very well for us. But please remain cautious before 
+         deploying!
+       </para>
+       <para>
+         Bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Webserver neglected to show log messages
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               TCP question/answer miscounted multiple questions over one socket. Fixed misnaming of counter
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               Packetcache now detects clock skew and times out entries
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               named.conf parser now reports errors with line number and offending token
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Filenames in named.conf can now contain :
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               The webserver now by default does not print out configuration statements, which might contain database backends. Use 
+               <command>webserver-print-arguments</command> to restore the old behaviour.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Generic PostgreSQL backend is now included. Still rather beta.
+             </para>
+           </listitem>
+          </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           FreeBSD version does not stop when requested to do so.
+         </para>
+         <para>
+           Wildcard CNAMES do not work as they do with bind.
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+         </para>
+       </sect3>
+
+      </sect2>
+      <sect2><title>Version 1.99.5 Early Access Prerelease</title>
+       <para>
+          The main focus of this release is stability and TCP improvements. This is the first release PowerDNS-the-company actually considers for running
+          on its production servers!
+       </para>
+       <para>
+         Major bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+                Zone2sql received a floating point division by zero error on named.confs with less than 100 domains.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+                Huffman encoder failed without specific error on illegal characters in a domain
+             </para
+           </listitem>
+           <listitem>
+             <para>
+                Fixed huge memory leaks in TCP code.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+                Removed further file descriptor leaks in guardian respawning code
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+                Pipebackend was too chatty.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+                pdns_server neglected to close fds 0, 1 &amp; 2 when daemonizing
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+                bindbackend can be instructed not to check the ctime of a zone by specifying <command>bind-check-interval=0</command>,
+                which is also the new default.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+                <command>pdns_server --list-modules</command> lists all available modules.
+             </para>
+           </listitem>
+          </itemizedlist>
+       </para>
+       <para>
+         Performance enhancements:
+       <itemizedlist>
+           <listitem>
+             <para>
+                TCP code now only creates a new database connection for AXFR.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+                TCP connections timeout rather quickly now, leading to less load on the server.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           FreeBSD version does not stop when requested to do so.
+         </para>
+         <para>
+           Wildcard CNAMES do not work as they do with bind.
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend, gpgsqlbackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+         </para>
+       </sect3>
+
+      </sect2>
+      <sect2><title>Version 1.99.4 Early Access Prerelease</title>
+       <para>
+         A lot of new named.confs can now be parsed, zone2sql &amp; bindbackend have gained features and stability.
+       </para>
+       <para>
+         Major bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Label compression was not always enabled, leading to large reply packets sometimes.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               Database errors on TCP server lead to a nameserver reload by the guardian.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               MySQL backend neglected to close its connection properly.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               BindParser miss parsed some IP addresses and netmasks.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Truncated answers were also truncated on the packetcache, leading to truncated TCP answers.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Zone2sql and the bindbackend now understand the Bind $GENERATE{} syntax.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql can optionally gloss over non-existing zones with <command>--on-error-resume-next</command>.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql and the bindbackend now properly expand @ also on the right hand side of records.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Zone2sql now sets a default TTL.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               DNS UPDATEs and NOTIFYs are now logged properly and sent the right responses.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Performance enhancements:
+       <itemizedlist>
+           <listitem>
+             <para>
+               'Fancy records' are no longer queried for on ANY queries - this is a big speedup.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           FreeBSD version does not stop when requested to do so.
+         </para>
+         <para>
+           Zone2sql refuses named.confs with less than 100 domains.
+         </para>
+         <para>
+           Wildcard CNAMES do not work as they do with bind.
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend, gpgsqlbackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+         </para>
+       </sect3>
+
+      </sect2>
+           
+      <sect2><title>Version 1.99.3 Early Access Prerelease</title>
+       <para>
+         The big news in this release is the BindBackend which is now capable of parsing many more named.conf Bind configurations.
+         Furthermore, PDNS has successfully parsed very large named.confs with large numbers of small domains, as well as small numbers of
+         large domains (TLD).
+       </para>
+       <para>
+         Zone transfers are now also much improved.
+       </para>
+       <para>
+         Major bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               zone2sql leaked file descriptors on each domain, used wrong Bison recursion leading to
+               parser stack overflows. This limited the amount of domains that could be parsed to 1024.
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql can now read all known zonefiles, with the exception of those containing $GENERATE
+             </para
+           </listitem>
+           <listitem>
+             <para>
+               Guardian relaunching a child lost two file descriptors
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Don't die on a connection reset by peer during zone transfer.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Webserver does not crash anymore on ringbuffer resize
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Feature enhancements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               AXFR can now be disabled, and re-enabled per IP address
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               --help accepts a parameter, will then show only help items with that prefix.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+             zone2sql now accepts a --zone-name parameter
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               BindBackend maturing - 9500 zones parsed in 3.5 seconds. No longer case sensitive.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <para>
+         Performance enhancements:
+       <itemizedlist>
+           <listitem>
+             <para>
+               Implemented RFC-breaking AXFR format (which is the industry standard). Zone transfers now zoom along
+               at wirespeed (many megabits/s).
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           FreeBSD version does not stop when requested to do so.
+         </para>
+         <para>
+           BindBackend cannot parse zones with $GENERATE statements. 
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend, gpgsqlbackend
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+         </para>
+       </sect3>
+
+      </sect2>
+           
+      <sect2><title>Version 1.99.2 Early Access Prerelease</title>
+       <para>
+         Major bugs fixed:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Database backend reload does not hang the daemon anymore
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Buffer overrun in local socket address initialisation may have caused binding problems
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               setuid changed the uid to the gid of the selected user
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               zone2sql doesn't coredump on invocation anymore. Fixed lots of small issues.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Don't parse configuration file when creating configuration file. This was a problem with reinstalling.
+             </para>
+           </listitem>
+         </itemizedlist>
+         Performance improvements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               removed a lot of unnecessary gettimeofday calls
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               removed needless select(2) call in case of listening on only one address
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               removed 3 useless syscalls in the fast path
+             </para>
+           </listitem>
+         </itemizedlist>
+         Having said that, more work may need to be done. Testing on a 486 saw packet rates in a simple setup 
+         (question/wait/answer/question..) improve from 200 queries/second to over 400.
+       </para>
+       <para>
+         Usability improvements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               Fixed error checking in init.d script (<command>show</command>, <command>mrtg</command>)
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Added 'uptime' to the mrtg output
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               removed further GNUisms from installer and init.d scripts for use on FreeBSD
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               Debian package and apt repository, thanks to Wichert Akkerman.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               FreeBSD /usr/ports, thanks to Peter van Dijk (in progress).
+             </para>
+           </listitem>
+         </itemizedlist>
+
+
+       </para>
+       <para>
+         Stability may be an issue as well as performance. This version has a tendency to log a bit too much which slows 
+         the nameserver down a lot.
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           Decreasing a ringbuffer on the website is a sure way to crash the daemon. Zone2sql, while improved, still
+           has problems with a zone in the following format:
+           
+           <programlisting>
+name         IN            A        1.2.3.4
+             IN            A        1.2.3.5
+           </programlisting>
+
+           To fix, add 'name' to the second line.
+         </para>
+         <para>
+           Zone2sql does not close filedescriptors.
+         <para>
+
+         <para>
+           FreeBSD version does not stop when requested via the init.d script.
+         <para>
+
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend, gpgsqlbackend
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  fully functioning bindbackend - will try to parse named.conf, but probably fail
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+
+
+         </para>
+       </sect3>
+      </sect2>
+      <sect2><title>Version 1.99.1 Early Access Prerelease</title>
+       <para>
+         This is the first public release of what is going to become PDNS 2.0. As such, it is not of production quality. 
+         Even PowerDNS-the-company does not run this yet.
+       </para>
+       <para>
+         Stability may be an issue as well as performance. This version has a tendency to log a bit too much which slows 
+         the nameserver down a lot.
+       </para>
+       <sect3><title>Known bugs</title>
+         <para>
+           Decreasing a ringbuffer on the website is a sure way to crash the daemon. Zone2sql is very buggy.
+         </para>
+       </sect3>
+       <sect3><title>Missing features</title>
+         <para>
+            Features present in this document, but disabled or withheld from the current release:
+            <itemizedlist>
+              <listitem>
+                <para>
+                  gmysqlbackend, oraclebackend, gpgsqlbackend
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  fully functioning bindbackend - will not parse configuration files
+                </para>
+              </listitem>
+            </itemizedlist>
+            
+            Some of these features will be present in newer releases.  
+
+
+         </para>
+       </sect3>
+      </sect2>
+    </sect1>
+    <sect1 id="thanks-to"><title>Acknowledgements</title>
+      <para>
+       PowerDNS is grateful for the help of the following people or institutions:
+       <itemizedlist>
+         <listitem><para>Dave Aaldering</para></listitem>
+         <listitem><para>Wichert Akkerman</para></listitem>
+         <listitem><para>Antony Antony</para></listitem>
+         <listitem><para>Mike Benoit (NetNation Communication Inc.)</para></listitem>
+         <listitem><para>Peter van Dijk</para></listitem>
+         <listitem><para>Koos van den Hout</para></listitem>
+         <listitem><para>Andre Koopal</para></listitem>
+         <listitem><para>Eric Veldhuyzen</para></listitem>
+         <listitem><para>Paul Wouters</para></listitem>
+         <listitem><para>Thomas Wouters</para></listitem>
+         <listitem><para>IETF Namedroppers mailinglist</para></listitem>
+       </itemizedlist>
+       Thanks!
+      </para>
+      <para>
+       (these people don't share the blame for any errors or mistakes in powerdns - those are all ours)
+      </para>
+  </Chapter>
+
+<Chapter id="installing-on-unix">
+<Title>Installing on Unix</Title>
+
+<Para>
+After unpacking the PDNS distribution the files need to be moved to
+appropriate locations.
+</Para>
+
+<Para>
+PDNS can be installed in a variety of directories, which can easily be
+customised to local policy. Two ways are available - manual and via a menu. 
+</Para>
+
+<Para>
+The menu is invoked by executing the './choosepaths' script and answering the
+questions. The manual way involves editing the 'pathconfig' file. The choice
+is up to you.
+</Para>
+
+<Para>
+After deciding paths, change to root and execute the 'installer' script. 
+This will:
+      <itemizedlist>
+       <listitem>
+         <para>Configure the PowerDNS binary so it knows where the configuration directory is</para>
+       </listitem>
+       <listitem>
+         <para>If necessary, create the configuration directory</para>
+       </listitem>
+       <listitem>
+         <para>Write sample configuration file (not overwriting existing one)</para>
+       </listitem>
+       <listitem>
+         <para>Write a SysV-style init.d script in the configured directory</para>
+       </listitem>
+       <listitem>
+         <para>Move binaries and libraries to the configured places</para>
+       </listitem>
+      </itemizedlist>
+    </Para>
+    
+    <sect1 id="problems">
+      <title>Possible problems at this point</title>
+      <para>
+       At this point some things may have gone wrong. Typical errors include:
+       <variablelist>
+         <varlistentry>
+           <term><errortype>error while loading shared libraries: libstdc++.so.x: cannot open shared object file: No such file or directory</errortype></term>
+           <listitem>
+             <para>
+               Errors looking like this indicate a mismatch between your PDNS distribution and your Unix operating system. Download the static PDNS
+               distribution for your operating system and try again. Please contact <email>pdns@powerdns.com</email> if this is impractical.
+             </para>
+           </listitem>
+         </varlistentry>
+
+
+
+       </variablelist>
+      </para>
+    </sect1>
+
+<Sect1 id="testing">
+<Title>Testing your install</Title>
+      <para>
+       After installing, it is a good idea to test the basic functionality of the software before configuring database backends.
+       For this purpose, PowerDNS contains the 'bindbackend' which has a domain built in example.com, which is
+       officially reserved for testing.
+
+       To test, edit <filename>pdns.conf</filename> and add the following if not already present:
+       
+       <screen>
+         launch=bind
+         bind-example-zones
+       </screen>
+
+       This configures powerdns to 'launch' the bindbackend, and enable the example zones. To fire up PDNS in testing mode, execute: 
+       <command>/etc/init.d/pdns monitor</command>, where you may have to substitute the location of your SysV init.d location you 
+       specified earlier.
+
+       In monitor mode, the pdns process runs in the foreground and is very verbose, which is perfect for testing your install.
+       
+       If everything went all right, you can query the example.com domain like this:
+       <screen>
+         <command>host www.example.com 127.0.0.1</command>
+       </screen>
+       www.example.com should now have IP address 1.2.3.4. The <command>host</command> command can usually be found in the dnsutils 
+       package of your operating system. Alternate command is: <command>dig www.example.com A @127.0.0.1</command> or even 
+       <command>nslookup www.example.com 127.0.0.1</command>, although nslookup is not advised for DNS diagnostics.
+
+       <itemizedlist>
+         <listitem>
+           <para>
+             example.com SOA record
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             example.com NS record pointing to ns1.example.com
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             example.com NS record pointing to ns2.example.com
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             example.com MX record pointing to mail.example.com
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             example.com MX record pointing to mail1.example.com
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             mail.example.com A record pointing to 4.3.2.1
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             mail1.example.com A record pointing to 5.4.3.2
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             ns1.example.com A record pointing to 4.3.2.1
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             ns2.example.com A record pointing to 5.4.3.2
+           </para>
+         </listitem>
+         <listitem>
+           <para>
+             host-0 to host-9999.example.com A record pointing to 2.3.4.5
+           </para>
+         </listitem>
+
+       </itemizedlist>
+
+       When satisfied that basic functionality is there, type <command>QUIT</command> to exit the monitor mode. 
+       The adventurous may also type <command>SHOW *</command> to see some internal statistics. 
+
+       In case of problems, you will want to read the following section.
+      </para>
+      
+      <sect2>
+       <title>Typical errors</title>
+       <para>
+         At this point some things may have gone wrong. Typical errors include:
+         <variablelist>
+           <varlistentry>
+             <term><errortype>binding to UDP socket: Address already in use</errortype></term>
+             <listitem>
+               <para>
+                 This means that another nameserver is listening on port 53 already. You can resolve this problem
+                 by determining if it is safe to shutdown the nameserver already present, and doing so. If uncertain,
+                 it is also possible to run PDNS on another port. To do so, add <command>local-port=5300</command> to
+                 <filename>pdns.conf</filename>, and try again. This however implies that you can only test your nameserver
+                 as clients expect the nameserver to live on port 53.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term><errortype>binding to UDP socket: Permission denied</errortype></term>
+             <listitem>
+               <para>
+                 You must be superuser in order to be able to bind to port 53. If this is not a possibility,
+                 it is also possible to run PDNS on another port. To do so, add <command>local-port=5300</command> to
+                 <filename>pdns.conf</filename>, and try again. This however implies that you can only test your nameserver
+                 as clients expect the nameserver to live on port 53.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term><errortype>Unable to launch, no backends configured for querying</errortype></term>
+             <listitem>
+               <para>
+                 PDNS did not find the <command>launch=bind</command> instruction in pdns.conf.
+               </para>
+             </listitem>
+           </varlistentry>
+
+         </variablelist>
+       </para>
+      </sect2>
+</Sect1>
+
+    <sect1 id="pdns-on-unix">
+    <Title>Running PDNS on unix</Title>
+
+    <Para>
+      PDNS is normally controlled via a SysV-style init.d script, often located in <filename>/etc/init.d</filename> or
+      <filename>/etc/rc.d/init.d</filename>. This script accepts the following commands:
+      <variablelist>
+       <varlistentry>
+         <term>monitor</term>
+         <listitem>
+           <para>
+             Monitor is a special way to view the daemon. It executes PDNS in the foreground with 
+             a lot of logging turned on, which helps in determining startup problems. 
+
+             Besides running in the foreground, the raw PDNS control socket is made available. All external
+             communication with the daemon is normally sent over this socket. While useful, the control console 
+             is not an officially supported feature. Commands which work are: <command>QUIT</command>, <command>SHOW *</command>,
+             <command>SHOW varname</command>, <command>RPING</command>.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>start</term>
+         <listitem>
+           <para>
+             Start PDNS in the background. Launches the daemon but makes no special effort to determine success, 
+             as making database connections may take a while. Use <command>status</command> to query success. You
+             can safely run <command>start</command> many times, it will not start additional PDNS instances.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>restart</term>
+         <listitem>
+           <para>
+             Restarts PDNS if it was running, starts it otherwise.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>status</term>
+         <listitem>
+           <para>
+             Query PDNS for status. This can be used to figure out if a launch was successful.
+             The status found is prefixed by the PID of the main PDNS process. 
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>stop</term>
+         <listitem>
+           <para>
+             Requests that PDNS stop. Again, does not confirm success. Success can be ascertained with the <command>status</command> command.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term>dump</term>
+         <listitem>
+           <para>
+             Dumps a lot of statistics of a running PDNS daemon. It is also possible to single out specific variable by using 
+             the <command>show</command> command.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term>show variable</term>
+         <listitem>
+           <para>
+             Show a single statistic, as present in the output of the <command>dump</command>.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term>mrtg</term>
+         <listitem>
+           <para>
+             See the performance monitoring <xref linkend="monitoring">.
+           </para>
+         </listitem>
+       </varlistentry>
+
+      </variablelist>
+    </Para>
+
+  </sect1>
+</Chapter>
+
+<Chapter id="windows">
+  <Title>Installing on Microsoft Windows</Title>
+    <para>
+    <note>
+      <para>
+         PowerDNS support for Windows is, as of 1.99.12, very recent and therefore quite 'beta'. For reliability, we currently advise the use of 
+         the Unix versions. Furthermore there is no support for master or slave operation in the ODBC backend, which is the only one provided currently. 
+         This will be fixed soon.
+      </para>
+    </note>
+    </para>
+    <para>
+      As of 1.99.12, PowerDNS supports Windows natively. PDNS can act as an NT service and works with any ODBC drivers you may have.
+    </para>
+    <para>
+      To install PowerDNS for Windows you should check if your PC meets the following requirements:
+      <itemizedlist>
+      <listitem>
+         <para>
+           A PC running Microsoft NT (with a recent servicepack and at least mdac 2.5), 2000 or XP.
+           </para>
+       </listitem>
+       <listitem>
+         <para>An ODBC source containing valid zone information (an example MS Access database is supplied in the form of <filename>powerdns.mdb</filename>).
+    </para>
+       </listitem>
+      </itemizedlist>
+  </para>
+
+  <para>
+    If your system meets these requirements, download the installer from <ulink url="http://www.powerdns.com/pdns/">http://www.powerdns.com/pdns/</ulink>.
+    After downloading the file begin the installation procedure by starting <filename>powerdns-VERSION.exe</filename>.
+
+  </para>
+
+  <para>
+    After installing the software you should create a valid ODBC source.
+    To do this you have open the ODBC sources dialog: <filename>Start->Settings->Control Panel->Administrative Tools->Data Sources (ODBC)</filename>.
+  </para>
+
+  <para>
+    We'll use the example zone database that is included in the installation to explain how to create a source.\r
+  </para>\r
+\r
+  <para>\r
+    When you are in the ODBC sources dialog you activate the <filename>System DSN</filename> tab. \r
+    <note><para>It is important to create a System DSN instead of an User DNS, otherwise the ODBC backend cannot function.</para></note>\r
+  </para>\r
+
+  <para>
+    Press <filename>Add...</filename>, then you have to select a driver.\r
+  </para>\r
+\r
+  <para>
+    Select <filename>Microsoft Access Driver (*.mdb)</filename>.
+  </para>
+
+  <para>
+    Use <filename>PowerDNS</filename> as the DSN name, you can leave the description empty.
+  </para>
+
+  <para>    
+    Then press <filename>Select...</filename> to select the database (ie. <filename>C:\Program Files\PowerDNS\powerdns.mdb</filename>).
+  </para>
+
+  <para>
+    Press <function>Ok</function> and you should be done.
+  </para>
+  \r
+  <para>
+    For more information, see <xref linkend="odbc">.
+  </para>
+\r
+  <sect1 id="windows-configuration">\r
+    <title>Configuring PDNS on Microsoft Windows</title>\r
+\r
+    <para>\r
+      You can specify program parameters in the <filename>pdns.conf</filename> file\r
+      which should be located in pdns directory (ie. <filename>C:\Program Files\PowerDNS\</filename>).\r
+    </para>\r
+\r
+    <para>\r
+      To see a list of available parameters you can run <filename>pdns.exe --help</filename>.\r
+    </para>\r
+\r
+    <note>\r
+      <para>\r
+        A default configuration file has been supplied with the installation.\r
+      </para>\r
+    </note>\r
+\r
+  </sect1>\r
+
+    <sect1 id="running-on-windows">
+      <title>Running PDNS on Microsoft Windows</title>
+
+    <para>
+      If you installed pdns on Windows NT, 2000 or XP you can run pdns as a service.\r
+         </para>
+\r
+       <para>
+      This is how to do it:
+      Go to services (<filename>Start->Settings->Control Panel->Administrative Tools->Services</filename>) and locate <filename>PDNS</filename> (you should have registered the program as a NT service during the installation).
+    </para>
+    
+    <para>
+      Double-click on <filename>PDNS</filename> and push the start button. You should now see a progress bar that gets to the end and see the status change to 'Started'.
+    </para>
+
+    <para>
+      This is the same as starting pdns like this:
+      <filename>pdns.exe --ntservice</filename>
+    </para>
+
+    <para>
+      If you haven't registered pdns as a service during the installation you can do so from the commandline by starting pdns like this:
+      <filename>pdns.exe --register-service</filename>
+    </para>
+
+    <para>
+      You can run pdns as a standard console program by using a command prompt or <filename>Start->Run...</filename>
+      This way you can specify command-line parameters (see the documentation for commandline options).
+    </para>
+
+    <para>
+      If you chose to add a PowerDNS menu to the start menu during the installation you can start pdns using the pdns shortcut in that menu.
+    </para>
+
+    </sect1>
+  </Chapter>
+
+  <Chapter id="configuring-db-connection">
+    <title>Configure database connectivity</title>
+    <para>
+      The default PDNS distribution comes with a simple MySQL backend built in, which we will now use for 
+      demonstrating database connectivity. This backend is called 'mysql', and needs to be configured
+      in <filename>pdns.conf</filename>. Add the following lines, adjusted for your local setup:
+      
+      <screen>
+       launch=mysql
+       mysql-host=127.0.0.1
+       mysql-user=root
+       mysql-dbname=pdnstest
+      </screen>
+      
+      Remove any earlier <command>launch</command> statements. Also remove the <command>bind-example-zones</command>
+      statement as the <command>bind</command> module is no longer launched.
+    </para>
+    <para>
+      WARNING! Make sure that you can actually resolve the hostname of your database without accessing the database! It is advised to supply
+      an IP address here to prevent chicken/egg problems!
+    </para>
+    <para>
+      Now start PDNS using the monitor command:
+      <screen>
+       # /etc/init.d/pdns monitor
+       (...)
+       15:31:30 PowerDNS 1.99.0 (Mar 12 2002, 15:00:28) starting up
+       15:31:30 About to create 3 backend threads
+       15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
+       15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
+       15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
+      </screen>
+      
+      This is as to be expected - we did not yet add anything to MySQL for PDNS to read from. At this point you may also see
+      other errors which indicate that PDNS either could not find your MySQL server or was unable to connect to it. Fix these 
+      before proceeding.
+    </para>
+    <para>
+      General MySQL knowledge is assumed in this chapter, please do not interpret these commands as DBA advice!
+    </para>
+    <sect1 id="configuring-mysql"><title>Configuring MySQL</title>
+      <para>
+       Connect to MySQL as a user with sufficient privileges and issue the following commands:
+       <screen>
+         # mysql 
+         mysql> CREATE DATABASE pdnstest;
+         mysql> use pdnstest;
+
+         mysql> CREATE TABLE records (
+         id int(11) NOT NULL auto_increment,
+         domain_id int(11) default NULL,
+         name varchar(255) default NULL,
+         type varchar(6) default NULL,
+         content varchar(255) default NULL,
+         ttl int(11) default NULL,
+         prio int(11) default NULL,
+         change_date int(11) default NULL,
+         PRIMARY KEY (id),
+         KEY name_index(name),
+         KEY nametype_index(name,type),
+         KEY domainid_index(domain_id)
+         );
+       </screen>
+       
+       Now we have a database and an empty table. PDNS should now be able to launch in monitor mode and display no errors:
+
+       <screen>
+         # /etc/init.d/pdns monitor
+         (...)
+         15:31:30 PowerDNS 1.99.0 (Mar 12 2002, 15:00:28) starting up
+         15:31:30 About to create 3 backend threads
+         15:39:55 [MySQLbackend] MySQL connection succeeded
+         15:39:55 [MySQLbackend] MySQL connection succeeded
+         15:39:55 [MySQLbackend] MySQL connection succeeded
+       </screen>
+       
+       A sample query sent to the database should now return quickly without data:
+       <screen>
+         $ host www.test.com 127.0.0.1
+         www.test.com A record currently not present at localhost
+       </screen>
+
+       And indeed, the control console now shows:
+       <screen>
+         Mar 12 15:41:12 We're not authoritative for 'www.test.com', sending unauth normal response
+       </screen>
+
+       Now we need to add some records to our database:
+       <screen>
+         # mysql pdnstest
+         mysql>
+         INSERT INTO records (domain_id, name, content, type,ttl,prio) 
+         VALUES (1,'test.com','localhost ahu@ds9a.nl 1','SOA',86400,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'test.com','dns-us1.powerdns.net','NS',86400,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'test.com','dns-eu1.powerdns.net','NS',86400,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'www.test.com','199.198.197.196','A',120,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'mail.test.com','195.194.193.192','A',120,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'localhost.test.com','127.0.0.1','A',120,NULL);
+         INSERT INTO records (domain_id, name, content, type,ttl,prio)
+         VALUES (1,'test.com','mail.test.com','MX',120,25);
+       </screen>
+       
+       If we now requery our database, <command>www.test.com</command> should be present:
+       <screen>
+         $ host www.test.com 127.0.0.1
+         www.test.com          A       199.198.197.196
+         
+         $ host -v -t mx test.com 127.0.0.1
+         Address: 127.0.0.1
+         Aliases: localhost
+
+         Query about test.com for record types MX
+         Trying test.com ...
+         Query done, 1 answer, authoritative status: no error
+         test.com              120     IN      MX      25 mail.test.com
+         Additional information:
+         mail.test.com         120     IN      A       195.194.193.192
+       </screen>
+       
+       To confirm what happened, issue the command <command>SHOW *</command> to the control console:
+       <screen>
+         % show *
+         corrupt-packets=0,latency=0,packetcache-hit=2,packetcache-miss=5,packetcache-size=0,
+         qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,
+         timedout-packets=0,udp-answers=7,udp-queries=7,
+         % 
+       </screen>
+       The actual numbers will vary somewhat. Now enter <command>QUIT</command> and start PDNS as a regular daemon, and check launch status:
+
+       <screen>
+         # /etc/init.d/pdns start 
+         pdns: started
+         # /etc/init.d/pdns status
+         pdns: 8239: Child running
+         # /etc/init.d/pdns dump  
+         pdns: corrupt-packets=0,latency=0,packetcache-hit=0,packetcache-miss=0,
+         packetcache-size=0,qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,
+         tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,
+       </screen>
+       
+       You now have a working database driven nameserver! To convert other zones already present, use the <command>zone2sql</command> 
+        described in Appendix A.
+      </para>
+      <sect2><title>Common problems</title>
+       <para>
+         Most problems involve PDNS not being able to connect to the database. 
+       <variablelist>
+         <varlistentry>
+             <term><errortype> Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)</errortype></term>
+             <listitem>
+               <para>
+                 Your MySQL installation is probably defaulting to another location for its socket. Can be resolved
+                 by figuring out this location (often <filename>/var/run/mysqld.sock</filename>), and specifying it 
+                 in the configuration file with the <command>mysql-socket</command> parameter.
+               </para>
+               <para>
+                 Another solution is to not connect to the socket, but to 127.0.0.1, which can be achieved by specifying
+                 <command>mysql-host=127.0.0.1</command>.
+               </para>
+             </listitem>
+           </varlistentry>
+         <varlistentry>
+             <term><errortype>Host 'x.y.z.w' is not allowed to connect to this MySQL server</errortype></term>
+             <listitem>
+               <para>
+                 These errors are generic MySQL errors. Solve them by trying to connect to your MySQL database with the MySQL 
+                 console utility <command>mysql</command> with the parameters specified to PDNS. Consult the MySQL documentation.
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </sect2>
+    </sect1>
+  </chapter>
+
+  <Chapter id="pipebackend-dynamic-resolution">
+    <title>Dynamic resolution using the PipeBackend</title>
+    <para>
+      Also included in the PDNS distribution is the PipeBackend. The PipeBackend is primarily meant for
+      allowing rapid development of new backends without tight integration with PowerDNS. It allows
+      end-users to write PDNS backends in any language. A perl sample is provided.
+
+      The PipeBackend is also very well suited for dynamic resolution of queries. Example applications include
+      DNS based loadbalancing, geo-direction, DNS based failover with low TTLs.
+    </para>
+    <sect1 id="pipe-and-bind"><title>Deploying the PipeBackend with the BindBackend</title>
+      <para>
+        Included with the PDNS distribution is the example.pl backend which has knowledge of the example.com zone, just like
+        the BindBackend. To install both, add the following to your <filename>pdns.conf</filename>:
+        <screen>
+          launch=pipe,bind
+          bind-example-zones
+          pipe-command=location/of/backend.pl
+        </screen>
+        Please adjust the <command>pipe-command</command> statement to the location of the unpacked PDNS distribution. If your backend is slow,
+       raise <command>pipe-timeout</command> from its default of 2000ms.
+
+        Now launch PDNS in monitor mode, and perform some queries. Note the difference with the earlier experiment where only the 
+        BindBackend was loaded. The PipeBackend is launched first and thus gets queried first.
+
+        The sample backend.pl script knows about:
+       <itemizedlist>
+         <listitem>
+           <para>
+             webserver.example.com A records pointing to 1.2.3.4, 1.2.3.5, 1.2.3.6
+           </para>
+          </listitem>
+         <listitem>
+           <para>
+             www.example.com CNAME pointing to webserver.example.com
+           </para>
+          </listitem>
+         <listitem>
+           <para>
+             MBOXFW (mailbox forward) records pointing to powerdns@example.com.
+              See the smtpredir documentation for information about MBOXFW.
+           </para>
+          </listitem>
+        </itemizedlist>
+
+        For more information about how to write exciting backends with the PipeBackend, see Appendix A.
+      </para>
+    </sect1>
+  </chapter>
+
+  <Chapter id="monitoring">
+    <title>Logging &amp; Monitoring PDNS performance</title>
+    <para>
+      In a production environment, you will want to be able to monitor PDNS performance. For this purpose, currently 
+      two methods are available, the webserver and the init.d
+<command>dump</command>, <command>show</command> and 
+      <command>mrtg</command>, commands. Furthermore, PDNS can perform a configurable amount of operational logging. This chapter
+       also explains how to configure syslog for best results.
+    </para>
+    <sect1 id="webserver"><title>Webserver</title>
+      <para>
+       To launch the internal webserver, add a <command>webserver</command> statement to the pdns.conf. This 
+       will instruct the PDNS daemon to start a webserver on localhost at port 8081, without password protection. 
+       Only local users (on the same host) will be able to access the webserver by default.
+
+       The webserver   lists a lot of information about the PDNS process, including frequent queries, frequently failing queries, 
+       lists of remote hosts sending queries, hosts sending corrupt queries etc. The webserver does not allow
+       remote management of the daemon.
+
+       The following nameserver related configuration items are available:
+       <variablelist>
+         <varlistentry>
+           <term>webserver</term>
+           <listitem>
+             <para>
+               If set to anything but 'no', a webserver is launched.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>webserver-address</term>
+           <listitem>
+             <para>
+               Address to bind the webserver to. Defaults to 127.0.0.1, which implies that only the local computer
+               is able to connect to the nameserver! To allow remote hosts to connect, change to 0.0.0.0 or the
+               physical IP address of your nameserver.
+             </para>
+           </listitem>
+         </varlistentry>
+       <varlistentry>
+         <term>webserver-password</term>
+         <listitem>
+           <para>
+             If set, viewers will have to enter this plaintext password in order to gain access to the statistics.
+           </para>
+         </listitem>
+       </varlistentry>
+         <varlistentry>
+           <term>webserver-port</term>
+           <listitem>
+             <para>
+               Port to bind the webserver to. Defaults to 8081.
+             </para>
+           </listitem>
+         </varlistentry>
+
+      </variablelist>
+      </para>
+      </sect1>
+    <sect1 id="init-d-commands"><title>Via init.d commands</title>
+      <para>
+       As mentioned before, the init.d commands <command>dump</command>, <command>show</command> and 
+       <command>mrtg</command> fetch data from a running PDNS process. Especially <command>mrtg</command> is powerful -
+       it outputs data in a format that is ready for processing by the MRTG graphing tool. 
+      </para>
+      <para>
+       MRTG can make insightful graphics on the performance of your nameserver, enabling the operator to easily spot trends.
+       MRTG can be found on 
+       <ulink url="http://people.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg.html">
+         http://people.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg.html
+       </ulink>
+      </para>
+      <para>
+       A sample mrtg.conf:
+       <screen>
+Interval: 5
+WorkDir: /var/www/mrtg
+WriteExpires: yes
+Options[_]: growright,nopercent
+XSize[_]: 600
+
+#---------------------------------------------------------------
+
+Target[udp-queries]: `/etc/init.d/pdns mrtg udp-queries udp-answers`
+Options[udp-queries]: growright,nopercent,perminute
+MaxBytes[udp-queries]: 600000
+AbsMax[udp-queries]: 600000
+Title[udp-queries]: Queries per minute
+PageTop[udp-queries]: &lt;H2&gt;Queries per minute&lt;/H2&gt;
+WithPeak[udp-queries]: ymwd
+YLegend[udp-queries]: queries/minute
+ShortLegend[udp-queries]: q/m
+LegendI[udp-queries]: udp-questions
+LegendO[udp-queries]: udp-answers
+
+
+Target[perc-failed]: `/etc/init.d/pdns mrtg udp-queries udp-answers`
+Options[perc-failed]: growright,dorelpercent,perminute
+MaxBytes[perc-failed]: 600000
+AbsMax[perc-failed]: 600000
+Title[perc-failed]: Queries per minute, with percentage success
+PageTop[perc-failed]: &lt;H2&gt;Queries per minute, with percentage success&lt;/H2&gt;
+WithPeak[perc-failed]: ymwd
+YLegend[perc-failed]: queries/minute
+ShortLegend[perc-failed]: q/m
+LegendI[perc-failed]: udp-questions
+LegendO[perc-failed]: udp-answers
+
+
+Target[packetcache-rate]: `/etc/init.d/pdns mrtg packetcache-hit udp-queries`
+Options[packetcache-rate]: growright,dorelpercent,perminute
+Title[packetcache-rate]: packetcache hitrate
+MaxBytes[packetcache-rate]: 600000
+AbsMax[packetcache-rate]: 600000
+PageTop[packetcache-rate]: &lt;H2&gt;packetcache hitrate&lt;/H2&gt;
+WithPeak[packetcache-rate]: ymwd
+YLegend[packetcache-rate]: queries/minute
+ShortLegend[packetcache-rate]: q/m
+LegendO[packetcache-rate]: total
+LegendI[packetcache-rate]: hit
+
+Target[packetcache-missrate]: `/etc/init.d/pdns mrtg packetcache-miss udp-queries`
+Options[packetcache-missrate]: growright,dorelpercent,perminute
+Title[packetcache-missrate]: packetcache MISSrate
+MaxBytes[packetcache-missrate]: 600000
+AbsMax[packetcache-missrate]: 600000
+PageTop[packetcache-missrate]: &lt;H2&gt;packetcache MISSrate&lt;/H2&gt;
+WithPeak[packetcache-missrate]: ymwd
+YLegend[packetcache-missrate]: queries/minute
+ShortLegend[packetcache-missrate]: q/m
+LegendO[packetcache-missrate]: total
+LegendI[packetcache-missrate]: MISS
+
+Target[latency]: `/etc/init.d/pdns mrtg latency`
+Options[latency]: growright,nopercent,gauge
+MaxBytes[latency]: 600000
+AbsMax[latency]: 600000
+Title[latency]: Query/answer latency
+PageTop[latency]: &lt;H2&gt;Query/answer latency&lt;/H2&gt;
+WithPeak[latency]: ymwd
+YLegend[latency]: usec
+ShortLegend[latency]: usec
+LegendO[latency]: latency
+LegendI[latency]: latency
+
+Target[recursing]: `/etc/init.d/pdns mrtg recursing-questions recursing-answers`
+Options[recursing]: growright,nopercent,gauge
+MaxBytes[recursing]: 600000
+AbsMax[recursing]: 600000
+Title[recursing]: Recursive questions/answers
+PageTop[recursing]: &lt;H2&gt;Recursing questions/answers&lt;/H2&gt;
+WithPeak[recursing]: ymwd
+YLegend[recursing]: queries/minute
+ShortLegend[recursing]: q/m
+LegendO[recursing]: recursing-questions
+LegendI[recursing]: recursing-answers
+
+       </screen>
+      </para>
+      <sect1 id="syslog"><title>Operational logging using syslog</title>
+      <para>(<command>logging-facility</command> is available from 1.99.10 and onwards)</para>
+      <para>
+       This chapter assumes familiarity with syslog, the unix logging device. PDNS logs messages with different levels. The more urgent the 
+       message, the lower the 'priority'. By default, PDNS will only log messages with an urgency of 3 or lower, but this can be changed
+       using the <command>loglevel</command> setting in the configuration file. Setting it to 0 will eliminate all logging, 9 will log
+       everything.
+      </para>
+      <para>
+       By default, logging is performed under the 'DAEMON' facility which is shared with lots of other programs. If you regard nameserving
+       as important, you may want to have it under a dedicated facility so PDNS can log to its own files, and not clutter generic files.
+      </para>
+      <para>
+       For this purpose, syslog knows about 'local' facilities, numbered from LOCAL0 to LOCAL7. To move PDNS logging to LOCAL0, add 
+       <command>logging-facility=0</command> to your configuration.
+      </para>
+      <para>
+       Furthermore, you may want to have separate files for the differing prioties - preventing lower priority messages from obscuring 
+       important ones.
+      </para>
+      <para>
+       A sample syslog.conf might be:
+       <programlisting>
+local0.info                       -/var/log/pdns.info
+local0.warn                       -/var/log/pdns.warn
+local0.err                        /var/log/pdns.err
+       </programlisting>
+      </para>
+      <para>
+       Where local0.err would store the really important messages. For performance and diskspace reasons, it is advised
+       to audit your syslog.conf for statements also logging PDNS activities. Many syslog.confs have a '*.*' statement to
+       /var/log/syslog, which you may want to remove.
+      </para>
+      <para>
+       For performance reasons, be especially certain that no large amounts of synchronous logging take place. Under Linux, this 
+       is indicated by filenames not starting with a '-' - indicating a synchronous log, which hurts performance.
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="security"><title>Security settings &amp; considerations</title>
+    <sect1 id="settings"><title>Settings</title>
+      <para>PDNS has several options to easily allow it to run more securely. Most notable are the <command>chroot</command>, 
+       <command>setuid</command> and <command>setgid</command> options which can be specified.</para>
+
+       <sect2><title>Running as a less privileged identity</title>
+       <para>
+         By specifying <command>setuid</command> and <command>setgid</command>, PDNS changes to this identity shortly after
+         binding to the privileged DNS ports. These options are highly recommended. It is suggested that a separate identity
+         is created for PDNS as the user 'nobody' is in fact quite powerful on most systems.
+       </para>
+
+       <para>
+         Both these parameters can be specified either numerically or as real names.
+         You should set these parameters immediately if they are not set!
+       </para>
+       <sect2><title>Jailing the process in a chroot</title>
+       <para>
+         The <command>chroot</command> option secures PDNS to its own directory so that even if it should become compromised and
+         under control of external influences, it will have a hard time affecting the rest of the system.
+       </para>
+       <para>
+         Even though this will hamper hackers a lot, chroot jails have been known to be broken. 
+       </para>
+       <para>
+         When chrooting PDNS, take care that backends will be able to get to their files. Many databases need access to a UNIX 
+         domain socket which should live within the chroot. It is often possible to hardlink such a socket into the chroot dir.
+       </para><para>
+         The default PDNS configuration is best chrooted to <filename>./</filename>, which boils down to the configured location
+         of the controlsocket. 
+       </para><para>
+         This is achieved by adding the following to pdns.conf: <command>chroot=./</command>, and restarting PDNS.
+       </para>
+      </sect2>
+    </sect1>
+    <sect1 id="considerations"><title>Considerations</title>
+      <para>
+       In general, make sure that the PDNS process is unable to execute commands on your backend database. 
+       Most database backends will only need SELECT privilege. Take care to not connect to your database as the 'root' 
+       or 'sa' user, and configure the chosen user to have very slight privileges.
+      </para>
+      <para>
+       Databases empathic-ally do not need to run on the same machine that runs PDNS! In fact, in benchmarks
+       it has been discovered that having a separate database machine actually improves performance.
+      </para>
+      <para>
+       Separation will enhance your database security highly. Recommended.
+      </para>
+      </sect1>
+    </chapter>
+    
+  <chapter id="virtual"><title>Virtual hosting</title>
+    <para>
+      It may be advantageous to run multiple separate PDNS installations on a single host, for example to make sure
+      that different customers cannot affect each others zones. PDNS fully supports running multiple instances on one host.
+    </para>
+    <para>
+      To generate additional PDNS instances, copy the init.d script <filename>pdns</filename> to <filename>pdns-name</filename>, 
+      where <filename>name</filename> is the name of your virtual configuration. Must not contain a - as this will confuse the 
+      script.
+    </para>
+    <para>
+      When you launch PDNS via this renamed script, it will seek configuration instructions not in <filename>pdns.conf</filename>
+      but in <filename>pdns-name.conf</filename>, allowing for separate specification of parameters.
+    </para>
+    <para>
+      Be aware however that the init.d <command>force-stop</command> will kill all PDNS instances!
+    </para>
+  </chapter>
+
+  <chapter id="performance"><title>Performance related settings</title>
+    <para>
+      Different backends will have different characteristics - some will want to have more parallel
+      instances than others. In general, if your backend is latency bound, like most relational databases are, 
+      it pays to open more backends.
+    </para>
+    <para>
+      This is done with the <command>distributor-threads</command> setting. Of special importance is the choice between 1
+      or more backends. In case of only 1 thread, PDNS reverts to unthreaded operation which may be a lot faster, depending
+      on your operating system and architecture.
+    </para>
+    <para>
+      Another very important setting <command>cache-ttl</command>. PDNS caches entire packets it sends out so as to save the
+      time to query backends to assemble all data. The default setting of 10 seconds may be low for high traffic sites, a value of
+      60 seconds rarely leads to problems.
+    </para>
+    <para>
+      Some PDNS operators set cache-ttl to many hours or even days, and use <command>pdns_control purge</command> to selectively
+      or globally notify PDNS of changes made in the backend. Also look at the Query Cache described in this chapter. It may
+      materially improve your performance.
+    </para>
+    <para>
+      To determine if PDNS is unable to keep up with packets, determine the value of the <command>qsize-q</command> variable. 
+      This represents the number of packets waiting for database attention. During normal operations the queue should be small. 
+    </para>
+    <para>
+      If it is known that backends will not contain CNAME records, the <command>skip-cname</command> setting can be used to prevent 
+      the normally mandatory CNAME lookup that is needed at least once for each DNS query. 
+    </para>
+
+    <para>
+      Much the same holds for the <command>wildcards</command> setting. On by default, each non-existent query will lead to a number of additional
+      wildcard queries. If it is known that the backends do not contain wildcard records, performance can be improved by adding <command>wildcards=no</command>
+      to <filename>pdns.conf</filename>.
+    </para>
+    <para>
+      Logging truly kills performance as answering a question from the cache is an order of magnitude less work than logging a 
+      line about it. Busy sites will prefer to turn <command>log-dns-details</command> and <command>log-failed-updates</command>
+      off.
+    </para>
+    <sect1 id="packetcache"><title>Packet Cache</title>
+      <para>
+       PDNS by default uses the 'Packet Cache' to recognise identical questions and supply them with identical answers, without any further 
+       processing. The default time to live is 10 seconds. It has been observed that the utility of the packet cache increases with the load on 
+       your nameserver. 
+      </para>
+      <para>
+       Not all backends may benefit from the packetcache. If your backend is memory based and does not lead to context switches, the packetcache
+       may actually hurt performance. 
+      </para>
+      <para>
+       The size of the packetcache can be observed with <command>/etc/init.d/pdns show packetcache-size</command>
+      </para>
+    </sect1>
+    <sect1 id="querycache"><title>Query Cache</title>
+      <para>
+       Besides entire packets, PDNS can also cache individual backend queries. Each DNS query leads to a number of backend queries,
+       the most obvious additional backend query is the check for a possible CNAME. So, when a query comes in for the 'A' record for
+       'www.powerdns.com', PDNS must first check for a CNAME for 'www.powerdns.com'.
+      </para>
+      <para>
+       The Query Cache caches these backend queries, many of which are quite repetitive. PDNS only caches queries with no answer,
+       or with exactly one. In the future this may be expanded but this lightweight solution is very simple and therefore fast.
+      </para>
+      <para>
+       Most gain is made from caching negative entries, ie, queries that have no answer. As these take little memory to store and
+       are typically not a real problem in terms of speed-of-propagation, the default TTL for negative queries is a rather high 60 seconds.
+      </para>
+      <para>
+       This only is a problem when first doing a query for a record, adding it, and immediately doing a query for that record again. It may
+       then take up to 60 seconds to appear. Changes to existing records however do not fall under the negative query ttl (
+       <command>negquery-cache-ttl</command>), but under the generic <command>query-ttl</command> which defaults to 20 seconds.
+      </para>
+      <para>
+       The default values should work fine for many sites. When tuning, keep in mind that the Query Cache mostly saves database access 
+       but that the Packet Cache also saves a lot of CPU because 0 internal processing is done when answering a question from the
+       Packet Cache.
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="migration"><title>Migrating to PDNS</title>
+    <para>
+      Before migrating to PDNS a few things should be considered. 
+      <variablelist>
+       <varlistentry>
+         <term>PDNS is not a recursing nameserver on its own</term>
+         <listitem>
+           <para>
+             If PDNS receives a question for which it is not authoritative, it can't go out on the net to figure out an answer. However, 
+             because many installations are expected to be both authoritative and recursing, PDNS can use a separate recursing backend
+             to provide non-authoritative answers. See <xref linkend="recursion"> for more details.
+           </para>
+         </listitem></varlistentry>
+       <varlistentry>
+         <term>PDNS does not operate as a 'slave' server with all backends</term>
+         <listitem>
+           <para>
+             Only the PostgreSQL backend has, of version 1.99.9, the ability to act as a slave.
+           </para>
+         </listitem>
+       </varlistentry>
+      </variablelist>
+      To migrate, the <command>zone2sql</command> tool is provided. 
+      </para>
+    <sect1 id="zone2sql"><title>Zone2sql</title>
+      <para>
+       Zone2sql parses Bind named.conf files and zonefiles and outputs SQL 
+       on standard out, which can then be fed to your database.
+      </para>
+      <para>
+       Zone2sql understands the Bind master file extension '$GENERATE' and will also honour '$ORIGIN' and '$TTL'.
+      </para>
+      <para>
+       For backends supporting slave operation (currently only the PostgreSQL backend), there is also an option to keep slave zones as slaves,
+       and not convert them to native operation. 
+      </para>
+      <para>
+       By default, zone2sql outputs code suitable for the mysqlbackend, but it can also generate SQL for the Generic PostgreSQL and Oracle backends. 
+       The following commands are available:
+      </para>
+
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>--bare</term>
+           <listitem>
+             <para>
+             Output in a bare format, suitable for further parsing. The output is formatted as follows:
+               <screen>
+                 domain_id&lt;TAB&gt;'qname'&lt;TAB&gt;'qtype'&lt;TAB&gt;'content'&lt;TAB&gt;prio&lt;TAB&gt;ttl
+               </screen>
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--gmysql</term>
+           <listitem>
+             <para>
+               Output in format suitable for the default configuration of the Generic MySQL backend.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--gpgsql</term>
+           <listitem>
+             <para>
+               Output in format suitable for the default configuration of the Generic PostgreSQL backend.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--help</term>
+           <listitem>
+             <para>
+               List options.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--mysql</term>
+           <listitem>
+             <para>
+               Output in format suitable for the default configuration of the MySQL backend. Default.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--named-conf=...</term>
+           <listitem>
+             <para>
+               Parse this named.conf to find locations of zones. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--on-error-resume-next</term>
+           <listitem>
+             <para>
+               Ignore missing files during parsing. Dangerous.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--oracle</term>
+           <listitem>
+             <para>
+               Output in format suitable for the default configuration of the Generic Oracle backend.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--slave</term>
+           <listitem>
+             <para>
+               Maintain slave status of zones listed in named.conf as being slaves. The default behaviour is to convert all zones
+               to native operation.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--startid</term>
+           <listitem>
+             <para>
+               Supply a value for the first domain_id generated. Defaults at 0.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--transactions</term>
+           <listitem>
+             <para>
+               For Oracle and PostgreSQL output, wrap each domain in a transaction for higher speed and integrity.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--verbose</term>
+           <listitem>
+             <para>
+               Be verbose during conversion.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--zone=...</term>
+           <listitem>
+             <para>
+               Parse only this zone file. Conflicts with <command>--named-conf</command> parameter. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>--zone-name=...</term>
+           <listitem>
+             <para>
+               When parsing a single zone without $ORIGIN statement, set this as the zone name.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+    </sect1>
+  </chapter>
+  
+  <chapter id="recursion"><title>Recursion</title>
+
+    <para>(only available from 1.99.8 and onwards)</para>
+    <para>
+      PDNS is an authoritative nameserver. It answers questions with data from its backends. Besides handing out authoritative
+      answers, DNS also needs so called 'recursion', where a nameserver gets a question for which it has no authoritative answer available, 
+      necessitating questions to other nameservers.
+    </para>
+    <para>
+      Although PDNS is an authoritative nameserver, a provision has been made to cater for installations that require both authoritative DNS 
+      and recursion on one IP address. 
+    </para>
+    <para>
+      By specifying the <command>recursor</command> option in the configuration file, questions requiring recursive treatment will be handed over
+      to the IP address specified. An example configuration might be <command>recursor=130.161.180.1</command>, which designates 130.161.180.1 as
+      the nameserver to handle recursive queries.
+    </para>
+    <para>
+      Any recursing nameserver is suitable but we highly advise the use of the DJBDNS dnscache (<ULINK URL="http://cr.yp.to/djbdns/dnscache.html" TYPE="alternate">http://cr.yp.to/djbdns/dnscache.html</ULINK>).
+    </para>
+    <para>
+      Take care not to point <command>recursor</command> to PDNS, which leads to a very tight packet loop!
+    </para>
+    <para>
+      By specifying <command>allow-recursion</command>, recursion can be restricted to netmasks specified. The default is to allow
+      recursion from everywhere. Example: <command>allow-recursion=192.168.0.0/24, 10.0.0.0/8, 1.2.3.4</command>.
+    </para>
+    <sect1 id="recursion-details"><title>Details</title>
+      <para>
+       Questions carry a number of flags. One of these is called 'Recursion Desired'. If PDNS is configured to allow recursion, AND such a flag
+       is seen, AND the IP address of the client is allowed to recurse via PDNS, then the packet is handed to the recursing backend.
+      </para>
+      <para>
+       If a Recursion Desired packet PDNS is configured to allow recursion, but not to the IP address of the client, resolution will proceed 
+       as if the RD flag were unset and the answer will indicate that recursion was not available.
+      </para>
+      <para>
+       Recursive questions and answers are not stored in the Packet Cache as recursing backends are generally well equipped to cache questions
+       themselves.
+      </para>
+      <para>
+       It is also possible to use a resolver living on a different port. To do so, specify a recursor like this: 
+       <command>recursor=130.161.180.1:5300</command>.
+      </para>
+      <para>
+       If the backend does not answer a question within a large amount of time, this is logged as 'Recursive query for remote 10.96.0.2 with internal id 0 
+       was not answered by backend within timeout, reusing id'.
+      </para>
+    </sect1>
+    <sect1 id="lazy-recursion"><title>'Lazy recursion'</title>
+      <para>
+       PowerDNS is an authoritative nameserver. Up to version 2.1, a packet indication that recursion was desired, coming from a host from which
+       recursion was allowed, would be handed sight unseen to the recursing backend. This means that older installations do not have the ability to 'override' 
+       the internet with local data. Recursive queries would not be answered from the database.
+      </para>
+      <para>
+       This behaviour sufficed for many users but some installations have a pressing need to override the internet, for example to support recursive 
+       queries for fake domains like 'powerdns.office' or '.internal'. 
+      </para>
+      <para>
+       As of version 2.1, PowerDNS has a feature called 'lazy recursion' where a packet will only be handed to the recursing backend if it cannot be answered
+       completely from the database. 'Completely' in this case means that the original question has an answer in the local database and any additional processing
+       can also succeed from the database.
+      </para>
+      <para>
+       So for example, if you have the 'your.office' domain and a query comes in for its MX record, you should locally have the 'your.office' MX record
+       as well as the IP address of (for example) 'smtp.your.office'. 
+      </para>
+      <para>
+       If any of these conditions fail, your packet is handed to the recursor anyhow. So to benefit from lazy-recursion, be very sure that all 
+       data needed is present locally!.
+      </para>
+      <para>
+       To restore pre-2.1 behaviour, specify <command>lazy-recursion=off</command>.
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="replication"><title>Master/Slave operation &amp; replication</title>
+
+    <para>
+      PDNS offers full master and slave semantics for replicating domain information. Furthermore, PDNS can benefit from native
+      database replication.
+    </para>
+    <sect1 id="native-replication"><title>Native replication</title>
+      <para>
+       Native replication is the default, unless other operation is specifically configured. Native replication basically means that PDNS will
+       not send out DNS update notifications, nor will react to them. PDNS assumes that the backend is taking care of replication unaided.
+      </para>
+      <para>
+       MySQL replication has proven to be very robust and well suited, even over transatlantic connections between badly peering ISPs. Other PDNS
+       users employ Oracle replication which also works very well.
+      </para>
+      <para>
+       To use native replication, configure your backend storage to do the replication and do not configure PDNS to do so.
+      </para>
+    </sect1>
+    <sect1 id="slave"><title>Slave operation</title>
+      <para>
+       On launch, PDNS requests from all backends a list of domains which have not been checked recently for changes. This should happen every 
+       '<command>refresh</command>' seconds, as specified in the SOA record. All domains that are unfresh are then checked for changes over at their
+       master. If the <link linkend="soa-type">SOA</link> serial number there is higher, the domain is retrieved and inserted into the database. In 
+       any case, after the check the domain is declared 'fresh', and will only be checked again after '<command>refresh</command>' seconds have passed.
+      </para>
+      <para>
+       PDNS also reacts to notifies by immediately checking if the zone has updated and if so, retransfering it.
+      </para>
+      <para>
+       All backends which implement this feature must make sure that they can handle transactions so as to not leave the zone in a half updated state. 
+       MySQL configured with either BerkeleyDB or InnoDB meets this requirement, as do PostgreSQL and Oracle. The Bindbackend implements transaction
+       semantics by renaming files if and only if they have been retrieved completely and parsed correctly.
+      </para>
+      <sect2 id=supermaster><title>Supermaster automatic provisioning of slaves</title>
+       <para>
+         PDNS can recognize so called 'supermasters'. A supermaster is a host which is master for domains and for which we are to be a slave. When
+         a master (re)loads a domain, it sends out a notification to its slaves. Normally, such a notification is only accepted if PDNS already 
+         knows that it is a slave for a domain.
+       </para>
+       <para>
+         However, a notification from a supermaster carries more persuasion. When PDNS determines that a notification comes from a supermaster and it is 
+         is bonafide, PDNS can provision the domain automatically, and configure itself as a slave for that zone.
+       </para>
+       <para>
+         To enable this feature, a backend needs to know about the IP address of the supermaster, and how PDNS will be listed in the set of
+         NS records remotely, and the 'account' name of your supermaster. There is no need to fill this out but it does help keep track of
+         where a domain comes from.
+       </para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="master"><title>Master operation</title>
+      <para>
+       When operating as a master, PDNS sends out notifications of changes to slaves, which react to these notifications by querying PDNS to see
+       if the zone changed, and transferring its contents if it has. Notifications are a way to promptly propagate zone changes to slaves, as 
+       described in RFC 1996.
+      </para>
+      <para>
+       Left open by RFC 1996 is who is to be notified - which is harder to figure out than it sounds. All slaves for this domain must receive a notification
+       but the nameserver only knows the names of the slaves - not the IP addresses, which is where the problem lies. The nameserver itself might
+       be authoritative for the name of its secondary, but not have the data available.
+      </para>
+      <para>
+       To resolve this issue, PDNS tries multiple tactics to figure out the IP addresses of the slaves, and notifies everybody. In contrived configurations
+       this may lead to duplicate notifications being sent out, which shouldn't hurt.
+      </para>
+      <para>
+       Some backends may be able to detect zone changes, others may chose to let the operator indicate which zones have changed and which haven't.
+       Consult the documentation for your backend to see how it processes changes in zones.
+      </para>
+      <para>
+       To help deal with slaves that may have missed notifications, or have failed to respond to them, several override commands are available via 
+       the pdns_control tool (<xref linkend="pdnscontrol">):
+      </para>
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>pdns_control notify <command>domain</command></term>
+           <listitem>
+             <para>
+               This instructs PDNS to notify all IP addresses it considers to be slaves of this domain. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>pdns_control notify-host <command>domain ip-address</command></term>
+           <listitem>
+             <para>
+               This is truly an override and sends a notification to an arbitrary IP address. Can be used in 'also-notify' situations
+               or when PDNS has trouble figuring out who to notify - which may happen in contrived configurations.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="fancy-records"><title>Fancy records for seamless email and URL integration</title>
+
+    <para>
+      PDNS also supports so called 'fancy' records. A Fancy Record is actually not a DNS record, but it is translated into one. Currently,
+      two fancy records are implemented, but not very useful without additional unreleased software. For completeness, they are listed here.
+      The software will become available later on and is part of the Express and PowerMail suite of programs.
+    </para>
+    <para>
+      These records imply extra database lookups which has a performance impact. Therefore fancy records are only queried for if they are enabled
+      with the <command>fancy-records</command> command in <filename>pdns.conf</filename>. 
+    </para>
+    <para>
+      <variablelist>
+       <varlistentry>
+         <term>MBOXFW</term>
+         <listitem>
+           <para>
+             This record denotes an email forward. A typical entry looks like this:
+             <screen>
+               support@yourdomain.com     MBOXFW       you@yourcompany.com
+             </screen>
+             When PDNS encounters a request for an MX record for yourdomain.com it will, if fancy records are enabled, also check for the existence
+             of an MBOXFW record ending on '@yourdomain.com', in which case it will hand out a record containing the configured 
+             <command>smtpredirector</command>. This server should then also be able to access the PDNS database to figure out where mail to 
+             support@yourdomain.com should go to.
+           </para>
+         </listitem>
+       <varlistentry>
+         <term>URL</term>
+         <listitem>
+           <para>
+             URL records work in much the same way, but for HTTP. A sample record:
+             <screen>
+               yourdomain.com     URL       http://somewhere.else.com/yourdomain
+             </screen>
+             A URL record is converted into an A record containing the IP address configured with the <command>urlredirector</command>
+             setting. On that IP address a webserver should live that knows how to redirect yourdomain.com to 
+             http://somewhere.else.com/yourdomain.
+           </para>
+         </listitem>
+       </varlistentry>
+      </variablelist>
+    </para>
+  </chapter>
+  <chapter id="all-settings"><title>Index of all settings</title>
+    <para>
+      All PDNS settings are listed here, excluding those that originate from backends, which are documented in the relevant chapters.
+      <variablelist>
+       <varlistentry>
+         <term><anchor id="allow-axfr-ips">allow-axfr-ips=...</term>
+         <listitem>
+           <para>When not allowing AXFR (disable-axfr), DO allow from these IP addresses or netmasks.
+           </para>
+         </listitem></varlistentry>
+       <varlistentry>
+         <term>allow-recursion=...</term>
+         <listitem>
+           <para>
+             By specifying <command>allow-recursion</command>, recursion can be restricted to netmasks specified. The default is to allow
+             recursion from everywhere. Example: <command>allow-recursion=192.168.0.0/24, 10.0.0.0/8, 1.2.3.4</command>.
+           </para>
+         </listitem></varlistentry>
+         <varlistentry><term>cache-ttl=...</term>
+           <listitem><para>
+               Seconds to store packets in the PacketCache. See <xref linkend="packetcache">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>chroot=...</term>
+           <listitem><para>
+               If set, chroot to this directory for more security. See <xref linkend="security">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>config-dir=...</term>
+           <listitem><para>
+               Location of configuration directory (pdns.conf)
+             </para></listitem></varlistentry>
+         <varlistentry><term>config-name=...</term>
+           <listitem><para>
+               Name of this virtual configuration - will rename the binary image. See <xref linkend="virtual">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>control-console=...</term>
+           <listitem><para>
+               Debugging switch - don't use.
+             </para></listitem></varlistentry>
+         <varlistentry><term>daemon=...</term>
+           <listitem><para>
+               Operate as a daemon
+             </para></listitem></varlistentry>
+         <varlistentry><term>default-soa-name=...</term>
+           <listitem><para>
+               name to insert in the SOA record if none set in the backend
+             </para></listitem></varlistentry>
+         <varlistentry><term>disable-axfr=...</term>
+           <listitem><para>
+               Do not allow zone transfers
+             </para></listitem></varlistentry>
+         <varlistentry><term>disable-tcp=...</term>
+           <listitem><para>
+               Do not listen to TCP queries. Breaks RFC compliance.
+             </para></listitem></varlistentry>
+         <varlistentry><term>distributor-threads=...</term>
+           <listitem><para>
+               Default number of Distributor (backend) threads to start. See <xref linkend="performance">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>fancy-records=...</term>
+           <listitem><para>
+               Process URL and MBOXFW records. See <xref linkend="fancy-records">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>guardian | --guardian=yes | --guardian=no</term>
+           <listitem><para>
+               Run within a guardian process. See <xref linkend="guardian">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>help</term>
+           <listitem><para>
+               Provide a helpful message
+             </para></listitem></varlistentry>
+         <varlistentry><term>launch=...</term>
+           <listitem><para>
+               Which backends to launch and order to query them in. See <xref linkend="modules">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>lazy-recursion=...</term>
+           <listitem><para>
+             On by default as of 2.1. Checks local data first before recursing. See <xref linkend="recursion">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>load-modules=...</term>
+           <listitem><para>
+               Load this module - supply absolute or relative path. See <xref linkend="modules">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>local-address=...</term>
+           <listitem><para>
+               Local IP address to which we bind. You can specify multiple addresses separated by commas or whitespace.
+             </para></listitem></varlistentry>
+         <varlistentry><term>local-port=...</term>
+           <listitem><para>
+               The port on which we listen. Only one port possible.
+             </para></listitem></varlistentry>
+         <varlistentry><term><anchor id="log-failed-updates">log-failed-updates=...</term>
+           <listitem><para>
+             If set to 'no', failed Windows Dynamic Updates will not be logged.
+             </para></listitem></varlistentry>
+         <varlistentry><term><anchor id="log-dns-details">log-dns-details=...</term>
+           <listitem><para>
+             If set to 'no', informative-only DNS details will not even be sent to syslog, improving performance. Available from 2.5 
+             and onwards.
+             </para></listitem></varlistentry>
+         <varlistentry><term>logging-facility=...</term>
+           <listitem><para>
+             If set to a a digit, logging is performed under this LOCAL facility. See <xref linkend="syslog">. Available from 1.99.9 and onwards.
+             </para></listitem></varlistentry>
+         <varlistentry><term>loglevel=...</term>
+           <listitem><para>
+               Amount of logging. Higher is more. Do not set below 3
+             </para></listitem></varlistentry>
+         <varlistentry><term>max-queue-length=...</term>
+           <listitem><para>
+             If this many packets are waiting for database attention, consider the situation hopeless and respawn.
+             </para></listitem></varlistentry>
+         <varlistentry><term>module-dir=...</term>
+           <listitem><para>
+               Default directory for modules. See <xref linkend="modules">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>negquery-cache-ttl=...</term>
+           <listitem><para>
+               Seconds to store queries with no answer in the Query Cache. See <xref linkend="querycache">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>no-config</term>
+           <listitem><para>
+             Do not attempt to read the configuration file.
+             </para></listitem></varlistentry>
+         <varlistentry><term>out-of-zone-additional-processing | --out-of-zone-additional-processing=yes | --out-of-zone-additional-processing=no</term>
+           <listitem><para>
+               Do out of zone additional processing
+             </para></listitem></varlistentry>
+         <varlistentry><term>query-cache-ttl=...</term>
+           <listitem><para>
+             Seconds to store queries with an answer in the Query Cache. See <xref linkend="querycache">.
+           </para></listitem></varlistentry>
+       <varlistentry><term>queue-limit=...</term>
+           <listitem><para>
+               Maximum number of miliseconds to queue a query. See <xref linkend="performance">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>query-logging | query-logging=yes | query-logging=no</term>
+           <listitem><para>
+             Hints to a backend that it should log a textual representation of queries it performs. Can be set at runtime.
+             </para></listitem></varlistentry>
+         <varlistentry><term>recursive-cache-ttl=...</term>
+           <listitem><para>
+               Seconds to store recursive packets in the PacketCache. See <xref linkend="packetcache">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>recursor=...</term>
+           <listitem><para>
+             If set, recursive queries will be handed to the recursor specified here. See <xref linkend="recursion">.
+           </para></listitem></varlistentry>
+       <varlistentry><term>setgid=...</term>
+           <listitem><para>
+             If set, change group id to this gid for more security. See <xref linkend="security">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>setuid=...</term>
+           <listitem><para>
+               If set, change user id to this uid for more security. See <xref linkend="security">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>skip-cname | --skip-cname=yes | --skip-cname=no</term>
+           <listitem><para>
+               Do not perform CNAME indirection for each query. Has performance implications. See <xref linkend="security">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>slave-cycle-interval=60</term>
+           <listitem><para>
+             Schedule slave up-to-date checks of domains whose status is unknown every .. seconds. See <xref linkend="fancy-records">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>smtpredirector=...</term>
+           <listitem><para>
+               Our smtpredir MX host. See <xref linkend="fancy-records">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>soa-serial-offset=...</term>
+           <listitem><para>
+             If your database contains single-digit SOA serials and you need to host .DE domains, this setting can help
+             placate their 6-digit SOA serial requirements. Suggested value is to set this to 1000000 which adds 1000000 to all SOA Serials
+             under that offset.
+             </para></listitem></varlistentry>
+         <varlistentry><term>socket-dir=...</term>
+           <listitem><para>
+               Where the controlsocket will live. See <xref linkend="controlsocket">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>strict-rfc-axfrs | --strict-rfc-axfrs=yes | --strict-rfc-axfrs=no</term>
+           <listitem><para>
+             Perform strictly RFC conformant AXFRs, which are slow, but needed to placate some old client tools.
+             </para></listitem></varlistentry>
+         <varlistentry><term>urlredirector=...</term>
+           <listitem><para>
+               Where we send hosts to that need to be url redirected. See <xref linkend="fancy-records">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>webserver | --webserver=yes | --webserver=no</term>
+           <listitem><para>
+               Start a webserver for monitoring. See <xref linkend="monitoring">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>webserver-address=...</term>
+           <listitem><para>
+               IP Address of webserver to listen on. See <xref linkend="monitoring">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>webserver-password=...</term>
+           <listitem><para>
+               Password required for accessing the webserver. See <xref linkend="monitoring">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>webserver-port=...</term>
+           <listitem><para>
+               Port of webserver to listen on. See <xref linkend="monitoring">.
+             </para></listitem></varlistentry>
+         <varlistentry><term>wildcard-url=...</term>
+           <listitem><para>
+             Check for wildcard URL records.
+             </para></listitem></varlistentry>
+         <varlistentry><term>wildcards=...</term>
+           <listitem><para>
+               Honor wildcards in the database. On by default. Turning this off has performance implications, see <xref linkend="performance">.
+             </para></listitem></varlistentry>
+      </variablelist>
+    </para>
+  </chapter>
+  <chapter id="metrics"><title>Index of all internal metrics</title>
+    <para></para>
+      <sect1 id="counters-variables"><title>Counters &amp; variables</title>
+      <para>
+      A number of counters and variables are set during PDNS operation. These can be queried with the init.d
+      <command>dump</command>, <command>show</command> and <command>mrtg</command> commands, or viewed with the
+      webserver.
+      
+      <variablelist>
+       <varlistentry>
+         <term>corrupt-packets</term>
+         <listitem><para>Number of corrupt packets received</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>latency</term>
+         <listitem><para>Average number of microseconds a packet spends within PDNS</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>packetcache-hit</term>
+         <listitem><para>Number of packets which were answered out of the cache</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>packetcache-miss</term>
+         <listitem><para>Number of times a packet could not be answered out of the cache</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>packetcache-size</term>
+         <listitem><para>Amount of packets in the packetcache</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>qsize-a</term>
+         <listitem><para>Size of the queue before the transmitting socket.</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>qsize-q</term>
+         <listitem><para>Number of packets waiting for database attention</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>servfail-packets</term>
+         <listitem><para>Amount of packets that could not be answered due to database problems</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>tcp-answers</term>
+         <listitem><para>Number of answers sent out over TCP</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>tcp-questions</term>
+         <listitem><para>Number of questions received over TCP</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>timedout-questions</term>
+         <listitem><para>Amount of packets that were dropped because they had to wait too long internally</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>udp-answers</term>
+         <listitem><para>Number of answers sent out over UDP</para></listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>udp-questions</term>
+         <listitem><para>Number of questions received over UDP</para></listitem>
+       </varlistentry>
+      </variablelist>
+    </para>
+    <para>
+      <sect2><title>Ring buffers</title>
+       <para>
+         Besides counters, PDNS also maintains the ringbuffers. A ringbuffer records events, each new event gets a place
+         in the buffer until it is full. When full, earlier entries get overwritten, hence the name 'ring'.
+       </para>
+    <para>
+      By counting the entries in the buffer, statistics can be generated. These statistics can currently only be viewed 
+      using the webserver and are in fact not even collected without the webserver running. 
+    </para>
+    <para>
+      The following ringbuffers are available:
+    </para>
+    <para>
+    <variablelist>
+      <varlistentry>
+       <term>Log messages (logmessages)</term>
+       <listitem><para>All messages logged</para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Queries for existing records but for a type we don't have (noerror-queries)</term>
+       <listitem><para>Queries for, say, the AAAA record of a domain, when only an A is available. 
+         Queries are listed in the following format: name/type. So an AAA query for pdns.powerdns.com looks like
+         pdns.powerdns.com/AAAA.</para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Queries for non-existing records within existing domains(nxdomain-queries)</term>
+       <listitem><para>If PDNS knows it is authoritative over a domain, and it sees a question for a record in that domain
+           that does not exist, it is able to send out an authoritative 'no such domain' message. Indicates that hosts are
+           trying to connect to services really not in your zone.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>UDP queries received (udp-queries)</term>
+       <listitem><para>
+           All UDP queries seen.
+         </para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Remote server IP addresses (remotes)</term>
+       <listitem><para>
+           Hosts querying PDNS. Be aware that UDP is anonymous - person A can send queries that appear to be coming from
+           person B.
+         </para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Remotes sending corrupt packets (remote-corrupts)</term>
+       <listitem><para>
+           Hosts sending PDNS broken packets, possibly meant to disrupt service. Be aware that UDP is 
+           anonymous - person A can send queries that appear to be coming from person B.
+         </para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Remotes querying domains for which we are not auth (remote-unauth)</term>
+       <listitem><para>
+           It may happen that there are misconfigured hosts on the internet which are configured to
+           think that a PDNS installation is in fact a resolving nameserver. These hosts will not
+           get useful answers from PDNS. This buffer lists hosts sending queries for domains which 
+           PDNS does not know about.
+         </para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Queries that could not be answered due to backend errors (servfail-queries)</term>
+       <listitem><para>
+           For one reason or another, a backend may be unable to extract answers for a certain domain from
+           its storage. This may be due to a corrupt database or to inconsistent data. When this happens,
+           PDNS sends out a 'servfail' packet indicating that it was unable to answer the question. This buffer
+           shows which queries have been causing servfails.
+         </para></listitem>
+      </varlistentry>
+      <varlistentry>
+       <term>Queries for domains that we are not authoritative for (unauth-queries)</term>
+       <listitem><para>
+           If a domain is delegated to a PDNS instance, but the backend is not made aware of this fact, questions come
+           in for which no answer is available, nor is the authority. Use this ringbuffer to spot such queries.
+         </para></listitem>
+      </varlistentry>
+    </variablelist>
+  </para>
+  </chapter>
+
+  <chapter id="types"><title>Supported record types and their storage</title>
+    <para>
+      This chapter lists all record types PDNS supports, and how they are stored in backends. The list is mostly alphabetical but
+      some types are grouped.
+    <variablelist>
+      <varlistentry>
+       <term>A</term>
+         <listitem>
+           <para>
+             The A record contains an IP address. It is stored as a decimal dotted quad string,
+             for example: '213.244.168.210'.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>AAAA</term>
+         <listitem>
+           <para>
+             The AAAA record contains an IPv6 address. It is stored as a decimal dotted quad string,
+             for example: '3ffe:8114:2000:bf0::1'. 
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>CNAME</term>
+         <listitem>
+           <para>
+             The CNAME record specifies the canonical name of a record. It is stored plainly. Like all other records, it is not
+             terminated by a dot. A sample might be 'webserver-01.yourcompany.com'.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>HINFO</term>
+         <listitem>
+           <para>
+             Hardware Info record, used to specify CPU and operating system. Stored with a single space separating these two, 
+             example: 'i386 Linux'.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>MX</term>
+         <listitem>
+           <para>
+             The MX record specifies a mail exchanger host for a domain. Each mail exchanger also has a priority or preference.
+             This should be specified in the separate field dedicated for that purpose, often called 'prio'. 
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term><anchor id="naptr">NAPTR</term>
+         <listitem>
+           <para>
+
+             Naming Authority Pointer, RFC 2915. Stored as follows:
+             <screen>
+             '100  50  "s"  "z3950+I2L+I2C"     ""  _z3950._tcp.gatech.edu'. 
+             </screen>
+             The fields are: order, preference, flags, service, regex, 
+             replacement. Note that the replacement is not enclosed in quotes, and should not be. The replacement may be omitted, in which 
+             case it is empty. See also RFC 2916 for how to use NAPTR for ENUM (E.164) purposes.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>NS</term>
+         <listitem>
+           <para>
+             Nameserver record. Specifies nameservers for a domain. Stored plainly: 'ns1.powerdns.com', as always without a terminating dot.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>PTR</term>
+         <listitem>
+           <para>
+             Reverse pointer, used to specify the host name belonging to an IP or IPv6 address. Name is stored plainly: 'www.powerdns.com'.
+             As always, no terminating dot.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>RP</term>
+         <listitem>
+           <para>
+             Responsible Person record, as described in RFC 1183. Stored with a single space between the mailbox name and the more-information
+             pointer. Example 'peter.powerdns.com peter.people.powerdns.com', to indicate that peter@powerdns.com is responsible and that more 
+             information about peter is available by querying the TXT record of peter.people.powerdns.com.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term><anchor id="soa-type">SOA</term>
+         <listitem>
+           <para>
+             The Start of Authority record is one of the most complex available. It specifies a lot about a domain: the name 
+             of the master nameserver ('the primary'), the hostmaster and a set of numbers indicating how the data in this domain
+             expires and how often it needs to be checked. Further more, it contains a serial number which should rise on each change
+             of the domain.
+           </para>
+           <para>
+             The stored format is:
+             <screen>
+               primary hostmaster serial refresh retry expire default_ttl
+             </screen>
+             Besides the primary and the hostmaster, all fields are numerical. PDNS has a set of default values:
+             <table>
+               <title>SOA fields</title>
+               <tgroup cols=2>
+                 <tbody>
+                   <row>
+                     <entry>primary</entry><entry><command>default-soa-name</command> configuration option</entry>
+                   </row>
+                   <row>
+                     <entry>hostmaster</entry><entry>hostmaster@domain-name</entry>
+                   </row>
+                   <row>
+                     <entry>serial</entry><entry>0</entry>
+                   </row>
+                   <row>
+                     <entry>refresh</entry><entry>10800 (3 hours)</entry>
+                   </row>
+                   <row>
+                     <entry>retry</entry><entry>3600 (1 hour)</entry>
+                   </row>
+                   <row>
+                     <entry>expire</entry><entry>604800 (1 week)</entry>
+                   </row>
+                   <row>
+                     <entry>default_ttl</entry><entry>3600 (1 hour)</entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+             </table>
+           </para>
+           <para>
+             The fields have complicated and sometimes controversial meanings. The 'serial' field is special. If left at 0, the default,
+             PDNS will perform an internal list of the domain to determine highest change_date field of all records within the zone, and use
+             that as the zone serial number. This means that the serial number is always raised when changes are made to the zone, as long
+             as the change_date field is being set.
+           </para>
+         </listitem>      
+       </varlistentry>
+       <varlistentry>
+         <term>TXT</term>
+         <listitem>
+           <para>
+             The TXT field can be used to attach textual data to a domain. Text is stored plainly.
+           </para>
+         </listitem>      
+       </varlistentry>
+      </variablelist>
+    </para>
+  </chapter>
+  <chapter id="faq"><title>HOWTO &amp; Frequently Asked Questions</title>
+    <para>
+      This chapter contains a number of FAQs and HOWTOs.
+    </para>
+    <sect1 id="pdns-devel-faq"><title>Backend developer HOWTO</title>
+      <para>
+       Writing backends without access to the full PDNS source means that you need to write code that can be loaded by PDNS at runtime. 
+       This in turn means that you need to use the same compiler that we do. For linux, this is currently GCC 3.0.4, although any 3.0.x 
+       compiler is probably fine. In tests, even 3.1 works.
+      </para>
+      <para>
+       For FreeBSD we use GCC 2.95.2.
+      </para>
+      <para>
+       Furthermore, your pdns_server executable must be dynamically linked. The default .rpm PDNS contains a static binary so you need to retrieve the
+       dynamic rpm or the dynamic tar.gz or the Debian unstable ('Woody') deb. FreeBSD dynamic releases are forthcoming.
+      </para>
+      <variablelist>
+       <varlistentry>
+         <term>Q: Will PDNS drivers work with other PDNS versions than they were compiled for?</term>
+         <listitem>
+           <para>
+             A: 'Probably'. We make no guarantees. Efforts have been made to keep the interface between the backend and PDNS as thin
+             as possible. For example, a backend compiled with the 1.99.11 backend development kit works with 1.99.10. But don't count on it.
+             We will notify when we think an incompatible API change has occured but you are best off recompiling your driver for each
+             new PDNS release.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: What is in that DNSPacket * pointer passed to lookup!</term>
+         <listitem>
+           <para>
+             A: For reasons outlined above, you should treat that pointer as opaque and only access it via the <function>getRemote()</function> 
+             functions made available and documented above. The DNSPacket class changes a lot and this level of indirection allows for greater
+             changes to be made without changing the API to the backend coder.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: How is the PowerDNS Open Source Backend Development Kit licensed?</term>
+         <listitem>
+           <para>
+             A: MIT X11, a very liberal license permitting basically everything.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: Can I release the backend I wrote?</term>
+         <listitem>
+           <para>
+             A: Please do! If you tell us about it we will list you on our page.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: Can I sell backends I wrote?</term>
+         <listitem>
+           <para>
+             A: You can. Again, if you tell us about them we will list your backend on the site. You can keep the source of your backend
+             secret if you want, or you can share it with the world under any license of your chosing.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: Will PowerDNS use my code in the PDNS distribution?</term>
+         <listitem>
+           <para>
+             A: If your license permits it and we like your backend, we sure will.  If your license does not permit it but we like your 
+             backend anyway we may contact you. 
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: My backend compiles but when I try to load it, it says 'undefined symbol: _Z13BackendMakersv'</term>
+         <listitem>
+           <para>
+             A: Your pdns_server binary is static and cannot load a backend driver at runtime. Get a dynamic version of pdns, or complain 
+             to pdns@powerdns.com if one isn't available. To check what kind of binary you have, execute 'file $(which pdns_server)'.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: My backend compiles but when I try to load it, it says 'undefined symbol: BackendMakers__Fv'</term>
+         <listitem>
+           <para>
+             A: You compiled with the wrong GCC. Use GCC 3.x for Linux, 2.95.x for FreeBSD. You may want to change g++ to g++-3.0 in the Makefile,
+             or change your path so that 3.x is used.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: I downloaded a dynamic copy of pdns_server but it doesn't run, even without my backend</term>
+         <listitem>
+           <para>
+             A: Run 'ldd' on the pdns_server binary and figure out what libraries you are missing. Most likely you need to install gcc 3.0 libraries, 
+             RedHat 7.1 and 7.2 have packages available, Debian installs these by default if you use the 'unstable deb' of PDNS.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: What I want can't be done from a backend - I need the whole PDNS source</term>
+         <listitem>
+           <para>
+             A: If you require the source, please contact us (pdns@powerdns.com). All commercial licensees receive the source, 
+             for others we may grant exceptions.
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: What is this 'AhuException' I keep reading about?</term>
+         <listitem>
+           <para>
+             A: This name has historical reasons and has <ulink url="http://ds9a.nl">no significance</ulink>. 
+           </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term>Q: I need a backend but I can't write it, can you help?</term>
+         <listitem>
+           <para>
+             A: Yes, we also do custom development. Contact us at pdns@powerdns.com.
+           </para>
+         </listitem>
+       </varlistentry>
+
+      </variablelist>
+    </sect1>
+    <sect1 id="powerdns-company-faq"><title>About PowerDNS.COM BV, 'the company'</title>
+      <para>
+       As of 25 November 2002, the PowerDNS nameserver and its modules are open source. This has led to a lot of questions on the future
+       of both PowerDNS, the company and the products. This FAQ attempts to address these questions.
+      </para>
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>Q: Is PowerDNS 2.9 really open source? What license?</term>
+           <listitem>
+             <para>
+               A: PowerDNS 2.9 is licensed under the GNU General Public License version two, the same license that covers the Linux kernel.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Is the open source version crippled?</term>
+           <listitem>
+             <para>
+               A: It is not. Not a single byte has been omitted.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Is the nameserver abandoned?</term>
+           <listitem>
+             <para>
+               A: Far from it. In fact, we expect development to speed up now that we have joined the open source community.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Why is the nameserver now open source?</term>
+           <listitem>
+             <para>
+               A: In the current economic climate and also the way the Internet is built up right now, selling software is very hard. Most  potential 
+               customers had never before bought a piece of software for their UNIX internet setup. Even though we know (from the recent survey) that
+               nameserver operators love PowerDNS, their suggested price for it is in the $100 range.
+             </para>
+             <para>
+               For us, it makes far more sense to open source PowerDNS than to ask $100 for it. It is expected that open sourcing PowerDNS will lead
+               to far higher adoption rates. We hope that PowerDNS will soon be included in major Linux and UNIX distributions.
+             </para>
+           </listitem>
+         <varlistentry>
+           <term>Q: How does PowerDNS.COM BV expect to make money now that the nameserver is free?</term>
+           <listitem>
+             <para>
+               A: In fact, we don't expect to in the near future. We also don't have a lot of expenses, basically 
+               some hosting and a few domain names. 
+             </para>
+             <para>
+               However, we are available for consulting work, for example to help a large registrar or registry migrate to PowerDNS, or to help
+               integrate our software in existing provisioning systems.
+             </para>
+             <para>
+               Furthermore, non-GPL licenses are available for those needing to do closed source modifications, or for customers 
+               uncomfortable with the GPL. This is much like what <ulink url="http://www.mysql.com/company/index.html">MySQL AB</ulink> is doing now.
+             </para>
+             <para>
+               In fact, their strategy is a lot like ours in general.
+             </para>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Can I buy support contracts for PowerDNS?</term>
+           <listitem>
+             <para>
+               Sure, to do so, please contact us at <email>sales@powerdns.com</email>
+             </para>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Will you accept patches? We've added a feature</term>
+           <listitem>
+             <para>
+               Probably - in general, it is best to discuss your intentions and needs on the <email>pdns-dev@mailman.powerdns.com</email> (<ulink url="http://mailman.powerdns.com/mailman/listinfo/pdns-dev">subscribe</ulink>)
+               mailinglist
+               before doing the work. We may have suggestions or guidelines on how you should implement the feature. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: PowerDNS doesn't work on my platform, will you port it?</term>
+           <term>Q: PowerDNS doesn't have feature I need, will you add it?</term>
+           <listitem>
+             <para>
+               Be sure to ask on the <email>pdns-dev@mailman.powerdns.com</email> (<ulink url="http://mailman.powerdns.com/mailman/listinfo/pdns-dev">subscribe</ulink>) mailinglist. You can even hire us to do work on PowerDNS
+               if plain asking is not persuasive enough. This might be the case if we don't currently have time for your feature, but you
+               need it quickly anyhow, and are not in a position to submit a patch implementing it.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Q: Will <ulink url="http://express.powerdns.com">PowerDNS Express</ulink> be open sourced? 
+             <ulink url="http://www.powerdns.com/powermail/">PowerMail?</ulink></term>
+           <listitem>
+             <para>
+               Perhaps, we're not yet sure. PowerMail most probably.
+             </para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term>Q: We are a Linux/Unix vendor, can we include PowerDNS?
+           <listitem>
+             <para>
+             A: Please do. In fact, we'd be very happy to work with you to make this happen. Contact <email>ahu@ds9a.nl</email> 
+             if you have specific upstream needs.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+    </sect1>
+  </chapter>
+  <Appendix id="backends-detail"><title>Backends in detail</title>
+    <para>
+      This appendix lists several of the available backends in more detail
+    </para>
+    
+    
+    <sect1 id="pipebackend"><title>PipeBackend</title>
+      <para>
+       <table>
+         <title>PipeBackend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>No</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>No</entry></row>
+             <row><entry>Case</entry><entry>Depends</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       The PipeBackend allows for easy dynamic resolution based on a 'Coprocess' which can be written in any
+       programming language that can read a question on standard input and answer on standard output. 
+      </para>
+      <para>
+       To configure, the following settings are available:
+       <variablelist>
+         <varlistentry>
+           <term>pipe-command</term>
+           <listitem>
+             <para>
+               Command to launch as backend. Mandatory.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>pipe-timeout</term>
+           <listitem>
+             <para>
+               Number of milliseconds to wait for an answer from the backend. If this time is ever exceeded, the backend
+               is declared dead and a new process is spawned. Available since 2.7.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>pipe-regex</term>
+           <listitem>
+             <para>
+               If set, only questions matching this regular expression are even sent to the backend. This makes sure that
+               most of PowerDNS does not slow down if you you reploy a slow backend. A query for the A record of 'www.powerdns.com'
+               would be presented to the regex as 'www.powerdns.com;A'. A matching regex would be '^www.powerdns.com;.*$'.
+             </para>
+             <para>
+               To match only ANY and A queries for www.powerdns.com, use '^www.powerdns.com;(A|ANY)$'. Available since 2.8.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      
+      <sect2 id="pipebackend-protocol"><title>PipeBackend protocol</title>
+       <para>
+         Questions come in over a file descriptor, by default standard input. Answers
+         are sent out over another file descriptor, standard output by default.
+       </para>
+       <sect3>
+      <title>Handshake</title>
+      <para>
+        PowerDNS sends out 'HELO\t1', indicating that it wants to speak the
+        protocol as defined in this document, version 1.
+        
+        A PowerDNS CoProcess must then send out a banner, prefixed by 'OK\t', 
+        indicating it launched successfully. If it does not support the indicated
+        version, it should respond with FAIL, but not exit. Suggested behaviour is
+        to try and read a further line, and wait to be terminated.
+      </para></sect3>
+    <sect3><title>Questions</title>
+      <para>
+        Questions come in three forms and are prefixed by a tag indicating the kind:
+       <variablelist>
+         <varlistentry>
+           <term>Q</term>
+           <listitem>
+             <para>
+                Regular queries
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>AXFR</term>
+           <listitem>
+             <para>
+                List requests, which mean that an entire zone should be listed
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>PING</term>
+           <listitem>
+             <para>
+                Check if the coprocess is functioning
+             </para>
+           </listitem>
+         </varlistentry>
+        </variablelist>
+The question format:
+<screen>
+type   qname           qclass  qtype   id      ip-address
+</screen>
+
+Fields are tab separated, and terminated with a single \n. 
+
+Type is the tag above, qname is the domain the question is about. qclass is
+always 'IN' currently, denoting an INternet question. qtype is the kind of
+information desired, the record type, like A, CNAME or AAAA. id can be
+specified to help your backend find an answer if the id is already known
+from an earlier query. You can ignore it.
+
+ip-address is the ip-address of the nameserver asking the question.
+      </para></sect3>
+    <sect3><title>Answers</title>
+      <para>
+
+        Each answer starts with a tag, possibly followed by a TAB and more data.
+       <variablelist>
+         <varlistentry>
+           <term>DATA</term>
+           <listitem>
+             <para>
+                Indicating a successful line of DATA
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>END</term>
+           <listitem>
+             <para>
+                Indicating the end of an answer - no further data
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>FAIL</term>
+           <listitem>
+             <para>
+                Indicating a lookup failure. Also serves as 'END'. No further data.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>LOG</term>
+           <listitem>
+             <para>
+                For specifying things that should be logged. Can only be sent after
+                a query and before an END line. After the tab, the message to be
+                logged
+                
+             </para>
+           </listitem>
+         </varlistentry>
+        </variablelist>
+
+
+        So letting it be known that there is no data consists if sending 'END'
+        without anything else.
+
+
+The answer format:
+<screen>
+DATA   qname           qclass  qtype   ttl     id      content 
+</screen>
+
+'content' is as specified in <xref linkend="types">.
+
+A sample dialogue may look like this:
+<screen>
+Q      www.ds9a.nl     IN      CNAME   -1      213.244.168.210
+DATA   www.ds9a.nl     IN      CNAME   3600    1 ws1.ds9a.nl
+Q      ws1.ds9a.nl     IN      CNAME   -1      213.244.168.210
+END
+Q      wd1.ds9a.nl     IN      A       -1      213.244.168.210
+DATA   ws1.ds9a.nl     IN      A       3600    1       1.2.3.4
+DATA   ws1.ds9a.nl     IN      A       3600    1       1.2.3.5
+DATA   ws1.ds9a.nl     IN      A       3600    1       1.2.3.6
+END
+</screen>
+
+         This would correspond to a remote webserver 213.244.168.210 wanting to
+resolve the IP address of www.ds9a.nl, and PowerDNS traversing the CNAMEs to
+find the IP addresses of ws1.ds9a.nl
+
+Another dialogue might be:
+<screen>
+Q      ds9a.nl         IN      SOA     -1      213.244.168.210
+DATA   ds9a.nl         IN      SOA     86400   1 ahu.ds9a.nl ...
+END
+AXFR   1
+DATA   ds9a.nl         IN      SOA     86400   1 ahu.ds9a.nl ...
+DATA   ds9a.nl         IN      NS      86400   1 ns1.ds9a.nl
+DATA   ds9a.nl         IN      NS      86400   1 ns2.ds9a.nl
+DATA   ns1.ds9a.nl     IN      A       86400   1 213.244.168.210
+DATA   ns2.ds9a.nl     IN      A       86400   1 63.123.33.135
+.
+.
+END
+</screen>
+
+This is a typical zone transfer.
+         </para>
+       </sect3>
+       <sect3>
+       <title>Sample perl backend</title>
+       <para>
+       <screen>
+#!/usr/bin/perl -w
+# sample PowerDNS Coprocess backend
+#
+
+use strict;
+
+
+$|=1;                                  # no buffering
+
+my $line=&lt;&gt;;
+chomp($line);
+
+unless($line eq "HELO\t1") {
+       print "FAIL\n";
+       print STDERR "Recevied '$line'\n";
+       &lt;&gt;;
+       exit;
+}
+print "OK      Sample backend firing up\n";    # print our banner
+
+while(&lt;&gt;)
+{
+       print STDERR "$$ Received: $_";
+       chomp();
+       my @arr=split(/\t/);
+       if(@arr&lt;6) {
+               print "LOG      PowerDNS sent unparseable line\n";
+               print "FAIL\n";
+               next;
+       }
+
+       my ($type,$qname,$qclass,$qtype,$id,$ip)=split(/\t/);
+
+       if(($qtype eq "A" || $qtype eq "ANY") && $qname eq "webserver.example.com") {
+               print STDERR "$$ Sent A records\n";
+               print "DATA     $qname  $qclass A       3600    -1      1.2.3.4\n";
+               print "DATA     $qname  $qclass A       3600    -1      1.2.3.5\n";
+               print "DATA     $qname  $qclass A       3600    -1      1.2.3.6\n";
+       }
+       elsif(($qtype eq "CNAME" || $qtype eq "ANY") && $qname eq "www.example.com") {
+               print STDERR "$$ Sent CNAME records\n";
+               print "DATA     $qname  $qclass CNAME   3600    -1      webserver.example.com\n";
+       }
+       elsif($qtype eq "MBOXFW") {
+               print STDERR "$$ Sent MBOXFW records\n";
+               print "DATA     $qname  $qclass MBOXFW  3600    -1      powerdns\@example.com\n";
+       }
+
+
+       print STDERR "$$ End of data\n";
+       print "END\n";
+}
+         </screen>
+       </para>
+       </sect3>
+      </sect2>
+                 
+    </sect1>
+    <sect1 id="mysqlbackend"><Title>MySQL backend</title>
+      <para>
+       <table>
+         <title>MySQL backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>No</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+             <row><entry>Case</entry><entry>Insensitive</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+        The MySQL Backend as present in PDNS is fixed - it requires a certain database schema to function. This schema corresponds to this create statement:
+        
+        <screen>
+          CREATE TABLE records (
+         id int(11) NOT NULL auto_increment,
+         domain_id int(11) default NULL,
+         name varchar(255) default NULL,
+         type varchar(6) default NULL,
+         content varchar(255) default NULL,
+         ttl int(11) default NULL,
+         prio int(11) default NULL,
+         change_date int(11) default NULL,
+         PRIMARY KEY (id),
+         KEY name_index(name),
+         KEY nametype_index(name,type),
+         KEY domainid_index(domain_id)
+         );
+        </screen>
+        
+        Every domain should have a unique domain_id, which should remain identical for all records in a domain. Records with a domain_id that
+       differs from that in the domain SOA record will not appear in a zone transfer.
+
+      </para>
+      <para>
+       The change_date may optionally
+        be updated to the time_t (the number of seconds since midnight UTC at the start of 1970), and is in that case used to auto calculate the 
+        SOA serial number in case that is unspecified.
+        
+      </para>
+      <sect2><title>Configuration settings</title>
+        <para>
+         WARNING! Make sure that you can actually resolve the hostname of your database without accessing the database! It is advised to supply
+         an IP address here to prevent chicken/egg problems!
+       </para>
+       <para>
+          <variablelist>
+            <varlistentry>
+              <term>mysql-dbname</term>
+              <listitem>
+                <para>
+                  Database name to connect to
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>mysql-host</term>
+              <listitem>
+                <para>
+                  Database host to connect to
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>mysql-password</term>
+              <listitem>
+                <para>
+                  Password to connect with
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>mysql-socket</term>
+              <listitem>
+                <para>
+                  MySQL socket to use for connecting
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>mysql-table</term>
+              <listitem>
+                <para>
+                  MySQL table name. Defaults to 'records'.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>mysql-user</term>
+              <listitem>
+                <para>
+                  MySQL user to connect as
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+       </para>
+      </sect2>
+      <sect2><title>Notes</title>
+       <para>
+         It has been observed that InnoDB tables outperform the default MyISAM tables by a large margin. Furthermore, the default 
+         number of backends (3) should be raised to 10 or 15 for busy servers.
+       </para>
+      </sect2>
+      
+    </sect1>
+    <sect1 id="pdnsbackend"><Title>MySQL PDNS backend</title>
+      <para>
+       <table>
+         <title>MySQL backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>No</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+             <row><entry>Case</entry><entry>Insensitive</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       This is the driver that corresponds to the set of XML-RPC tools available from PowerDNS. For database schemas, see there.
+      </para>
+      <para>
+       It takes a number of parameters:
+      </para>
+       <para>
+          <variablelist>
+            <varlistentry>
+              <term>pdns-dbname</term>
+              <listitem>
+                <para>
+                  Database name to connect to
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>pdns-host</term>
+              <listitem>
+                <para>
+                  Database host to connect to
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>pdns-password</term>
+              <listitem>
+                <para>
+                  Password to connect with
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>pdns-socket</term>
+              <listitem>
+                <para>
+                  MySQL socket to use for connecting
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>pdns-user</term>
+              <listitem>
+                <para>
+                  MySQL user to connect as
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+       </para>
+      <sect2><title>Notes</title>
+       <para>
+         It has been observed that InnoDB tables outperform the default MyISAM tables by a large margin. Furthermore, the default 
+         number of backends (3) should be raised to 10 or 15 for busy servers.
+       </para>
+      </sect2>
+      
+    </sect1>
+
+    <sect1 id="generic-mypgsql-backends"><Title>Generic MySQL and PgSQL backends</title>
+      <para>
+       <table>
+         <title>Generic PgSQL and MySQL backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Module name</entry><entry>gpgsql / gmysql</entry></row>
+             <row><entry>Native</entry><entry>Yes - but PostgreSQL does not replicate</entry></row>
+             <row><entry>Master</entry><entry>Yes</entry></row>
+             <row><entry>Slave</entry><entry>Yes</entry></row>
+             <row><entry>Superslave</entry><entry>Yes</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+             <row><entry>Case</entry><entry>All lower</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       PostgreSQL and MySQL backend with easily configurable SQL statements, allowing you to graft PDNS on any PostgreSQL or MySQL database of your choosing. 
+       Because all database schemas will be different, a generic backend is needed to cover all needs. 
+      </para>          
+      <para>
+       The template queries are expanded using the C function 'snprintf' which implies that substitutions are performed on the basis of %-place holders. 
+       To place a a % in a query which will not be substituted, use %%. Make sure to fill out the search key, often called 'name' in lower case!
+      </para>
+      <para>
+       There are in fact two backends, one for PostgreSQL and one for MySQL but they accept the same settings and use almost exactly the same database schema.
+      </para>
+      <sect2><title>MySQL specifics</title>
+       <para>
+         <warning>
+           <para>
+             As of 2.3, the Generic MySQL backend has not been tested a lot. Use the regular MySQL backend if unsure! Especially 'master' support is 
+             very new.
+           </para>
+         </warning>
+         <warning>
+           <para>
+             If using MySQL with 'slave' support enabled in PowerDNS you <emphasis>must</emphasis> run MySQL with a table engine that supports transactions.
+           </para>
+         </warning>
+       </para>
+       <para>
+         In practice, great results are achieved with the 'InnoDB' tables. PowerDNS will silently function with non-transaction aware MySQLs but at one point
+         this is going to harm your database, for example when an incoming zone transfer fails.
+       </para>
+       <para>
+         The default setup conforms to the following schema:
+         <programlisting>
+create table domains (
+ id             INT auto_increment,
+ name           VARCHAR(255) NOT NULL,
+ master                 VARCHAR(20) DEFAULT NULL,
+ last_check     INT DEFAULT NULL,
+ type           VARCHAR(6) NOT NULL,
+ notified_serial INT DEFAULT NULL, 
+ account         VARCHAR(40) DEFAULT NULL,
+ primary key (id)
+)type=InnoDB;
+
+CREATE UNIQUE INDEX name_index ON domains(name);
+
+CREATE TABLE records (
+  id              INT auto_increment,
+  domain_id       INT DEFAULT NULL,
+  name            VARCHAR(255) DEFAULT NULL,
+  type            VARCHAR(6) DEFAULT NULL,
+  content         VARCHAR(255) DEFAULT NULL,
+  ttl             INT DEFAULT NULL,
+  prio            INT DEFAULT NULL,
+  change_date     INT DEFAULT NULL,
+  primary key(id)
+)type=InnoDB;
+
+CREATE INDEX rec_name_index ON records(name);
+CREATE INDEX nametype_index ON records(name,type);
+CREATE INDEX domain_id ON records(domain_id);
+
+create table supermasters (
+  ip VARCHAR(25) NOT NULL, 
+  nameserver VARCHAR(255) NOT NULL, 
+  account VARCHAR(40) DEFAULT NULL
+);
+
+GRANT SELECT ON supermasters TO pdns;
+GRANT ALL ON domains TO pdns;
+GRANT ALL ON records TO pdns;
+         </programlisting>
+       </para>
+       <para>
+         This schema contains all elements needed for master, slave and superslave operation. Depending on which features will be used, the 'GRANT' statements
+         can be trimmed to make sure PDNS cannot subvert the contents of your database.
+       </para>
+       <para>
+         Zone2sql with the --gmysql flag also assumes this layout is in place.
+       </para>
+      </sect2>
+      <sect2><title>PostgresSQL specifics</title>
+      <para>
+       The default setup conforms to the following schema:
+       <programlisting>
+create table domains (
+ id             SERIAL PRIMARY KEY,
+ name           VARCHAR(255) NOT NULL,
+ master                 VARCHAR(20) DEFAULT NULL,
+ last_check     INT DEFAULT NULL,
+ type           VARCHAR(6) NOT NULL,
+ notified_serial INT DEFAULT NULL, 
+ account         VARCHAR(40) DEFAULT NULL
+);
+CREATE UNIQUE INDEX name_index ON domains(name);
+  
+CREATE TABLE records (
+        id              SERIAL PRIMARY KEY,
+        domain_id       INT DEFAULT NULL,
+        name            VARCHAR(255) DEFAULT NULL,
+        type            VARCHAR(6) DEFAULT NULL,
+        content         VARCHAR(255) DEFAULT NULL,
+        ttl             INT DEFAULT NULL,
+        prio            INT DEFAULT NULL,
+        change_date     INT DEFAULT NULL, 
+        CONSTRAINT domain_exists 
+        FOREIGN KEY(domain_id) REFERENCES domains(id)
+        ON DELETE CASCADE
+);
+
+CREATE INDEX rec_name_index ON records(name);
+CREATE INDEX nametype_index ON records(name,type);
+CREATE INDEX domain_id ON records(domain_id);
+
+create table supermasters (
+         ip VARCHAR(25) NOT NULL, 
+         nameserver VARCHAR(255) NOT NULL, 
+         account VARCHAR(40) DEFAULT NULL
+);
+
+GRANT SELECT ON supermasters TO pdns;
+GRANT ALL ON domains TO pdns;
+GRANT ALL ON domains_id_seq TO pdns;
+GRANT ALL ON records TO pdns;
+GRANT ALL ON records_id_seq TO pdns;
+       </programlisting>
+      </para>
+      <para>
+       This schema contains all elements needed for master, slave and superslave operation. Depending on which features will be used, the 'GRANT' statements
+       can be trimmed to make sure PDNS cannot subvert the contents of your database.
+      </para>
+      <para>
+       Zone2sql with the --gpgsql flag also assumes this layout is in place.
+      </para>
+      </sect2>
+      <sect2><title>Basic functionality</title>
+       <para>
+         4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers.
+       </para>
+       <para>The 4+4 regular queries must return the following 6 fields, in this exact order:
+         <variablelist>
+           <varlistentry>
+             <term>content</term>
+             <listitem>
+               <para>
+                 This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>ttl</term>
+             <listitem>
+               <para>
+                 TTL of this record, in seconds. Must be a real value, no checking is performed.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>prio</term>
+             <listitem>
+               <para>
+                 For MX records, this should be the priority of the mail exchanger specified.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>qtype</term>
+             <listitem>
+               <para>
+                 The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this
+                 field returns an exact answer - PDNS won't recognise 'A      ' as 'A'. This can be achieved by using a VARCHAR instead 
+                 of a CHAR.
+               </para>
+             </listitem>
+             
+           </varlistentry>
+           <varlistentry>
+             <term>domain_id</term>
+             <listitem>
+               <para>
+                 Each domain must have a unique domain_id. No two domains may share a domain_id, all records in a domain should have the same. A number.
+               </para>
+           </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>name</term>
+             <listitem>
+               <para>
+                 Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain!
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+         Please note that the names of the fields are not relevant, but the order is!
+       </para>
+       <para>
+         As said earlier, there are 8 SQL queries for regular lookups. To configure them, set 'gmysql-basic-query' or 'gpgsql-basic-query', depending on your
+         choice of backend. If so called 'MBOXFW' fancy records are not used, four queries remain:
+         <variablelist>
+           <varlistentry>
+             <term>basic-query</term>
+             <listitem>
+               <para>
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'</command>
+                 This is the most used query, needed for doing 1:1 lookups of qtype/name values. First %s is replaced by the ASCII representation
+                 of the qtype of the question, the second by the name.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>id-query</term>
+             <listitem>
+               <para>
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' and domain_id=%d</command>
+                 Used for doing lookups within a domain. First %s is replaced by the qtype, the %d which should appear after the %s by the numeric 
+                 domain_id.
+               </para>
+             </listitem>
+           </varlistentry>
+           
+           <varlistentry>
+             <term>any-query</term>
+             <listitem>
+               <para>
+                 For doing ANY queries. Also used internally.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where name='%s'</command>
+                 The %s is replaced by the qname of the question.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>any-id-query</term>
+             <listitem>
+               <para>
+                 For doing ANY queries within a domain. Also used internally.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where name='%s' and domain_id=%d</command>
+                 The %s is replaced by the name of the domain, the %d by the numerical domain id.
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+       <para>
+         The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally:
+         <variablelist>
+           <varlistentry>
+             <term>list-query</term>
+             <listitem>
+               <para>
+                 To list an entire zone.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where domain_id=%d</command>
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+      </sect2>
+      <sect2><title>Fancy records</title>
+       <para>
+         If PDNS is used with so called 'Fancy Records', the 'MBOXFW' record exists which specifies an email address forwarding instruction, 
+         wildcard queries are sometimes needed. This is not enabled by default.  A wildcard query is 
+         an internal concept - it has no relation to *.domain-type lookups. You can safely leave these queries blank.
+         <variablelist>
+           <varlistentry>
+             <term>wildcard-query</term>
+             <listitem>
+               <para>
+                 Can be left blank. See above for an explanation.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s'</command>
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>wildcard-id-query</term>
+             <listitem>
+               <para>
+                 Can be left blank. See above for an explanation.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s' and domain_id=%d</command>
+                 Used for doing lookups within a domain.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>wildcard-any-query</term>
+             <listitem>
+               <para>
+                 For doing wildcard ANY queries.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where name like '%s'</command>
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>wildcard-any-id-query</term>
+             <listitem>
+               <para>
+                 For doing wildcard ANY queries within a domain.
+                 Default: <command>select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d</command>
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+      </sect2>
+         
+      <sect2><title>Settings and specifying queries</title>
+       <para>
+         The queries above are specified in pdns.conf. For example, the basic-query would appear as:
+         <screen>
+           gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'
+         </screen>
+         
+         Queries can span multiple lines, like this:
+         <screen>
+           gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \
+           where qtype='%s' and name='%s'
+         </screen>
+         Do not wrap statements in quotes as this will not work.
+         Besides the query related settings, the following configuration options are available:
+       </para>
+       <para>
+          <variablelist>
+            <varlistentry>
+              <term>gpgsql-dbname</term>
+              <listitem>
+                <para>
+                  Database name to connect to
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>gpgsql-host</term>
+              <listitem>
+                <para>
+                  Database host to connect to. WARNING: When specified as a hostname a chicken/egg situation might arise where the database
+                 is needed to resolve the IP address of the database. It is best to supply an IP address of the database here.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>gpgsql-password</term>
+              <listitem>
+                <para>
+                  Password to connect with
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>gpgsql-user</term>
+              <listitem>
+                <para>
+                  PgSQL user to connect as
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+       </para>
+      </sect2>
+      <sect2><title>Native operation</title>
+       <para>
+         For native operation, either drop the FOREIGN KEY on the domain_id field, or (recommended), make sure
+         the <command>domains</command> table is filled properly. To add a domain, issue the following:
+         <programlisting>
+           insert into domains (name,type) values ('powerdns.com','NATIVE');
+         </programlisting>
+         The records table can now be filled by with the domain_id set to the id of the domains table row just inserted.
+       </para>
+      </sect2>
+      <sect2><title>Slave operation</title>
+       <para>
+         The PostgreSQL backend is fully slave capable. To become a slave of the 'powerdns.com' domain, execute this:
+         <programlisting>
+           insert into domains (name,master,type) values ('powerdns.com','213.244.168.217','SLAVE');
+         </programlisting>
+         And wait a while for PDNS to pick up the addition - which happens within one minute. There is no need to inform PDNS that a new domain
+         was added.
+         Typical output is:
+         <programlisting>
+           Apr 09 13:34:29 All slave domains are fresh
+           Apr 09 13:35:29 1 slave domain needs checking
+           Apr 09 13:35:29 Domain powerdns.com is stale, master serial 1, our serial 0
+           Apr 09 13:35:30 [gPgSQLBackend] Connected to database
+           Apr 09 13:35:30 AXFR started for 'powerdns.com'
+           Apr 09 13:35:30 AXFR done for 'powerdns.com'
+           Apr 09 13:35:30 [gPgSQLBackend] Closing connection
+         </programlisting>
+       </para>
+       <para>
+         From now on, PDNS is authoritative for the 'powerdns.com' zone and will respond accordingly for queries within that zone. 
+       </para>
+       <para>
+         Periodically, PDNS schedules checks to see if domains are still fresh. The default <command>slave-cycle-interval</command> is 60 seconds, large installations may need to raise this value. Once a domain has been checked, it will not be checked before its SOA refresh timer has expired. Domains whose status is unknown get checked every 60 seconds by default.
+       </para>
+      </sect2>
+      <sect2><title>Superslave operation</title>
+       <para>
+         To configure a supermaster with IP address 10.0.0.11 which lists this installation as 'autoslave.powerdns.com', issue the following:
+         <programlisting>
+           insert into supermasters ('10.0.0.11','autoslave.powerdns.com','internal');
+         </programlisting>
+         From now on, valid notifies from 10.0.0.11 that list a NS record containing 'autoslave.powerdns.com' will lead to the
+         provisioning of a slave domain under the account 'internal'. See <xref linkend="supermaster"> for details.
+       </para>
+      </sect2>
+      <sect2><title>Master operation</title>
+       <para>
+         The PostgreSQL backend is fully master capable with automatic discovery of serial changes. Raising the serial number of a domain
+         suffices to trigger PDNS to send out notifications. To configure a domain for master operation instead of the default native replication,
+         issue:
+         <programlisting>
+           insert into domains (name,type) values ('powerdns.com','MASTER');
+         </programlisting>
+         Make sure that the assigned id in the domains table matches the domain_id field in the records table!
+       </para>
+    </sect1>
+    
+    <sect1 id="oracle"><Title>Generic Oracle backend</title>
+      <para>
+       <table>
+         <title>Oracle backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>No</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       Oracle backend with easily configurable SQL statements, allowing you to graft PDNS on any Oracle database of your choosing.
+      </para>
+      <para>
+       PowerDNS is currently ascertaining if this backend can be distributed in binary form without violating Oracle licensing. In the meantime, 
+       the source code to the Oracle backend is available for runtime linking into dynamic versions of PowerDNS. See 
+       <ulink url="http://downloads.powerdns.com/backends">http://downloads.powerdns.com/backends</ulink> for sources.
+      </para>
+      <para>
+       The following configuration settings are available:
+      </para>
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>oracle-debug-queries</term>
+           <listitem>
+             <para>
+               Output all queries to disk for debugging purposes.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-time-queries</term>
+           <listitem>
+             <para>
+               Output all queries to disk for timing purposes.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-uppercase-database</term>
+           <listitem>
+             <para>
+               Change all domain names to uppercase before querying database.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-database</term>
+           <listitem>
+             <para>
+               Oracle database name to connect to.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-home</term>
+           <listitem>
+             <para>
+               PDNS can set the ORACLE_HOME environment variable from within the executable, allowing execution of
+               the daemon from init.d scripts where ORACLE_HOME may not yet be set.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-sid</term>
+           <listitem>
+             <para>
+               PDNS can set the ORACLE_SID environment variable from within the executable, allowing execution of
+               the daemon from init.d scripts where ORACLE_SID may not yet be set.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-username</term>
+           <listitem>
+             <para>
+               Oracle username to connect as.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-password</term>
+           <listitem>
+             <para>
+               Oracle password to connect with.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      <para>
+       The generic Oracle backend can be configured to use user-specified queries. The following are the default queries
+       and their names:
+      </para>
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>oracle-forward-query</term>
+           <listitem>
+             <para>
+               select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from Records where name = :name and type = :type
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-forward-query-by-zone</term>
+           <listitem>
+             <para>
+               select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name and type = :type and ZoneId = :id
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-forward-any-query</term>
+           <listitem>
+             <para>
+               select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>oracle-list-query</term>
+           <listitem>
+             <para>
+               select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate, 0), name from records where ZoneId = :id
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      <sect2><title>Setting up Oracle for use with PowerDNS</title>
+       <para>
+         To setup a database that corresponds to these default queries, issue the following as Oracle user sys:
+         <screen>
+           create user powerdns identified by YOURPASSWORD;
+           grant connect to powerdns;
+           
+           create tablespace powerdns datafile '/opt/oracle/oradata/oracle/powerdns.dbf'
+             size 256M extent management local autoallocate;
+           
+           alter user powerdns quota unlimited on powerdns; 
+         </screen>
+       </para>
+       <para>
+         As user 'powerdns' continue with:
+         <screen>
+create table Domains (
+ ID             number(11) NOT NULL,
+ NAME           VARCHAR(255) NOT NULL,
+ MASTER                 VARCHAR(20) DEFAULT NULL,
+ LAST_CHECK     INT DEFAULT NULL,
+ TYPE           VARCHAR(6) NOT NULL,
+ NOTIFIED_SERIAL INT DEFAULT NULL,
+ ACCOUNT        VARCHAR(40) DEFAULT NULL,
+ primary key (ID)
+)tablespace POWERDNS;
+
+create index DOMAINS$NAME on Domains (NAME) tablespace POWERDNS;
+create sequence DOMAINS_ID_SEQUENCE;
+
+create table Records
+(
+  ID                number(11) NOT NULL,
+  ZoneID            number(11) default NULL REFERENCES Domains(ID) ON DELETE CASCADE,
+  NAME              varchar2(255) default NULL,
+  TYPE              varchar2(6) default NULL,  
+  CONTENT           varchar2(255) default NULL,
+  TimeToLive        number(11) default NULL,   
+  Priority          number(11) default NULL,
+  CreateDate        number(11) default NULL,
+  ChangeDate        number(11) default NULL,
+  primary key (ID)
+)tablespace POWERDNS;
+
+create index RECORDS$NAME on RECORDS (NAME) tablespace POWERDNS;
+create sequence RECORDS_ID_SEQUENCE;
+         </screen>
+       </para>
+       <para>
+         To insert records, either use <command>zone2sql</command> with the <command>--oracle</command> setting, or execute sql
+         along the lines of:
+         <screen>
+insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherlabs.nl','NATIVE');
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'SOA', 'ahu.casema.net. hostmaster.ds9a.nl. 2000081401 28800 7200 604800 86400', 3600, 0 from Domains where name='netherlabs.nl';
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ahu.casema.net', 3600, 0 from Domains where name='netherlabs.nl';
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ns1.pine.nl', 3600, 0 from Domains where name='netherlabs.nl';
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ns2.pine.nl', 3600, 0 from Domains where name='netherlabs.nl';
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'A', '213.244.168.210', 3600, 0 from Domains where name='netherlabs.nl';
+insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'MX', 'outpost.ds9a.nl', 3600, 10 from Domains where name='netherlabs.nl';
+
+         </screen>
+       </para>
+       <para>
+         For performance reasons it is best to specify <command>--transactions</command> too!
+       </para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="db2"><Title>DB2 backend</title>
+      <para>
+       <table>
+         <title>DB2 backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>No</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       PowerDNS is currently ascertaining if this backend can be distributed in binary form without violating IBM DB2 licensing. If you have a DB2 license, 
+       please contact pdns@powerdns.com so we can ship you a copy of this driver.
+      </para>
+      <para>
+       The DB2 backend executes the following queries:
+       <variablelist>
+         <varlistentry>
+           <term>Forward Query</term>
+           <listitem>
+             <para>
+               select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ? and type = ?
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Forward By Zone Query</term>
+           <listitem>
+             <para>
+               select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ? and Type = ? and ZoneId = ?
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>Forward Any Query</term>
+           <listitem>
+             <para>
+               select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ?
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>List Query</term>
+           <listitem>
+             <para>
+               select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where ZoneId = ?
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      <para>
+       Configuration settings:
+       <variablelist>
+         <varlistentry>
+           <term>db2-server</term>
+           <listitem>
+             <para>
+               Server name to connect to. Defaults to 'powerdns'. Make sure that your nameserver is not needed to resolve an IP address needed to connect as
+               this might lead to a chicken/egg situation. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>db2-user</term>
+           <listitem>
+             <para>
+               Username to connect as. Defaults to 'powerdns'.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>db2-password</term>
+           <listitem>
+             <para>
+               Password to connect with. Defaults to 'powerdns'.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+    </sect1>
+    
+    <sect1 id="bindbackend"><Title>Bind zone file backend</title>
+      <para>
+       <table>
+         <title>Bind zone file backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>No</entry></row>
+             <row><entry>Slave</entry><entry>Experimental</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>No</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       The BindBackend started life as a demonstration of the versatility of PDNS but quickly gained in importance when there appeared to be demand
+       for a Bind 'workalike'.
+      </para>
+      <para>
+       The BindBackend parses a Bind-style named.conf and extracts information about zones from it. It makes no attempt to honour other configuration flags,
+       which you should configure (when available) using the PDNS native configuration.
+      </para>
+      <para>
+       <variablelist>
+         <varlistentry>
+           <term>--help=bind</term>
+           <listitem>
+             <para>
+                Outputs all known parameters related to the bindbackend
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bind-example-zones</term>
+           <listitem>
+             <para>
+               Loads the 'example.com' zone which can be queried to determine if PowerDNS is functioning without configuring 
+               database backends.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bind-config=</term>
+           <listitem>
+             <para>
+               Location of the Bind configuration file to parse.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bind-check-interval=</term>
+           <listitem>
+             <para>
+               How often to check for zone changes. See 'Operation' section.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bind-enable-huffman</term>
+           <listitem>
+             <para>
+               Enable Huffman compression on zone data. Currently saves around 20% of memory actually used, but slows down operation
+               somewhat.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      <sect2>
+       <title>Operation</title>
+       <para>
+         On launch, the BindBackend first parses the named.conf to determine which zones need to be loaded. These will then be parsed
+         and made available for serving, as they are parsed. So a named.conf with 100.000 zones may take 20 seconds to load, but after 10 seconds, 
+         50.000 zones will already be available. While a domain is being loaded, it is not yet available, to prevent incomplete answers.
+       </para>
+       <para>
+         Reloading is currently done only when a request for a zone comes in, and then only after <command>bind-check-interval</command> seconds have passed
+         after the last check. If a change occurred, access to the zone is disabled, the file is reloaded, access is restored, and the question is answered.
+         For regular zones, reloading is fast enough to answer the question which lead to the reload within the DNS timeout.
+       </para>
+        <para>
+          If <command>bind-check-interval</command> is specified as zero, no checks will be performed.
+        </para>
+      <sect2><title>Performance</title>
+       <para>
+         The BindBackend does not benefit from the packet cache as it is fast enough on its own. Furthermore, on most systems, there will
+         be no benefit in using multiple CPUs for the packetcache, so a noticeable speedup can be attained by specifying 
+         <command>distributor-threads=1</command> in <filename>pdns.conf</filename>.
+       </para>
+      </sect2>
+      <sect2><title>Master/slave configuration</title>
+       <para>
+         Currently disabled in prereleases. But see <xref linkend="slave">.
+       </para>
+      </sect2>
+    </sect1>
+
+  <sect1 id="odbc">
+    <Title>ODBC backend</Title>
+      <para>
+       <table>
+         <title>ODBC backend capabilities</title>
+         <tgroup cols=2>
+           <tbody>
+             <row><entry>Native</entry><entry>Yes</entry></row>
+             <row><entry>Master</entry><entry>Yes (experimental)</entry></row>
+             <row><entry>Slave</entry><entry>Yes (experimental)</entry></row>
+             <row><entry>Superslave</entry><entry>No</entry></row>
+             <row><entry>Autoserial</entry><entry>Yes</entry></row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+    <para>
+      The ODBC backend can retrieve zone information from any source that has a ODBC driver available.
+      <note><para>This backend is only available on PowerDNS for Windows.</para></note>
+    </para>
+
+    <para>
+       The ODBC backend needs data in a fixed schema which is the same as the data needed by the MySQL backend. The create statement
+       will resemble this:
+        <screen>
+          CREATE TABLE records (
+         id int(11) NOT NULL auto_increment,
+         domain_id int(11) default NULL,
+         name varchar(255) default NULL,
+         type varchar(6) default NULL,
+         content varchar(255) default NULL,
+         ttl int(11) default NULL,
+         prio int(11) default NULL,
+         change_date int(11) default NULL,
+         PRIMARY KEY (id),
+         KEY name_index(name),
+         KEY nametype_index(name,type),
+         KEY domainid_index(domain_id)
+         );
+        </screen>
+    </para>
+
+    <para>
+      To use the ODBC backend an ODBC source has to be created, to do this see the section Installing PowerDNS on Microsoft Windows, <xref linkend="windows">.
+    </para>
+
+    <para>
+       The following configuration settings are available:
+
+      <variablelist>
+         <varlistentry>
+         <term>odbc-datasource</term>
+         <listitem>
+             <para>
+          Specifies the name of the data source to use. 
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+         <term>odbc-user</term>
+         <listitem>
+             <para>
+          Specifies the username that has to be used to log into the datasource.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+         <term>odbc-pass</term>
+         <listitem>
+             <para>
+          Specifies the user's password.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+         <term>odbc-table</term>
+         <listitem>
+             <para>
+          Specifies the name of the table containing the zone information.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+      <para>
+       The ODBC backend has been tested with Microsoft Access, MySQL (via MyODBC) and Microsoft SQLServer. As the SQL statements used are very basic,
+       it is expected to work with many ODBC drivers.
+      </para>
+  </sect1>
+
+</appendix>
+<appendix id="pdns-internals"><title>PDNS internals</title>
+    <para>
+      PDNS is normally launched by the init.d script but is actually a binary called <filename>pdns_server</filename>. This 
+      file is started by the <command>start</command> and <command>monitor</command> commands to the init.d script. Other commands
+      are implemented using the controlsocket.
+    </para>
+    <sect1 id="controlsocket"><title>Controlsocket</title>
+      <para>
+        The controlsocket is the means to contact a running PDNS daemon, or as we now know, a running <filename>pdns_server</filename>.
+        Over this sockets, instructions can be sent using the <filename>pdns_control</filename> program. Like the <filename>pdns_server</filename>,
+        this program is normally accessed via the init.d script.
+      </para>
+      <sect2 id="pdnscontrol"><title>pdns_control</title>
+
+       <para>
+         To communicate with PDNS over the controlsocket, the <command>pdns_control</command> command is used. The init.d script also calls 
+         pdns_control. The syntax is simple: <command>pdns_control command arguments</command>. Currently this is most useful for telling backends
+         to rediscover domains or to force the transmission of notifications. See <xref linkend="master">.
+       </para>
+       <para>
+         Besides the commands implemented by the init.d script, for which see <xref linkend="pdns-on-unix">, the following pdns_control commands
+         are available:
+         <variablelist>
+           <varlistentry>
+             <term>ccounts</term>
+             <listitem>
+               <para>
+                 Returns counts on the contents of the cache.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>version</term>
+             <listitem>
+               <para>
+                 returns the version of a running pdns daemon.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>purge</term>
+             <listitem>
+               <para>
+                 Purges the entire Packet Cache - see <xref linkend="performance">.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>purge <userinput>record</userinput></term>
+             <listitem>
+               <para>
+                 Purges all entries for this exact record name - see <xref linkend="performance">.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>purge <userinput>record</userinput>$</term>
+             <listitem>
+               <para>
+                 Purges all entries ending on this name, effectively purging an entire domain - see <xref linkend="performance">.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>set <userinput>variable value</userinput></term>
+             <listitem>
+               <para>
+                 Set a configuration parameter. Currently only the 'query-logging' parameter can be set. 
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="guardian"><title>Guardian</title>
+      <para>
+        When launched by the init.d script, <filename>pdns_server</filename> wraps itself inside a 'guardian'. This guardian monitors the
+        performance of the inner <filename>pdns_server</filename> instance which shows up in the process list of your OS as 
+        <filename>pdns_server-instance</filename>. 
+
+        It is also this guardian that <filename>pdns_control</filename> talks to. A <command>STOP</command> is interpreted by the guardian, 
+        which causes the guardian to sever the connection to the inner process and terminate it, after which it terminates itself.
+
+        The init.d script <command>DUMP</command> and <command>SHOW</command> commands need to access the inner process, because
+        the guardian itself does not run a nameserver. For this purpose, the guardian passes controlsocket requests to the control console of the
+        inner process. This is the same console as seen with init.d <command>MONITOR</command>.
+      </para></sect1>
+    <sect1 id="modules"><title>Modules &amp; Backends</title>
+      <para>
+       PDNS has the concept of backends and modules. Non-static PDNS distributions have the ability to load new modules at runtime, while the
+       static versions come with a number of modules built in, but cannot load more. 
+      </para>
+      <para>
+       Related parameters are:
+       <variablelist>
+         <varlistentry>
+           <term>--help</term>
+           <listitem>
+             <para>
+                Outputs all known parameters, including those of launched backends, see below.
+             </para>
+           </listitem>
+         </varlistentry>
+          <varlistentry>
+            <term>--launch=backend,backend1,backend1:name</term>
+            <listitem>
+              <para>
+                Launches backends. In its most simple form, supply all backends that need to be launched. If you find
+                that you need to launch single backends multiple times, you can specify a name for later instantiations.
+                In this case, there are 2 instances of backend1, and the second one is called 'name'.
+
+                This means that <command>--backend1-setting</command> is available to configure the first or main instance, and
+                <command>--backend1-name-setting</command> for the second one.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>--load-modules=/directory/libyourbackend.so</term>
+            <listitem>
+              <para>
+                If backends are available in nonstandard directories, specify their location here. Multiple files
+                can be loaded if separated by commas. Only available in non-static PDNS distributions.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>--list-modules</term>
+            <listitem>
+              <para>
+                Will list all available modules, both compiled in and in dynamically loadable modules.
+              </para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+       To run on the commandline, use the <command>pdns_server</command> binary. For example, to see options for the gpgsql backend, 
+       use the following:
+       <screen>
+         $ /usr/sbin/pdns_server --launch=gpgsql --help=gpgsql
+       </screen>
+      </para>
+    </sect1>
+    <sect1 id="dns-to-query"><title>How PDNS translates DNS queries into backend queries</title>
+      <para>
+       A DNS query is not a straightforward lookup. Many DNS queries need to check the backend for additional data, for example to
+       determine of an unfound record should lead to an NXDOMAIN ('we know about this domain, but that record does not exist') or an 
+       unauthoritative response.
+      </para>
+      <para>
+       Simplified, without CNAME processing and wildcards, the algorithm is like this:
+      </para>
+      <para>
+       When a query for a <command>qname</command>/<command>qtype</command> tuple comes in, it is requested directly from the backend. 
+       If present, PDNS adds the contents of the reply to the list of records to return. A question tuple may generate multiple answer 
+       records.
+      </para>
+      <para>
+       Each of these records is now investigated to see if it needs 'additional processing'. This holds for example for MX records which may
+       point to hosts for which the PDNS backends also contain data. This involves further lookups for A or AAAA records.
+      </para>
+      <para>
+       After all additional processing has been performed, PDNS sieves out all double records which may well have appeared. The resulting set of 
+       records is added to the answer packet, and sent out.
+      </para>
+      <para>
+       A zone transfer works by looking up the <command>domain_id</command> of the SOA record of the name and then listing all records of that 
+       <command>domain_id</command>. This is why all records in a domain need to have the same domain_id.
+      </para>
+      <para>
+       When a query comes in for an unknown domain, PDNS starts looking for SOA records of all subdomains of the qname, so 
+       no.such.powerdns.com turns into a SOA query for no.such.powerdns.com, such.powerdns.com, powerdns.com, com, ''. When a SOA is found,
+       that zone is consulted for relevant NS instructions which lead to a referral. If nothing is found within the zone, an authoritative 
+       NXDOMAIN is sent out.
+      </para>
+      <para>
+       If no SOA was found, an unauthoritative no-error is returned.
+      </para>
+      <para>
+       In reality, each query for a question tuple first involves checking for a CNAME, unless that resolution has been disabled with the
+       <command>skip-cname</command> option.
+      </para>
+      <para>
+       PDNS breaks strict RFC compatability by not always checking for the presence of a SOA record first. This is unlikely to lead to 
+       problems though.
+      </para>
+  </appendix>
+  <appendix id="backend-writers-guide"><title>Backend writers' guide</title>
+    <para>
+      PDNS backends are implemented via a simple yet powerful C++ interface. If your needs are not met by the PipeBackend, you 
+      may want to write your own. Doing so requires a copy of the PowerDNS Open Source Backend Development kit which can be found on <ulink 
+       url="http://downloads.powerdns.com/releases/dev">http://downloads.powerdns.com/releases/dev</ulink>.
+    </para>
+    <para>
+      A backend contains zero DNS logic. It need not look for CNAMES, it need not return NS records unless explicitly asked for, etcetera.
+      All DNS logic is contained within PDNS itself - backends should simply return records matching the description asked for. 
+    </para>
+    <para> 
+      <warning><para>
+      However, please note that your backend can get queries in aNy CAsE! If your database is case sensitive, like most are (with the notable
+      exception of MySQL), you must make sure that you do find answers which differ only in case.
+       </para></warning>
+    </para>
+    <sect1 id="simple-backends"><title>Simple read-only native backends</title>
+      <para>
+       Implementing a backend consists of inheriting from the DNSBackend class. For read-only backends, which do not support slave operation,
+       only the following methods are relevant:
+       
+       <programlisting>
+       class DNSBackend
+       {
+       public:
+
+       virtual bool lookup(const QType &amp;qtype, const string &amp;qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0; 
+       virtual bool list(int domain_id)=0; 
+       virtual bool get(DNSResourceRecord &amp;r)=0;
+       virtual bool getSOA(const string &amp;name, SOAData &amp;soadata);
+       };
+       </programlisting>
+      
+       Note that the first three methods must be implemented. <function>getSOA()</function> has a useful default implementation.
+      </para>
+      <para>
+       The semantics are simple. Each instance of your class only handles one (1) query at a time. There is no need for locking as PDNS guarantees
+       that your backend will never be called reentrantly. 
+      </para>
+      <para>
+       Some examples, a more formal specification is down below. A normal lookup starts like this:
+       
+       <programlisting>
+        YourBackend yb;
+       yb.lookup(QType::CNAME,"www.powerdns.com");
+       </programlisting>
+      
+       Your class should now do everything to start this query. Perform as much preparation as possible - handling errors at this stage is better for PDNS 
+       than doing so later on. A real error should be reported by throwing an exception. 
+      </para>
+      <para>
+       PDNS will then call the <function>get()</function> method to get <command>DNSResourceRecord</command>s back. The following code illustrates
+       a typical query:
+       
+      <programlisting>
+       yb.lookup(QType::CNAME,"www.powerdns.com");
+
+       DNSResourceRecord rr;
+       while(yb.get(rr))
+         cout&lt;&lt;"Found cname pointing to '"+rr.content+"'"&lt;&lt;endl;
+       }
+       </programlisting>
+      </para>
+      <para>
+       Each zone starts with a Start of Authority (SOA) record. This record is special so many backends will choose to implement it
+       specially. The default <function>getSOA()</function> method performs a regular lookup on your backend to figure out the SOA, 
+       so if you have no special treatment for SOA records, where is no need to implement your own <function>getSOA()</function>.
+      </para>
+      <para>
+       Besides direct queries, PDNS also needs to be able to list a zone, to do zone transfers for example. Each zone has an id which should be
+       unique within the backend. To list all records belonging to a zone id, the <function>list()</function> method is used. Conveniently,
+       the domain_id is also available in the <command>SOAData</command> structure.
+      </para>
+      <para>
+       The following lists the contents of a zone called "powerdns.com".
+      
+       <programlisting>
+       SOAData sd;
+       if(!yb.getSOA("powerdns.com",sd))  // are we authoritative over powerdns.com?
+         return RCode::NotAuth;           // no
+
+       yb.list(sd.domain_id); 
+       while(yb.get(rr))
+         cout&lt;&lt;rr.qname&lt;&lt;"\t IN "&lt;&lt;rr.qtype.getName()&lt;&lt;"\t"&lt;&lt;rr.content&lt;&lt;endl;
+       </programlisting>
+      </para>
+      <para>
+       Please note that when so called 'fancy records' (see <xref linkend="fancy-records">) are enabled, a backend can receive
+       wildcard lookups. These have a % as the first character of the qdomain in lookup. 
+      </para>
+      <sect2><title>A sample minimal backend</title>
+       <para>
+         This backend only knows about the host "random.powerdns.com", and furthermore, only about its A record:
+         
+         <programlisting>
+/* FIRST PART */
+class RandomBackend : public DNSBackend
+{
+public:
+  bool list(int id) {
+    return false; // we don't support AXFR
+  }
+    
+  void lookup(const QType &amp;type, const string &amp;qdomain, DNSPacket *p, int zoneId)
+  {
+    if(type.getCode()!=QType::A || qdomain!="random.powerdns.com")  // we only know about random.powerdns.com A
+      d_answer="";                                                  // no answer
+    else {
+      ostringstream os;
+      os&lt;&lt;random()%256&lt;&lt;"."&lt;&lt;random()%256&lt;&lt;"."&lt;&lt;random()%256&lt;&lt;"."&lt;&lt;random()%256;
+      d_answer=os.str();                                           // our random ip address
+    }
+  }
+
+  bool get(DNSResourceRecord &amp;rr)
+  {
+    if(!d_answer.empty()) {
+      rr.qname="random.powerdns.com";                               // fill in details
+      rr.qtype=QType::A;                                            // A record
+      rr.ttl=86400;                                                 // 1 day
+      rr.content=d_answer;
+
+      d_answer="";                                                  // this was the last answer
+      
+      return true;
+    }
+    return false;                                                   // no more data
+  }
+  
+private:
+  string d_answer;
+};
+
+/* SECOND PART */
+
+class RandomFactory : public BackendFactory
+{
+public:
+  RandomFactory() : BackendFactory("random") {}
+
+  DNSBackend *make(const string &amp;suffix)
+  {
+    return new RandomBackend();
+  }
+};
+
+/* THIRD PART */
+
+class RandomLoader
+{
+public:
+  Loader()
+  {
+    BackendMakers().report(new RandomFactory);
+    
+    L&lt;&lt;Logger::Info&lt;&lt;" [RandomBackend] This is the randombackend ("__DATE__", "__TIME__") reporting"&lt;&lt;endl;
+  }  
+};
+
+static RandomLoader randomloader;
+       </programlisting>         
+        This simple backend can be used as an 'overlay'. In other words, it only knows about a single record, another loaded backend would have
+        to know about the SOA and NS records and such. But nothing prevents us from loading it without another backend.
+      </para>
+      <para>
+        The first part of the code contains the actual logic and should be pretty straightforward. The second part is a boilerplate
+        'factory' class which PDNS calls to create randombackend instances. Note that a 'suffix' parameter is passed. Real life backends
+        also declare parameters for the configuration file; these get the 'suffix' appended to them. Note that the "random" in the 
+        constructor denotes the name by which the backend will be known.
+      </para>
+      <para>
+        The third part registers the RandomFactory with PDNS. This is a simple C++ trick which makes sure that this function
+        is called on execution of the binary or when loading the dynamic module.
+      </para>
+       <para>
+         Please note that a RandomBackend is actually in most PDNS releases. By default it lives on random.example.com, but you can change
+         that by setting <command>random-hostname</command>.
+       </para>
+       <para>
+         NOTE: this simple backend neglects to handle case properly! For a more complete example, see the full pdns-dev distribution as found on
+         <ulink url="http://www.powerdns.com/pdns">the website</ulink>.
+       </para>
+    </sect2>
+    <sect2><title>Interface definition</title>
+      <para>
+       Classes:
+       <table>
+         <title>DNSResourceRecord class</title>
+         <tgroup cols=2>
+           <tbody>
+             <row>
+               <entry>QType qtype</entry><entry>QType of this record</entry>
+             </row>
+             <row>
+               <entry>string qname</entry><entry>name of this record</entry>
+             </row>
+             <row>
+               <entry>string content</entry><entry>ASCII representation of right hand side</entry>
+             </row>
+             <row>
+               <entry>u_int16_t priority</entry><entry>priority of an MX record.</entry>
+             </row>
+             <row>
+               <entry>u_int32_t ttl</entry><entry>Time To Live of this record</entry>
+             </row>
+             <row>
+               <entry>int domain_id</entry><entry>ID of the domain this record belongs to</entry>
+             </row>
+             <row>
+               <entry>time_t last_modified</entry><entry>If unzero, last time_t this record was changed</entry>
+             </row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       <table>
+         <title>SOAData struct</title>
+         <tgroup cols=2>
+           <tbody>
+             <row>
+               <entry>string nameserver</entry><entry>Name of the master nameserver of this zone</entry>
+             </row>
+             <row>
+               <entry>string hostmaster</entry><entry>Hostmaster of this domain. May contain an @</entry>
+             </row>
+             <row>
+               <entry>u_int32_t serial</entry><entry>Serial number of this zone</entry>
+             </row>
+             <row>
+               <entry>u_int32_t refresh</entry><entry>How often this zone should be refreshed</entry>
+             </row>
+             <row>
+               <entry>u_int32_t retry</entry><entry>How often a failed zone pull should be retried.</entry>
+             </row>
+             <row>
+               <entry>u_int32_t expire</entry><entry>If zone pulls failed for this long, retire records</entry>
+             </row>
+             <row>
+               <entry>u_int32_t default_ttl</entry><entry>Difficult</entry>
+             </row>
+             <row>
+               <entry>int domain_id</entry><entry>The ID of the domain within this backend. Must be filled!</entry>
+             </row>
+             <row>
+               <entry>DNSBackend *db</entry><entry>Pointer to the backend that feels authoritative for a domain and can act as a slave</entry>
+             </row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       Methods:
+       <variablelist>
+         <varlistentry>
+           <term>void lookup(const QType &amp;qtype, const string &amp;qdomain, DNSPacket *pkt=0, int zoneId=-1)</term>
+           <listitem>
+             <para>
+               This function is used to initiate a straight lookup for a record of name 'qdomain' and type 'qtype'.
+               A QType can be converted into an integer by invoking its <function>getCode()</function> method and into
+               a string with the <function>getCode()</function>.
+             </para>
+             <para>
+                 The original question may or may not be passed in the pointer p. If it is, you can retrieve (from 1.99.11 onwards) 
+                 information about who asked the question with the <function>getRemote(DNSPacket *)</function> method. Alternatively, 
+                 <function>bool getRemote(struct sockaddr *sa, socklen_t *len)</function> is available.
+               </para>
+               <para>
+                 Note that <command>qdomain</command> can be of any case and that your backend should make sure it is in effect case 
+                 insensitive. Furthermore, the case of the original question should be retained in answers returned by <function>get()</function>!
+               </para>
+             <para>
+               Finally, the domain_id might also be passed indicating that only answers from the indicated zone need apply. This
+               can both be used as a restriction or as a possible speedup, hinting your backend where the answer might be found.
+             </para>
+             <para>
+               If initiated succesfully, as indicated by returning <command>true</command>, answers should be made available over the
+               <function>get()</function> method.
+               </para>
+               <para>
+                 Should throw an AhuException if an error occured accessing the database. Returning otherwise indicates that the query 
+                 was started succesfully. If it is known that no data is available, no exception should be thrown! An exception indicates
+                 that the backend considers itself broken - not that no answers are available for a question.
+               </para>
+               <para>
+                 It is legal to return here, and have the first call to <function>get()</function> return false. This is interpreted as 'no data'
+               </para>
+             </listitem>
+           </varlistentry>
+         
+         <varlistentry>
+           <term>bool list(int domain_id)
+           <listitem>
+             <para>
+               Initiates a list of the indicated domain. Records should then be made available via the <function>get()</function> method. 
+               Need not include the SOA record. If it is, PDNS will not get confused.
+             </para>
+             <para>
+               Should return false if the backend does not consider itself authoritative for this zone.
+               Should throw an AhuException if an error occured accessing the database. Returning true indicates that data is or should be available.
+             </para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term>bool get(DNSResourceRecord &amp;rr)</term>
+           <listitem>
+             <para>
+               Request a DNSResourceRecord from a query started by <function>get()</function> of <function>list()</function>. If this functions returns 
+               <command>true</command>, <command>rr</command> has been filled with data. When it returns false, no more data is available, 
+               and <command>rr</command> does not contain new data. A backend should make sure that it either fills out all fields of the 
+               DNSResourceRecord or resets them to their default values.
+             </para>
+               <para>
+                 The qname field of the DNSResourceRecord should be filled out with the exact <function>qdomain</function> passed to lookup, preserving
+                 its case. So if a query for 'CaSe.yourdomain.com' comes in and your database contains dat afor 'case.yourdomain.com', the qname field of rr
+                 should contin 'CaSe.yourdomain.com'!
+               </para>
+             <para>
+               Should throw an AhuException in case a database error occurred.
+             </para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term>bool getSOA(const string &amp;name, SOAData &amp;soadata)</term>
+           <listitem>
+             <para>
+               If the backend considers itself authoritative over domain <function>name</function>, this method should fill out
+               the passed <command>SOAData</command> structure and return a positive number. If the backend is functioning correctly, but
+               does not consider itself authoritative, it should return 0. In case of errors, an AhuException should be thrown.
+             </para>
+           </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+      </sect2>
+    </sect1>
+    <sect1 id="backend-error-reporting"><title>Reporting errors</title>
+       <para>
+         To report errors, the Logger class is available which works mostly like an iostream. Example usage is as shown above in the RandomBackend.
+         Note that it is very important that each line is ended with <command>endl</command> as your message won't be visible otherwise.
+       </para>
+       <para>
+         To indicate the importance of an error, the standard syslog errorlevels are available. They can be set by outputting 
+         <function>Logger::Critical</function>,
+         <function>Logger::Error</function>,
+         <function>Logger::Warning</function>,
+         <function>Logger::Notice</function>,
+         <function>Logger::Info</function> or
+         <function>Logger::Debug</function> to <function>L</function>, in descending order of graveness.
+       </para>
+      </sect1>
+      <sect1 id="backend-configuration-details"><title>Declaring and reading configuration details</title>
+       <para>
+         It is highly likely that a backend needs configuration details. On launch, these parameters need to be declared with PDNS so it knows it
+         should accept them in the configuration file and on the commandline. Furthermore, they will be listed in the output of 
+         <command>--help</command>.
+       </para>
+       <para>
+         Declaring arguments is done by implementing the member function <function>declareArguments()</function> in the factory class of your
+         backend. PDNS will call this method after launching the backend.
+       </para>
+       <para>
+         In the <function>declareArguments()</function> method, the function <function>declare()</function> is available. The exact definitions:
+         <variablelist>
+           <varlistentry>
+             <term>void declareArguments(const string &amp;suffix="")</term>
+             <listitem>
+               <para>
+                 This method is called to allow a backend to register configurable parameters. The suffix is the sub-name of this module. There is
+                 no need to touch this suffix, just pass it on to the declare method.
+               </para>
+             </listitem>
+           </varlistentry>
+           
+           <varlistentry>
+             <term>void declare(const string &amp;suffix, const string &amp;param, const string &amp;explanation, const string &amp;value)</term>
+             <listitem>
+               <para>The suffix is passed to your method, and can be passed on to declare. <command>param</command> is the name of your parameter.
+                 <command>explanation</command> is what will appear in the output of --help. Furthermore, a default value can be supplied in the 
+                 <command>value</command> parameter.
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+       <para>
+         A sample implementation:
+         <programlisting>
+           void declareArguments(const string &amp;suffix)
+           {
+             declare(suffix,"dbname","Pdns backend database name to connect to","powerdns");
+             declare(suffix,"user","Pdns backend user to connect as","powerdns");
+             declare(suffix,"host","Pdns backend host to connect to","");
+             declare(suffix,"password","Pdns backend password to connect with","");
+           }
+         </programlisting>
+       </para>
+       <para>
+         After the arguments have been declared, they can be accessed from your backend using the <function>mustDo()</function>,
+         <function>getArg()</function> and <function>getArgAsNum()</function> methods. The are defined as follows in the DNSBackend class:
+       </para>
+       <para>
+         <variablelist>
+           <varlistentry>
+             <term>void setArgPrefix(const string &amp;prefix)</term>
+             <listitem>
+               <para>
+                 Must be called before any of the other accessing functions are used. Typical usage is '<function>setArgPrefix("mybackend"+suffix)</function>'
+                 in the constructor of a backend.
+               </para>
+             </listitem>
+           </varlistentry>
+
+           <varlistentry>
+             <term>bool mustDo(const string &amp;key)</term>
+             <listitem>
+               <para>
+                 Returns true if the variable <function>key</function> is set to anything but 'no'.
+               </para>
+             </listitem>
+           </varlistentry>
+
+           <varlistentry>
+             <term>const string&amp; getArg(const string &amp;key)</term>
+             <listitem>
+               <para>
+                 Returns the exact value of a parameter.
+               </para>
+             </listitem>
+           </varlistentry>
+
+           <varlistentry>
+             <term>int getArgAsNum(const string &amp;key)</term>
+             <listitem>
+               <para>
+                 Returns the numerical value of a parameter. Uses <function>atoi()</function> internally
+               </para>
+             </listitem>
+           </varlistentry>
+         </variablelist>
+       </para>
+       <para>
+         Sample usage from the BindBackend, using the <command>bind-example-zones</command> and <command>bind-config</command>
+         parameters.
+         <programlisting>
+  if(mustDo("example-zones")) {
+    insert(0,"www.example.com","A","1.2.3.4");
+    /* ... */
+  }
+  
+
+  if(!getArg("config").empty()) {
+    BindParser BP;
+    
+    BP.parse(getArg("config"));
+  }
+
+         </programlisting>
+       </para>
+      </sect1>
+
+    <sect1 id="rw-backends"><title>Read/write slave-capable backends</title>
+      <para>
+       The backends above are 'natively capable' in that they contain all data relevant for a domain and do not pull in data from other nameservers.
+       To enable storage of information, a backend must be able to do more.
+      </para>
+      <para>
+       Before diving into the details of the implementation some theory is in order. Slave domains are pulled from the master. PDNS needs to 
+       know for which domains it is to be a slave, and for each slave domain, what the IP address of the master is.
+      </para>
+      <para>
+       A slave zone is pulled from a master, after which it is 'fresh', but this is only temporary. In the SOA record of a zone there is a field
+       which specifies the 'refresh' interval. After that interval has elapsed, the slave nameserver needs to check at the master ff the serial
+       number there is higher than what is stored in the backend locally.
+      </para>
+      <para>
+       If this is the case, PDNS dubs the domain 'stale', and schedules a transfer of data from the remote. This transfer remains scheduled
+       until the serial numbers remote and locally are identical again.
+      </para>
+      <para>
+       This theory is implemented by the <function>getUnfreshSlaveInfos</function> method, which is called on all backends periodically. 
+       This method fills a vector of <command>SlaveDomain</command>s with domains that are unfresh and possibly stale. 
+      </para>
+      <para>
+       PDNS then retrieves the SOA of those domains remotely and locally and creates a list of stale domains. For each of these domains, PDNS
+       starts a zonetransfer to resynchronise. Because zone transfers can fail, it is important that the interface to the backend allows
+       for transaction semantics because a zone might otherwise be left in a halfway updated situation.
+      </para>
+      <para>
+       The following excerpt from the DNSBackend shows the relevant functions:
+      </para>
+      <para>
+       <programlisting>
+         class DNSBackend {
+         public:
+           /* ... */
+           virtual bool getDomainInfo(const string &amp;domain, DomainInfo &amp;di);
+          virtual bool isMaster(const string &amp;name, const string &amp;ip);
+          virtual bool startTransaction(const string &amp;qname, int id);
+          virtual bool commitTransaction();
+          virtual bool abortTransaction();
+          virtual bool feedRecord(const DNSResourceRecord &amp;rr);
+          virtual void getUnfreshSlaveInfos(vector&lt;DomainInfo&gt;* domains);
+          virtual void setFresh(int id);
+           /* ... */
+        }
+       </programlisting>
+      </para>
+      <para>
+        The mentioned DomainInfo struct looks like this:
+       <table>
+         <title>DomainInfo struct</title>
+         <tgroup cols=2>
+           <tbody>
+             <row>
+               <entry>int id</entry><entry>ID of this zone within this backend</entry>
+             </row>
+             <row>
+               <entry>string master</entry><entry>IP address of the master of this domain, if any</entry>
+             </row>
+             <row>
+               <entry>u_int32_t serial</entry><entry>Serial number of this zone</entry>
+             </row>
+             <row>
+               <entry>u_int32_t notified_serial</entry><entry>Last serial number of this zone that slaves have seen</entry>
+             </row>
+             <row>
+               <entry>time_t last_check</entry><entry>Last time this zone was checked over at the master for changes</entry>
+             </row>
+             <row>
+               <entry>enum {Master,Slave,Native} kind</entry><entry>Type of zone</entry>
+             </row>
+             <row>
+               <entry>DNSBackend *backend</entry><entry>Pointer to the backend that feels authoritative for a domain and can act as a slave</entry>
+             </row>
+           </tbody>
+         </tgroup>
+       </table>
+      </para>
+      <para>
+       These functions all have a default implementation that returns false - which explains that these methods can be omitted in simple backends. 
+       Furthermore, unlike with simple backends, a slave capable backend must make sure that the 'DNSBackend *db' field of the SOAData record is filled 
+       out correctly - it is used to determine which backend will house this zone. 
+       <variablelist>
+         <varlistentry>
+           <term>bool isMaster(const string &amp;name, const string &amp;ip);</term>
+           <listitem>
+             <para>
+               If a backend considers itself a slave for the domain <command>name</command> and if the IP address in <command>ip</command>
+               is indeed a master, it should return true. False otherwise. This is a first line of checks to guard against reloading a domain
+               unnecessarily.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>void getUnfreshSlaveInfos(vector&lt;DomainInfo&gt;* domains)</term>
+           <listitem>
+             <para>
+               When called, the backend should examine its list of slave domains and add any unfresh ones to the domains vector.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bool getDomainInfo(const string &amp;name, DomainInfo &amp; di)</term>
+           <listitem>
+             <para>
+                This is like getUnfreshSlaveInfos, but for a specific domain. If the backend considers itself authoritative for the named
+                zone, <function>di</function> should be filled out, and 'true' be returned. Otherwise return false.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bool startTransaction(const string &amp;qname, int id)</term>
+           <listitem>
+             <para>
+               When called, the backend should start a transaction that can be committed or rolled back atomically later on. 
+               In SQL terms, this function should <command>BEGIN</command> a transaction and <command>DELETE</command> all
+               records.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bool feedRecord(const DNSResourceRecord &amp;rr)</term>
+           <listitem>
+             <para>
+               Insert this record.
+             </para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term>bool commitTransaction();</term>
+           <listitem>
+             <para>
+               Make the changes effective. In SQL terms, execute <command>COMMIT</command>.
+             </para>
+           </listitem>
+         </varlistentry>
+             
+         <varlistentry>
+           <term>bool abortTransaction();</term>
+           <listitem>
+             <para>
+               Abort changes. In SQL terms, execute <command>ABORT</command>.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bool setFresh()</term>
+           <listitem>
+             <para>
+               Indicate that a domain has either been updated or refreshed without the need for a retransfer. This causes
+               the domain to vanish from the vector modified by <function>getUnfreshSlaveInfos()</function>.
+             </para>
+           </listitem>
+         </varlistentry>
+
+       </variablelist>
+      </para>
+      <para>
+       PDNS will always call <function>startTransaction()</function> before making calls to <function>feedRecord()</function>.
+       Although it is likely that <function>abortTransaction()</function> will be called in case of problems, backends should also
+       be prepared to abort from their destructor.
+      </para>
+      <para>
+       The actual code in PDNS is currently (1.99.9):
+       <programlisting>
+    Resolver resolver;
+    resolver.axfr(remote,domain.c_str());
+
+    db->startTransaction(domain, domain_id);
+    
+    L&lt;&lt;Logger::Error&lt;&lt;"AXFR started for '"&lt;&lt;domain&lt;&lt;"'"&lt;&lt;endl;
+    Resolver::res_t recs;
+    
+    while(resolver.axfrChunk(recs)) {
+      for(Resolver::res_t::const_iterator i=recs.begin();i!=recs.end();++i) {
+       db->feedRecord(*i);
+      }
+    }
+    db->commitTransaction();
+    db->setFresh(domain_id);
+    L&lt;&lt;Logger::Error&lt;&lt;"AXFR done for '"&lt;&lt;domain&lt;&lt;"'"&lt;&lt;endl;
+       </programlisting>
+      </para>
+      <sect2><title>Supermaster/Superslave capability</title>
+        <para>
+          A backend that wants to act as a 'superslave' for a master should implement the following method:
+          <programlisting>
+            class DNSBackend 
+            {
+               virtual bool superMasterBackend(const string &amp;ip, const string &amp;domain, const vector&lt;DNSResourceRecord&gt;&amp;nsset, string *account, DNSBackend **db)
+            };
+          </programlisting>
+          This function gets called with the IP address of the potential supermaster, the domain it is sending a notification for and the set of NS records
+          for this domain at that IP address. 
+        </para>
+        <para>
+          Using the supplied data, the backend needs to determine if this is a bonafide 'supernotification' which should be honoured. If it decides that it
+          should, the supplied pointer to 'account' needs to be filled with the configured name of the supermaster (if accounting is desired), and the 
+          db needs to be filled with a pointer to your backend.
+        </para>
+        <para>
+          Supermaster/superslave is a complicated concept, if this is all unclear see <xref linkend="supermaster">.
+      </sect2>
+    </sect1>
+    <sect1 id="master-backends"><title>Read/write master-capable backends</title>
+      <para>
+        In order to be a useful master for a domain, notifies must be sent out whenever a domain is changed. Periodically, PDNS
+        queries backends for domains that may have changed, and sends out notifications for slave nameservers.
+      </para>
+      <para>
+        In order to do so, PDNS calls the <function>getUpdatedMasters()</function> method. Like the <function>getUnfreshSlaveInfos()</function>
+        function mentioned above, this should add changed domain names to the vector passed.
+      </para>
+      <para>
+       The following excerpt from the DNSBackend shows the relevant functions:
+      </para>
+      <para>
+       <programlisting>
+         class DNSBackend {
+         public:
+           /* ... */
+          virtual void getUpdatedMasters(vector&lt;DomainInfo&gt;* domains);
+          virtual void setNotifed(int id, u_int32_t serial);
+           /* ... */
+        }
+       </programlisting>
+      </para>
+      <para>
+       These functions all have a default implementation that returns false - which explains that these methods can be omitted in simple backends. 
+
+       Furthermore, unlike with simple backends, a slave capable backend must make sure that the 'DNSBackend *db' field of the SOAData record is filled 
+       out correctly - it is used to determine which backend will house this zone. 
+
+       <variablelist>
+         <varlistentry>
+           <term>void getUpdatedMasters(vector&lt;DomainInfo&gt;* domains)</term>
+           <listitem>
+             <para>
+               When called, the backend should examine its list of master domains and add any changed ones to the DomainInfo vector
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>bool setNotified(int domain_id, u_int32_t serial)</term>
+           <listitem>
+             <para>
+                Indicate that notifications have been queued for this domain and that it need not be considered 'updated' anymore
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      </para>
+    </sect1>
+
+  </appendix>
+  <appendix id="compiling-powerdns"><title>Compiling PowerDNS</title>
+    <para>
+      The PowerDNS source is separated from many of its modules. The main PowerDNS source tree however is able
+      to pull in certain files for creating packaged releases.
+    </para>
+    <para>
+      First download the source or retrieve from anoncvs.powerdns.com (module 'powerdns'). If from cvs, you need to execute 
+      <filename>./bootstrap</filename> to have the GNU autotools build the configure script and the Makefiles.
+    </para>
+    <para>
+      The run ./configure, followed by 'make'. PowerDNS prefers being compiled with GCC 3.2 but 2.95.4 and 3.0.4 will also work on most systems.
+      It will not compile on Debian Potato because that lacks the <filename>sstream</filename> include file.
+    </para>
+    <para>
+      After compiling, the <filename>./installer</filename> script can be used to install. 
+    </para>
+    <sect1><title>Configuring external modules with PowerDNS</title>
+       <para>
+       A module needs to see the PowerDNS sources. See the INSTALL file of a module on how to configure this.
+       </para>
+    </sect1>
+  </book>
diff --git a/pdns/docs/powerdns-case.sgml b/pdns/docs/powerdns-case.sgml
new file mode 100644 (file)
index 0000000..7689ac2
--- /dev/null
@@ -0,0 +1,252 @@
+<!doctype linuxdoc system>
+
+<article>
+
+<!-- Title information -->
+<title>The case for PowerDNS</title>
+<author>PowerDNS BV (bert hubert &lt;bert@trilab.com&gt;) &nl;
+Trilab BV</author>
+<date>v1.0 $Date: 2002/11/27 15:18:34 $</date>
+<abstract>
+This document describes what PowerDNS is, how it works and how it can be
+maintained and operated.
+</abstract>
+<toc>
+<sect>The PowerDNS modular system
+<p>
+PowerDNS consists of four distinct modules:
+<itemize>
+<item>Internet Nameserver
+<item>Logical Engine
+<item>Query Backend
+<item>Web-enabled configuration
+</itemize>
+
+Each of these modules can function on its own, and is therefore eminently
+testable and provably correct.
+
+When a DNS query comes in ('What is the IP Address of come.to'), it is
+received by the Internet Nameserver, which parses the packet and sends it to
+the Logical Engine. The Logical Engine then tries to find the best answer
+possible to the question.
+
+To do so, it applies certain rules. Is 'come.to' a globally redirected host?
+If it isn't, is it perhaps an alias for another host? Or do we simply need
+to look up the IP address, and return that. Each of these questions is
+fielded to the Query Backend.
+
+This query backend often just translates the question into SQL, and passes
+it to a relational database, like Oracle, MS SQLServer or PostgreSQL.
+
+A web-frontend is provided for configuring PowerDNS. This frontend is
+multi-user aware, so responsibilities can be delegated, whereby each
+operator can only manage his or her domains.
+
+More on the frontend the relevant chapter.
+
+<sect>PowerDNS Operation &amp; Operational Limits
+<p>
+PowerDNS has been designed to be easy to operate and to function robustly.
+For example, should an unexpected exception occur, the program is restarted
+automatically, within seconds.
+
+<sect1>Installation
+<p>
+PowerDNS can span multiple computers, which either all connect to the same
+database, or each have their own mirrored copy. Normally, PowerDNS is sold
+using an ASP model. However, our initial customer may choose to have a
+local, privately owned installation.
+
+We will assist or even perform the installation for such a customer.
+
+Engineered for simplicity, configuring the nameserver itself (not the
+domains, these are configured using the web-frontend) is done from one
+single point, with only a limited number of settings that need to be
+changed.
+
+<sect1>Operational Limits
+<p>
+Extensive benchmarking has convinced us that network capacity is more of a
+limiting factor than PowerDNS itself will ever be. In testing, the PowerDNS
+server sustained 1500 queries/s on a regular desktop PC for a prolonged
+period of time. It is assumed that this is more than even the biggest
+current nameservers need to handle.
+
+<sect1>Maintaining and configuring domains
+<p>
+Great care has been taken to make the maintenance and configuration of
+domains as easy as possible. Two modes are available, 'Wizard' 
+and 'Advanced'. This latest mode is 'vocabulary compatible' with the Bind
+nameserver, so existing administrators will feel right at home. The Wizard
+mode has been stripped of all jargon, and should be easy to follow for most
+Internet users.
+
+The Wizard mode also performs stringent tests on the information entered by
+the operator, so as to prevent misconfiguration.
+
+<sect>Features
+<p>
+PowerDNS has the following features:
+<descrip>
+<tag>Regular nameserving</tag>
+A better performing and robust nameserver. Feature set is limited to current
+and near-future internet practices. Other nameservers often support arcane
+and outdated Name Classes, like those used at MIT in the 1980s. Supporting
+these classes involves shipping more code, which might contain more security
+problems and bugs. More on security in the relevant chapter.
+<tag>Failover</tag>
+When multiple webservers are available, PowerDNS can be configured to only
+return IP Addresses of the servers which are actually functioning. This
+feature has been available for a long time from companies like Alteon or
+Arrowpoint (now both Cisco property).
+
+However, these machines can only function on local networks, as they
+function as a network-element. All your servers need to be in the same
+location for this to work. This is clearly not appropriate in case of
+maximum availability. 
+<tag>Global Redirection</tag>
+In combination with Failover support, it is possible to support smart global
+redirection, whereby American customers might get connected to a server in
+New York, whereas European customers might be served by a computer in
+Amsterdam.
+
+<tag>Mail forwarding</tag>
+Although not strictly a Nameserver function, PowerDNS supports very rapid
+and robust mail forwarding. This system has already been employed the past
+months to forward mail for the V3 domains. It is specially engineered to not
+fall over in case of database problems, should they occur, for example when
+the database is suffering from a Denial of Service, as recently happened.
+
+<tag>URL Aliasing</tag>
+Much of the same goes for this. Customers can use URL Aliasing to let them
+point their (sub)domain to other webpages.
+
+<tag>Mail hosting</tag>
+The entire concept of mail hosting was re-engineered because it was found
+that existing systems suffered from sub-optimal performance, with a large
+server able to handle only 50.000 mailboxes at a time.
+
+This support consists of SMTP, Pop and IMAP4, which makes it compatible with
+almost all webmail solutions available.
+
+</descrip>
+
+<sect>Security and Reliability
+<p>
+<sect1>Security
+<p>
+Nameserving is a complex business. Currently, it is evident that existing
+servers suffer from security and Denial of Service vulnerabilities. 
+
+There are several reasons for these problems:
+<descrip>
+<tag>Support for obsolete protocols</tag>
+Nameservers currently in use support ancient pre-Internet protocols like
+Hesiod and Chaosnet. Even if you are an Internet-only user, like everybody
+these days, your nameserver will still respond to packets containing
+questions for these protocols. The code supporting these features stems from
+the early 1980s and hasn't been audited in ages.
+
+The support for these protocols also causes other nameservers to be bigger
+than they need be.
+
+<tag>Support for undesirable features</tag>
+This is the cause of the most recent bout of Bind problems. Bind 
+supports 'inverse queries', also known as 'iqueries'. This is a Jeopardy like
+situation whereby you ask a nameserver 'Which question has this answer'.
+These questions are no longer appropriate in a time where the Internet can
+at best be considered a unfriendly place.
+
+<tag>Complete integration</tag> 
+Current nameservers are completely integrated solutions, carrying within
+their codebase a complete database and replication facility - which is
+exposed to the world.  By offloading this functionality to a separate
+Relational Database, complexity is vastly reduced. Furthermore, relational
+databases are very trusted systems - it is good to leave the hard work to
+them.
+
+<tag>Use of outdated languages</tag>
+With languages like C it is very easy to make programming mistakes which
+endanger system security. By using C++ with full typechecking and dynamic
+strings, a lot of problems are avoided. It is no longer possible 
+to 'overflow the buffer', as it is called.
+</descrip>
+
+<sect1>Reliability 
+<p> 
+PowerDNS can be operated from two or more completely independent locations.
+Failure of the one does not hamper the other. Each of these locations can
+easily be redundant in itself. UDP, the protocol over which DNS questions
+are asked and answered on the internet, lends itself very well to clustering
+solutions. It is advised that each location consists of two unconnected
+computers in a failover setup. The 'Virtual Router Redundancy Protocol'
+suffices, one of the easiest ways to set up a redundant group of computers.
+
+Regular nameservers can only run off their secondary for a limited period of
+time (often measured in days!). PowerDNS does not have this limitation.
+
+<sect>Statistics, Logging &amp; Monitoring 
+<p>
+PowerDNS can be configured to keep extensive details on its operation. From
+these details, which are available in an easily parseable ASCII form, it is
+possible to compile statistics.
+
+Of possible interest are:
+<itemize>
+<item>Number of questions for which PowerDNS had no answer
+<item>Average time needed to find answer to a question
+<item>Number of questions per second handled
+</itemize>
+
+Should there be a need, graphs can be compiled in realtime using the popular
+MRTG utility, which is easily interfaced onto PowerDNS.
+
+<sect>PowerDNS as a Registrar or domain-merchant Backend
+<p>
+The Web-frontend that comes with PowerDNS is engineered to support millions
+of users simultaneously. When stripped of advanced features, it makes a fine
+platform for any Registrar or domain-merchant.
+
+Everything in PowerDNS has been designed for incredibly high performance, so
+it is possible to support huge numbers of users on limited amounts of
+hardware.
+
+There is no point in the system which needs to be implemented as a single
+computer - all parts can be grown to span multiple servers.
+
+<sect>Competition
+<p>
+Besides the widely used Bind nameserver, there are other solutions
+available. Each of these solutions has its pros and cons.
+<sect1>F5 3DNS
+<p>
+
+Based on an expanded version of BIND, it offers a lot of interesting
+features, like global redirection and loadbalancing. It needs 
+several 'probes' at your datacenters, which attempt to measure network 
+connectivity.
+
+Unclear how it scales to larger number of domains, or even subdomains. Might
+conflict with plans of being a 'subdomain registrar'.
+
+Can combine with the 'Big-IP Controller' for local failover and
+loadbalancing. 
+<sect1>Cisco Distributed Director
+<p>
+Is a weird contraption, which has been reported to take up to an hour to
+process any configuration changes. Uses complicated BGP metrics to calculate
+the optimum server for a user. In our experience, BGP is no longer the right
+way to do so. BGP differentiates the internet into so called Autonomous
+Subsystems. These days however, most of the AS's out there spread the globe.
+
+The Cisco Distributed Director will not be able to differentiate via BGP
+between a server or user located in San Francisco or one in Moscow, if both
+are in the MCI Worldcom network.
+
+This machine also appears to require machines at each server location.
+
+Also unclear how it handles large numbers of domains, especially given the
+time it needs to process configuration changes. 
+
+</article>
+
diff --git a/pdns/docs/powerdns-install.sgml b/pdns/docs/powerdns-install.sgml
new file mode 100644 (file)
index 0000000..acc415d
--- /dev/null
@@ -0,0 +1,183 @@
+<!doctype linuxdoc system>
+<article>
+
+<!-- Title information -->
+
+<title>PowerDNS 1.2 Install &amp; Usage guide
+<author>PowerDNS BV 
+Trilab BV
+<date>v1.1 $Date: 2002/11/27 15:18:35 $
+<abstract>
+This document provides information on how to install PowerDNS and on how
+to maintain it afterwards
+</abstract>
+
+<!-- Table of contents -->
+<toc>
+<!-- Begin the document -->
+<sect>Introduction
+<p>
+PowerDNS is a versatile high-performance modular nameserver that can answer
+questions based on a number of data sources, accessed via backend drivers.
+
+<sect>Compilation
+<p>
+See the INSTALL file that comes with the distribution.
+
+<sect>Syntax
+<p>
+The actual process is called 'ahudns' for historical reasons. It is expected
+that this will change in a future release.
+
+On startup, ahudns reads two files in the configuration directory
+(/usr/local/etc or /opt/ahudns/etc, or whatever was specified during
+compilation), ahudns.conf and ahudns.rc.
+
+<sect1>ahudns.conf
+<p>
+In the configuration directory, you will find ahudns.conf-dist which lists
+the small number of runtime configuration parameters available.
+
+These parameters can either be set via the commandline or via ahudns.conf.
+<descrip>
+<tag>cache-ttl=...</tag>
+Seconds to store packets in the PacketCache. Can be set to zero to
+disable the PacketCache entirely. This is non advised for busy sites. Values
+of in the order of 10 seconds already give appreciable hitrates (80%).
+<tag>default-soa-name=...</tag>
+Name to insert in the SOA record if none set in the backend. Either make
+sure that your backend data source contains complete SOA records, or set
+this to a useful value. This default to 'a.misconfigured.powerdns.server'!
+<tag>distributor-threads=...</tag>
+Default number of Distributor (backend) threads to start. This is very
+dependent on your needs and backend. Higher values are generally better, up
+to a point. MySQL performs very well with a value of 5, with tens of queries
+per second.
+<tag>fancy-records=...</tag>
+Process CURL, URL and MBOXFW records. These magic records are presently
+undocumented and should not be used.
+<tag>localaddress=...</tag>
+       Local IP address to which we bind. It can be important to set this -
+PowerDNS can get confused by machines with multiple NICs.
+<tag>localport=...</tag>
+       The port on which we listen. Should probably always be 53.
+<tag>loglevel=...</tag>
+       Amount of logging. Higher is more. Do not set below 3
+<tag>out-of-zone-additional-processing | out-of-zone-additional-processing=yes | out-of-zone-additional-processing=no </tag>
+       Do out of zone additional processing. Use this if all clients are
+trusted.
+<tag>smtpredirector=...</tag>
+       Our smtpredir MX host. Used for the MBOXFW record.
+<tag>urlredirector=...</tag>
+       Where we send hosts to that need to be url redirected. Used for URL
+and CURL.
+<tag>wildcards=...</tag>
+       Honor wildcards in the database. Switch this off for a significant
+performance gain. Off by default.
+</descrip>
+
+<sect1>ahudns.rc
+<p>
+Given the fact that PowerDNS is very modular, it can't expect to have all
+backend modules available at compile time. Therefore modules are loaded
+dynamically at runtime. This is done by executing the ahudns.rc script found
+in the configuration directory, where ahudns.conf also resides.
+
+You will find ahudns.rc-dist which you can rename to ahudns.rc, and edit at
+will to have PowerDNS load additional modules. 
+
+When no modules are loaded, the daemon responds to queries with a 'SERVFAIL'
+packet, indicating that client nameservers should query other servers.
+<sect>Controling ahudns
+<p>
+On startup, ahudns opens a 'controlsocket', which can be used to control the
+daemon. Use the provided 'dynloader' program to issue commands. The
+following commands can be useful:
+<descrip>
+<tag>list</tag>List all statistical variables available
+<tag>ping</tag>Ping the daemon - it will reply if all is well
+<tag>show</tag>Show the value of a specified variable
+<tag>quit</tag>Use this to shut ahudns down
+</descrip>
+
+Use like this: dynloader /opt/ahudns/var/ahudns.controlsocket [command]
+whereby the path refers to the controlsocket location. See the 'init.d'
+chapter for an easier way to control ahudns.
+
+<sect>Running ahudns
+<p>
+There are at least three ways of running ahudns &amp; smtpredir.
+
+<sect1>Directly
+<p>
+By default ahudns runs in the foreground, and can be run from any directory.
+The configuration directory to use is compiled in. In case of problems (out
+of memory, fatal errors), it will exit and not restart by default.
+
+Stop the daemon with the 'killall' or 'pkill command'
+<sect2>With the safe_ahudns wrapper
+<p>
+A better way of running ahudns is with the safe_ahudns wrapper, which is
+distributed with PowerDNS. 
+
+This approach is a lot like that taken by safe_mysql from the MySQL
+distribution, should ahudns ever fail for whatever reason, safe_ahudns will
+instantly restart it.
+
+To start ahudns, run '/opt/ahudns/bin/safe_ahudns &' and then check the log
+to see if the connection to the database succeeded.
+
+To stop, use the dynloader programm and pass the command 'quit', which will
+make the daemon exit with error code 99. safe_ahudns interprets 99 as a
+healthy exit with no need to restart the daemon.
+
+<sect1>Running controlled with init.d scripts 
+<p> 
+This is the preferred way of running ahudns. For easy control of both ahudns
+and smtpredir, use the init.d scripts provided in the 'sample' directory.
+They are usually placed in /etc/init.d, but because of unix variations, they
+are not installed there by default. 
+
+Available commands are 'stop', 'start', 'status' and 'restart'. The init.d
+scripts use the safe_* wrappers internally, which will take care of
+restarting the daemons if needed.
+
+<sect>Virtual configurations: running multiple nameservers on a single server
+<p>
+In order to have any number of separate ahudns and smtpredir installations
+there is the ability to specify different configuration files and
+configuration names. This allows you to stop and start the right daemon with
+ease.
+
+By default, all configuration lives in /opt/ahudns/etc, but this can be
+changed with the '--config-dir' commandline option. The recommended layout
+for virtual configurations is:
+
+<tscreen><verb>
+/opt/ahudns/etc                                For default configuration
+/opt/ahudns/etc-customer1              Customer1 directory
+/opt/ahudns/etc-customer1/ahudns.conf  Customer1 configuration
+/opt/ahudns/etc-customer1/ahudns.rc    Customer1 backends
+/opt/ahudns/etc-customer2              Customer2 directory
+/opt/ahudns/etc-customer2/ahudns.conf  Customer2 configuration
+/opt/ahudns/etc-customer2/ahudns.rc    Customer2
+/opt/ahudns/var/ahudns.controlsocket   Default control socket (for dynloader)
+/opt/ahudns/var/ahudns-customer1.controlsocket 
+/opt/ahudns/var/ahudns-customer2.controlsocket 
+</verb></tscreen>
+
+The init.d scripts are aware of virtual configurations. If the 'CONFIGNAME'
+parameter is set, they will automatically start and stop the right instance
+of the daemon, and also pass the name of the virtual configuration file. 
+
+Be aware that your ahudns.rc script should refer to the right controlsocket!
+
+A typical virtual installation will have several ahudns- files in
+/etc/init.d, with each a differing CONFIGNAME in the first few lines.
+
+<sect>Logging
+<p>
+Logging is regular syslog, with facility DAEMON. 
+
+</article>
\ No newline at end of file
diff --git a/pdns/docs/powerdns-overview.sgml b/pdns/docs/powerdns-overview.sgml
new file mode 100644 (file)
index 0000000..caed77e
--- /dev/null
@@ -0,0 +1,146 @@
+<!doctype linuxdoc system>
+
+<article>
+
+<!-- Title information -->
+<title>PowerDNS Overview</title>
+<author>PowerDNS BV (bert hubert &lt;bert@trilab.com&gt;) &nl;
+Trilab BV</author>
+<date>v1.0 $Date: 2002/11/27 15:18:35 $</date>
+<abstract>
+This document describes what PowerDNS is and what it is for
+</abstract>
+<toc>
+<sect>What is PowerDNS
+<p>
+PowerDNS consists of:
+<itemize>
+<item>A Nameserver
+<item>A Mailserver
+<item>A Webserver
+</itemize>
+<sect1>What is a Nameserver?
+<p>
+A Nameserver is a device which translates a human-friendly name 
+like 'www.cnn.com' into an Internet Protocol (IP) Address that can be used to
+connect to the actual webserver. This functionality is vital as the
+numerical IP Addresses are unknown to end users so an inability to serve
+names means an inability to serve webpages, or to receive mail.
+
+Due to the complexity and arcane rules surrounding the Domain Name System,
+only a very limited number of Nameserver implementations exist, with the
+vast majority of sites running the antiquated Bind program, which can trace
+it roots to the creation days of the Internet.
+
+<sect1>Nameservers are crucial and tricky to maintain
+<p>
+Nameservers are at the very core of the Internet. All domain operators will
+have experienced often day-long outages due to misconfiguration or other
+operator mistakes. This makes Nameservers somewhat of a no-go zone, with the
+actual configuration and server itself often considered sacred. Domain
+maintenance takes experience operators and is hard to delegate to junior
+personnel.
+
+<sect1>Fixing up the existing Nameservers is not enough
+<p>
+The current Bind program has a long history of security incidents, the most
+recent ones affecting nearly all Internet providers. Currently, even major
+providers are still running vulnerable versions of Bind. Neither HP nor Sun
+have released fixes recently, forcing companies running Nameservers to
+download unsupported versions directly from the Internet Software Consortium.
+
+Any enhancements which affect ease of use will not help improve the security
+situation. Bind predates the large-scale use of relational databases and
+therefore comes with its own built in directory. A paradigm of secure design
+is to use modular programs with clear trust relations between them.
+Integrating everything, including a complete database and replications
+mechanism within the Nameserver itself makes security nearly impossible to
+achieve.
+
+There is a clear need to reinvent the Nameserver.
+
+<sect>The PowerDNS Modular System
+<p>
+PowerDNS Nameserver consists of four distinct modules:
+<itemize>
+<item>Internet Nameserver
+<item>Logical Engine
+<item>Query Backend
+<item>Web-enabled configuration
+</itemize>
+
+Each of these modules can function on its own, and is therefore eminently
+testable and provably correct.
+
+When a DNS query comes in ('What is the IP Address of www.cnn.com'), it is
+received by the Internet Nameserver, which parses the packet and sends it to
+the Logical Engine. The Logical Engine then tries to find the best answer
+possible to the question.
+
+To do so, it applies certain rules. Is 'come.to' a globally redirected host?
+If it isn't, is it perhaps an alias for another host? Or do we simply need
+to look up the IP address, and return that. Each of these questions is
+fielded to the Query Backend.
+
+This query backend often just translates the question into SQL, and passes
+it to a relational database, like Oracle, MySQL, MS SQLServer or PostgreSQL.
+
+An error checking web-frontend is provided for configuring PowerDNS. This
+frontend is multi-user aware, so responsibilities can be delegated, whereby
+each operator can only manage his or her domains.
+
+<sect>Benefits
+<sect1>Modular security, use of a trusted database
+<p>
+Because of the fact that all data comes from a central database, the actual
+Nameserver is very small, outsourcing a lot of the complexity to existing
+and very well trusted database products.
+<sect1>Complete ISP integration into a single data warehouse
+<p>
+Use of a central data repository also means that, for the first time ever, a
+complete self contained ISP solution is possible. When a domain is added to
+the Webserver, the PowerDNS Nameserver is aware of this. If an email address
+is added to a domain, PowerDNS automatically sends the Internet to the right
+place to deliver the message.
+
+Although not obvious for the layman, this is a quantum leap improvement over
+the current situation where Nameservers are an unconnected and often
+independently or externally maintained part of a complete ISP solution.
+
+When operators first experience the integrated operation of PowerDNS they
+are often enveloped by a strong 'this is how it is supposed to be' feeling,
+only then realizing the strangeness of the situation up to now.
+
+<sect1>Very high performance
+<p>
+Storing and retrieving data at high speed is a problem that has been well
+solved by cheaply available database servers. By building on these existing
+products, PowerDNS scales just as well as the database. As there are
+database solutions out there that achieve tens of thousands of transactions
+per second, there is no bottleneck in sight.
+<sect1>Instant updates
+<p>
+Because of this high performance, it is possible to lower the so 
+called 'Time To Live' of DNS answers. This in turn means that changes to the
+Nameservers configuration go live nearly instantaneously, instead of taking
+over 24 hours to propagate, as is usually the case.
+<sect1>Interoperability
+<p>
+PowerDNS is, by design, very open. By conforming to all Internet RFCs that
+apply, interoperation with everything currently in use is easily possible.
+The source is unencumbered and can easily be supplied to major customers,
+both for improvements or to diagnose operating problems.
+
+<sect>PowerDNS is a complete Nameserving ISP solution
+<p>
+For the first time, the creation of Internet services can be done from an
+integrated high-performance platform. By reinventing the Nameserver, all
+major ISP functionality can be offered from a single database of user and
+domain data.
+
+By allowing easy web-management of this solution, especially Nameserver
+configuration has become easier and more robust then ever, surpassing
+previous 'Bind front-end' solutions in both performance and reliability.
+
+</article>
+
diff --git a/pdns/docs/powerdns-technical.sgml b/pdns/docs/powerdns-technical.sgml
new file mode 100644 (file)
index 0000000..d681ca8
--- /dev/null
@@ -0,0 +1,193 @@
+<!doctype linuxdoc system>
+
+<article>
+
+<!-- Title information -->
+<title>PowerDNS technical overview</title>
+<author>PowerDNS BV (bert hubert &lt;bert@trilab.com&gt;) &nl;
+Trilab BV</author>
+<date>v1.1 $Date: 2002/11/27 15:18:35 $</date>
+<abstract>
+This document contains a technical description of PowerDNS. 
+</abstract>
+<toc>
+<sect>PowerDNS is a next generation authoritative nameserver
+<p>
+DNS is among the most mission-critical parts of the internet. While in
+essence very simple, current implementations are complicated applications
+with source code often spanning dozens of megabytes.
+
+The growth of the number of domains means that there is a growing need for a
+lean and mean nameserver that is capable of serving millions of users with
+millions of domains.
+
+The operation of PowerDNS consists of three different parts:
+<itemize>
+<item>Internet Interface
+<item>Logical Engine
+<item>Query Backend
+</itemize>
+
+The Internet Interface receives a question, and hands it to the Logical
+Engine. This Logical Engine then splits up the question into the
+sub-queries, which are handed to the Query Backend, which in turn sends
+queries to any number of data sources. The answer is then transferred back by
+the Logical Engine to the Internet Interface, which sends out the packet
+containing the requested data.
+
+<descrip>
+<tag>The Internet Interface</tag>
+PowerDNS supports receiving queries over UDP and TCP. When a question is
+received, relevant parts of the packet containing the question are compared
+to queries received earlier. 
+
+<tag>The Logical Engine</tag>
+A DNS query cannot be translated directly into a backend query. A question
+might be 'What is the IP Address of www.site.com'. In order to answer this
+question, some separate steps need to be performed:
+
+<itemize>
+<item>Is this nameserver Authoritative for this domain, or any of its parent
+domains?
+<item>Do we have a Canonical Name for www.site.com?
+<item>Does www.site.com exist?
+<item>Do we have an IP address for it?
+<item>If we don't, do we know who does?
+<item>Possibly send IP addresses for the nameservers who do know
+</itemize>
+
+This algorithm is described at length in RFC 1034.
+
+<tag>The Query Backend</tag>
+A real life nameserver may have many data sources. Several customer
+databases might exist, as well as standard Zone files. The Query Backend
+fields questions to any number of backends, in a prescribed order. This
+allows for maximum flexibility.
+</descrip>
+
+<sect>Simplicity brings reliability 
+<p> 
+
+By building on top of existing databases, PowerDNS is as trustworthy as your
+favorite database. Data storage and retrieval is a well solved problem. A
+nameserver should not reinvent it. We support almost all industry standard
+databases and also do custom backend development to graft PowerDNS on an
+existing database or schema.
+
+Due to the completely from scratch implementation without an existing
+installed base to appease, PowerDNS has remained very lean and mean.
+
+Monitoring is at the root of reliability, so the PowerDNS runtime can be
+queried by external scripts. This enables the operator to be informed of any
+problems at an early stage. Some sample scripts for the popular MRTG program
+are supplied.
+
+<sect>Incredible performance
+<p>
+Because of the many steps of the algorithm prescribed by RFC 1034, just
+hooking on a database to a nameserver is not a recipe for great performance.
+Steps need to be taken to streamline the process. 
+
+PowerDNS does so in two ways: 
+<descrip>
+<tag>Reordering the steps of the algorithm</tag>
+It is often possible to skip some of the steps in the algorithm initially,
+and only perform the other steps when it is really needed, which is often
+not the case.
+<tag>The PacketCache</tag>
+The PacketCache is quite revolutionary in that it caches entire query
+packets for short amounts of time. This PacketCache is consulted before
+running the RFC 1034 Algorithm in the Logical Engine. In production, it has
+been confirmed that even a 1 minute cache can achieve a 80% hitrate and
+thereby prevent 4 out of 5 database queries from ever happening.
+</descrip>
+
+Benchmarking has shown that PowerDNS should be able to reach in the order of
+20.000 queries/second on a reasonably fast database. When using direct
+tables like those supported by Berkeley DB, 50.000 should be achievable.
+
+The use of POSIX Threads also allows PowerDNS to use a large number of
+processors efficiently on architectures that support it.
+<sect>Complete security
+<p>
+PowerDNS is written in highly portable C++ using the ISO Standard C++
+Library (STL). This Library comes with dynamic string classes which all but
+erase the possibility of the much feared buffer overflows that have been
+hitting other nameservers.
+
+The very modular design of PowerDNS also makes for strict internal
+interfaces which can prevent any undesired action from having deleterious
+effects.
+
+Due to the use of modern tools and libraries, PowerDNS consists of only 7000
+lines of source. This is very well auditable in a reasonable period of time
+and can be regarded as a trusted computing base.
+
+Because the database is most often external, it is highly useful to grant
+PowerDNS read-only access to that database. Even a successful compromise can
+than not easily be exploited, because the database refuses to accept updates
+from the nameserver.
+
+<sect>Special Functions
+<p>
+Besides doing lookups in well known databases such as Oracle, Microsoft SQL
+Server, MySQL, PostgreSQL and Sybase, there are special purpose backends
+available.
+
+<sect1>Very Large Zone support
+<p>
+For customers with very large zones and a lots of secondaries, a special
+module has been developed to meet the following goals:
+<itemize>
+<item>Absolute 100% robustness
+<item>Incremental updates
+<item>Near realtime updates
+<item>Idempotent update packets
+<item>Instantaneous zone reloading
+</itemize>
+
+In short, this means that updates are broadcast from a central point. These
+updates can be broadcast as many times as desired because there is no harm
+in applying them more than once. Each of these updates is applied within
+seconds. 
+
+It does not use a relational database but instead relies on any of the
+well known table engines that are available, with a strong slant towards
+Berkeley DB.
+<sect1>Global Redirection
+<p>
+With the aid of a comprehensive map of IP addresses, it is possible to do
+smart routing of customers to servers geographically near them. While not
+providing pin-point accuracy, it is broadly effective and very fast.
+
+<sect1>DNS based loadbalancing and failover
+<p>
+Because of the efficiency of PowerDNS, it is feasible to use very low TTLs
+on answers. This in turn makes it possible to perform DNS based
+loadbalancing and failover. This can be very robust because the DNS
+infrastructure itself is redundant, whereas regular loadbalancing agents are
+themselves a single point of failure.
+
+<sect1>CORBA backend
+<p>
+By allowing questions to be asked over this industry standard protocol,
+it becomes trivially easy to integrate PowerDNS with existing middleware
+applications and/or customer databases.
+
+<sect>Standards compliance
+<p>
+PowerDNS is committed to being fully standards compliant. Current supported
+standards include RFC 1034, RFC 1035 and RFC 2181. 
+
+<sect>Availability
+<p>
+PowerDNS is available immediately for use. It comes with completely
+documented source and a license that allows the end-user to improve and or
+change the source.
+
+Licensing is possible on a per-CPU or on a per-Domain basis. 
+
+PowerDNS is a fully supported product with different levels of support
+available.
+</article>
+
diff --git a/pdns/dynhandler.cc b/pdns/dynhandler.cc
new file mode 100644 (file)
index 0000000..250d266
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "dynhandler.hh"
+#include "statbag.hh"
+#include "logger.hh"
+#include "dns.hh"
+#include "arguments.hh"
+#include <signal.h>
+#include "misc.hh"\r
+#include "communicator.hh"
+
+static bool s_pleasequit;
+
+bool DLQuitPlease()
+{
+  return s_pleasequit;
+}
+
+string DLQuitHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  string ret="No return value";
+  if(parts[0]=="QUIT") {
+    s_pleasequit=true;
+    ret="Scheduling exit";
+    L<<Logger::Error<<"Scheduling exit on remote request"<<endl;
+  }
+  return ret;
+
+}
+
+static void dokill(int)
+{
+  exit(1);
+}
+
+string DLRQuitHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+#ifndef WIN32
+  signal(SIGALRM, dokill);
+
+  alarm(1);
+
+#else
+
+  if ( !PDNSService::instance()->isRunningAsService())
+    GenerateConsoleCtrlEvent( CTRL_C_EVENT, 0 );
+  else
+    PDNSService::instance()->stop();
+  
+#endif // WIN32
+
+  return "Exiting";
+}
+
+string DLPingHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  return "PONG";
+}
+
+string DLShowHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  extern StatBag S;
+  string ret("Wrong number of parameters");
+  if(parts.size()==2) {
+    if(parts[1]=="*")
+      ret=S.directory();
+    else
+      ret=S.getValueStr(parts[1]);
+  }
+
+  return ret;
+}
+
+static string d_status;
+
+void setStatus(const string &str)
+{
+  d_status=str;
+}
+
+string DLStatusHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  ostringstream os;
+  os<<ppid<<": "<<d_status;
+  return os.str();
+}
+
+string DLUptimeHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  ostringstream os;
+  os<<humanDuration(time(0)-s_starttime);
+  return os.str();
+}
+
+string DLPurgeHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  extern PacketCache PC;  
+  ostringstream os;
+  int ret;
+
+  if(parts.size()>1)
+    ret=PC.purge(parts[1]);
+  else
+    ret=PC.purge();
+  os<<ret;
+  return os.str();
+}
+
+string DLCCHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  extern PacketCache PC;  
+  map<char,int> counts=PC.getCounts();
+  ostringstream os;
+  bool first=true;
+  for(map<char,int>::const_iterator i=counts.begin();i!=counts.end();++i) {
+    if(!first) 
+      os<<", ";
+    first=false;
+
+    if(i->first=='!')
+      os<<"negative queries: ";
+    else if(i->first=='Q')
+      os<<"queries: ";
+    else if(i->first=='n')
+      os<<"non-recursive packets: ";
+    else if(i->first=='r')
+      os<<"recursive packets: ";
+    else 
+      os<<"unknown: ";
+
+    os<<i->second;
+  }
+
+  return os.str();
+}
+
+
+string DLSettingsHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  static const char *whitelist[]={"query-logging",0};
+  const char **p;
+
+  if(parts.size()!=3) {
+    return "Syntax: set variable value";
+  }
+  
+  for(p=whitelist;*p;p++)
+    if(*p==parts[1])
+      break;
+  if(p) {
+    arg().set(parts[1])=parts[2];
+    return "done";
+  }
+  else
+    return "This setting cannot be changed at runtime";
+
+}
+
+
+string DLVersionHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+
+  return VERSION;
+}
+
+
+string DLNotifyHostHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  extern CommunicatorClass Communicator;
+  ostringstream os;
+  if(parts.size()!=3)
+    return "syntax: notify domain ip";
+  L<<Logger::Warning<<"Notification request to host "<<parts[2]<<" for domain '"<<parts[1]<<"' received"<<endl;
+  Communicator.notify(parts[1],parts[2]);
+  return "Added to queue";
+}
+
+string DLNotifyHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  extern CommunicatorClass Communicator;
+  ostringstream os;
+  if(parts.size()!=2)
+    return "syntax: notify domain";
+  L<<Logger::Warning<<"Notification request for domain '"<<parts[1]<<"' received"<<endl;
+  if(!Communicator.notifyDomain(parts[1]))
+    return "Failed to add to the queue - see log";
+  return "Added to queue";
+}
+
+string DLRediscoverHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  PacketHandler P;
+  P.getBackend()->rediscover();
+  L<<Logger::Error<<"Rediscovery was requested"<<endl;
+  return "Ok";
+}
+
+string DLReloadHandler(const vector<string>&parts, Utility::pid_t ppid)
+{
+  PacketHandler P;
+  P.getBackend()->reload();
+  L<<Logger::Error<<"Reload was requested"<<endl;
+  return "Ok";
+}
diff --git a/pdns/dynhandler.hh b/pdns/dynhandler.hh
new file mode 100644 (file)
index 0000000..620814b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_DYNHANDLER_HH
+#define PDNS_DYNHANDLER_HH
+
+#include <vector>
+#include <string>
+#include <stdlib.h>
+#include <sys/types.h>
+\r
+#ifndef WIN32\r
+# include "config.h"\r
+# include <unistd.h>\r
+#else\r
+# include "pdnsservice.hh"\r
+#endif // WIN32\r
+
+using namespace std;
+
+
+bool DLQuitPlease();
+string DLQuitHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLRQuitHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLPingHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLShowHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLUptimeHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLSettingsHandler(const vector<string>&parts, Utility::pid_t ppid);
+void setStatus(const string &str);
+string DLCCHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLStatusHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLNotifyHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLNotifyHostHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLReloadHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLRediscoverHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLVersionHandler(const vector<string>&parts, Utility::pid_t ppid);
+string DLPurgeHandler(const vector<string>&parts, Utility::pid_t ppid);
+#endif /* PDNS_DYNHANDLER_HH */
diff --git a/pdns/dynlistener.cc b/pdns/dynlistener.cc
new file mode 100644 (file)
index 0000000..1b86487
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: dynlistener.cc,v 1.1 2002/11/27 15:18:33 ahu Exp $ 
+/* (C) Copyright 2002 PowerDNS.COM BV */
+#include <cstring>
+#include <string>
+#include <map>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <iostream>
+#include <sstream>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "misc.hh"
+#include "dns.hh"
+#include "arguments.hh"
+#include "dnsbackend.hh"
+#include "dynlistener.hh"
+#include "dnspacket.hh"
+#include "logger.hh"
+#include "statbag.hh"
+
+
+
+extern StatBag S;
+
+DynListener::DynListener(const string &pname)
+{
+  d_restfunc=0;
+  string programname=pname;
+
+  if(!programname.empty()) {
+    struct sockaddr_un local;
+    d_s=socket(AF_UNIX,SOCK_DGRAM,0);
+
+    if(d_s<0) {
+      L<<Logger::Error<<"creating socket for dynlistener: "<<strerror(errno)<<endl;;
+      exit(1);
+    }
+
+    int tmp=1;
+    if(setsockopt(d_s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
+      throw AhuException(string("Setsockopt failed: ")+strerror(errno));
+    
+    string socketname=arg()["socket-dir"]+"/";
+    cleanSlashes(socketname);
+    
+    if(!mkdir(socketname.c_str(),0700)) // make /var directory, if needed
+      L<<Logger::Warning<<"Created local state directory '"<<socketname<<"'"<<endl;
+    else if(errno!=EEXIST) {
+      L<<Logger::Critical<<"FATAL: Unable to create socket directory ("<<socketname<<") and it does not exist yet"<<endl;
+      exit(1);
+    }
+    
+    socketname+=programname+".controlsocket";
+    unlink(socketname.c_str());
+    memset(&local,0,sizeof(local));
+    local.sun_family=AF_UNIX;
+    strcpy(local.sun_path,socketname.c_str());
+    
+    if(bind(d_s, (sockaddr*)&local,sizeof(local))<0) {
+      L<<Logger::Critical<<"binding to dynlistener '"<<socketname<<"': "<<strerror(errno)<<endl;
+      exit(1);
+    }
+    if(!arg()["setgid"].empty()) {
+      if(chown(socketname.c_str(),static_cast<uid_t>(-1),Utility::makeGidNumeric(arg()["setgid"]))<0)
+       L<<Logger::Error<<"Unable to change group ownership of controlsocket: "<<strerror(errno)<<endl;
+      if(chmod(socketname.c_str(),0660)<0)
+       L<<Logger::Error<<"Unable to change group access mode of controlsocket: "<<strerror(errno)<<endl;
+    }
+      
+
+    L<<Logger::Warning<<"Listening on controlsocket in '"<<socketname<<"'"<<endl;
+    d_udp=true;
+  }
+  else
+    d_udp=false;
+  
+
+}
+
+void DynListener::go()
+{
+  d_ppid=getpid();
+  pthread_create(&d_tid,0,&DynListener::theListenerHelper,this);
+}
+
+void *DynListener::theListenerHelper(void *p)
+{
+  DynListener *us=static_cast<DynListener *>(p);
+  us->theListener();
+  return 0;
+}
+
+string DynListener::getLine()
+{
+  char mesg[512];
+  memset(mesg,0,sizeof(mesg));
+  int len;
+    
+  if(d_udp) {
+    d_addrlen=sizeof(d_remote);
+
+    if((len=recvfrom(d_s,mesg,512,0,(sockaddr*) &d_remote, &d_addrlen))<0) {
+      L<<Logger::Error<<"Unable to receive packet from controlsocket ("<<d_s<<") - exiting: "<<strerror(errno)<<endl;
+      exit(1);
+    }
+  }
+  else {
+    if(isatty(0))
+      write(1, "% ", 2);
+    if((len=read(0,mesg,512))<0) 
+      throw AhuException("Reading from the control pipe: "+stringerror());
+    else if(len==0)
+      throw AhuException("Guardian exited - going down as well");
+  }
+  
+  return mesg;
+}
+
+void DynListener::sendLine(const string &l)
+{
+  if(d_udp)
+    sendto(d_s,l.c_str(),l.length()+1,0,(struct sockaddr *)&d_remote,d_addrlen);       
+  else {
+    string line=l;
+    line.append("\n");
+    write(1,line.c_str(),line.length());
+  }
+}
+
+void DynListener::registerFunc(const string &name, g_funk_t *gf)
+{
+  d_funcdb[name]=gf;
+}
+
+void DynListener::registerRestFunc(g_funk_t *gf)
+{
+  d_restfunc=gf;
+}
+
+void DynListener::theListener()
+{
+  try {
+    map<string,string> parameters;
+
+    for(;;) {
+      string line=getLine();
+      chomp(line,"\n");
+
+      vector<string>parts;
+      stringtok(parts,line," ");
+      if(parts.empty()) {
+       sendLine("Empty line");
+       continue;
+      }
+      upperCase(parts[0]);
+      if(!d_funcdb[parts[0]]) {
+       if(d_restfunc) 
+         sendLine((*d_restfunc)(parts,d_ppid));
+       else
+         sendLine("Unknown command: '"+parts[0]+"'");
+       continue;
+      }
+
+      sendLine((*d_funcdb[parts[0]])(parts,d_ppid));
+    }
+  }
+  catch(AhuException &AE)
+    {
+      L<<Logger::Error<<"Fatal: "<<AE.reason<<endl;
+    }
+  catch(string &E)
+    {
+      L<<Logger::Error<<"Fatal: "<<E<<endl;
+    }
+  catch(...)
+    {
+      L<<Logger::Error<<"Fatal: unknown exception occured"<<endl;
+    }
+}
+
diff --git a/pdns/dynlistener.hh b/pdns/dynlistener.hh
new file mode 100644 (file)
index 0000000..6394f23
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_DYNLISTENER
+#define PDNS_DYNLISTENER
+
+#include <string>
+#include <vector>
+#include <pthread.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <iostream>
+#include <sstream>
+\r
+#ifndef WIN32\r
+#include <unistd.h>\r
+#include <sys/un.h>\r
+#include <dlfcn.h>\r
+\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#endif // WIN32\r
+\r
+using namespace std;
+
+class DynListener
+{
+public:
+  DynListener(const string &pname="");
+  void go();
+  void theListener();
+  static void *theListenerHelper(void *p);
+
+  typedef string g_funk_t(const vector<string> &parts, Utility::pid_t ppid); // guido!
+  typedef map<string,g_funk_t *> g_funkdb_t;
+  
+  void registerFunc(const string &name, g_funk_t *gf);
+  void registerRestFunc(g_funk_t *gf);
+private:
+  void sendLine(const string &line);
+  string getLine();\r
+\r
+#ifndef WIN32
+  struct sockaddr_un d_remote;\r
+#else\r
+  HANDLE m_pipeHandle;\r
+#endif // WIN32\r
+  
+  Utility::socklen_t d_addrlen;
+
+  int d_s;
+  pthread_t d_tid;
+  bool d_udp;
+  pid_t d_ppid;
+  
+
+  g_funkdb_t d_funcdb;
+  g_funk_t* d_restfunc;
+
+};
+#endif /* PDNS_DYNLISTENER */
diff --git a/pdns/dynloader.cc b/pdns/dynloader.cc
new file mode 100644 (file)
index 0000000..95f47b3
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+#include <errno.h>
+#include <climits>
+#include <string>
+#include <map>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include "ahuexception.hh"
+#include "misc.hh"
+#include "dynmessenger.hh"
+#include "arguments.hh"
+#include "config.h"
+#include "statbag.hh"
+#include "misc.hh"
+using namespace std;
+
+ArgvMap &arg()
+{
+  static ArgvMap arg;
+  return arg;
+}
+
+StatBag S;
+
+int main(int argc, char **argv)
+{
+  string s_programname="pdns";
+  string localdir;
+
+  static char pietje[128]="!@@SYSCONFDIR@@:";
+  arg().set("config-dir","Location of configuration directory (pdns.conf)")=
+    strcmp(pietje+1,"@@SYSCONFDIR@@:") ? pietje+strlen("@@SYSCONFDIR@@:")+1 : SYSCONFDIR;
+  
+  arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
+  arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
+  arg().set("chroot","")="";
+  arg().laxParse(argc,argv);
+
+  if(arg()["config-name"]!="") 
+    s_programname+="-"+arg()["config-name"];
+
+  string configname=arg()["config-dir"]+"/"+s_programname+".conf";
+  cleanSlashes(configname);
+  
+  arg().laxFile(configname.c_str());
+  string socketname=arg()["socket-dir"]+"/"+s_programname+".controlsocket";
+  if(arg()["chroot"].empty())
+    localdir="/tmp";
+  else
+    localdir=dirname(strdup(socketname.c_str()));
+
+
+  const vector<string>&commands=arg().getCommands();
+
+  if(commands.empty()) {
+    cerr<<"No command passed"<<endl;
+    return 0;
+  }
+
+  try {
+    string command=commands[0];
+
+    DynMessenger D(localdir,socketname);
+
+    string message;
+    for(vector<string>::const_iterator i=commands.begin();i!=commands.end();++i) {
+      if(i!=commands.begin())
+       message+=" ";
+      message+=*i;
+    }
+    
+    if(command=="show") {
+      message="SHOW ";
+      for(unsigned int n=1;n<commands.size();n++) {
+       message+=commands[n];
+       message+=" ";
+      }
+    }
+    else if(command=="list") {
+      message="SHOW *";
+      command="show";
+    }
+    else if(command=="quit" || command=="QUIT") {
+      message="QUIT";
+    }
+    else if(command=="status" || command=="STATUS") {
+      message="STATUS";
+    }
+    else if(command=="version" || command=="VERSION") {
+      message="VERSION";
+    }
+    
+    
+    if(D.send(message)<0) {
+      cerr<<"Error sending command"<<endl;
+      return 1;
+    }
+    
+    string resp=D.receive();
+    
+    cout<<resp<<endl;
+  }
+  catch(AhuException &ae) {
+    cerr<<"Fatal error: "<<ae.reason<<endl;
+  }
+  return 0;
+}
+
+
diff --git a/pdns/dynmessenger.cc b/pdns/dynmessenger.cc
new file mode 100644 (file)
index 0000000..858327d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "dynmessenger.hh"
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+DynMessenger::DynMessenger(const string &localdir, const string &fname)
+{
+  d_s=socket(AF_UNIX,SOCK_DGRAM,0);
+  
+  if(d_s<0) {
+    throw AhuException(string("socket")+strerror(errno));
+  }
+  
+  memset(&d_local,0,sizeof(d_local));
+
+  string localname=localdir;
+
+  localname+="/lsockXXXXXX";
+  d_local.sun_family=AF_UNIX;
+  strcpy(d_local.sun_path,localname.c_str());
+
+  if(mkstemp(d_local.sun_path)<0)
+    throw AhuException("Unable to generate local temporary file: "+string(strerror(errno)));
+  
+  unlink(d_local.sun_path);
+  
+  if(bind(d_s, (sockaddr*)&d_local,sizeof(d_local))<0) 
+    throw AhuException("Unable to bind to local temporary file: "+string(strerror(errno)));
+  
+  if(chmod(d_local.sun_path,0666)<0) { // make sure that pdns can reply!
+    perror("fchmod");
+    exit(1);
+  }
+
+  memset(&d_remote,0,sizeof(d_remote));
+  
+  d_remote.sun_family=AF_UNIX;
+  strcpy(d_remote.sun_path,fname.c_str());
+}
+
+DynMessenger::~DynMessenger()
+{
+  if(unlink(d_local.sun_path)<0)
+    cerr<<"Warning: unable to unlink local unix domain endpoint: "<<strerror(errno)<<endl;
+  close(d_s);
+}   
+
+int DynMessenger::send(const string &msg) const
+{
+  if(sendto(d_s,msg.c_str(),strlen(msg.c_str())+1,
+           0,(struct sockaddr *)&(d_remote),
+           sizeof(d_remote))<0)
+    {
+      perror("sendto");
+      return -1;
+    }
+  return 0;
+
+}
+
+/*
+       int  recvfrom(int  s,  void  *buf,  size_t len, int flags,
+       struct sockaddr *from, socklen_t *fromlen);
+*/
+
+string DynMessenger::receive() const 
+{
+  char buffer[512];
+  struct sockaddr_un dontcare;
+  unsigned int len=sizeof(dontcare);
+  int retlen;
+  retlen=recvfrom(d_s,buffer,sizeof(buffer),0,(struct sockaddr *)&dontcare,&len);
+  // FIXME XXX error checking!
+  buffer[retlen]=0;
+  string answer=buffer;
+  return answer;
+}
+
diff --git a/pdns/dynmessenger.hh b/pdns/dynmessenger.hh
new file mode 100644 (file)
index 0000000..4b70e46
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef DYNMESSENGER_HH
+#define DYNMESSENGER_HH
+
+#include <string>
+#include <sys/types.h>
+
+#ifndef WIN32
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <sys/un.h>
+# include <unistd.h>
+# include <libgen.h>
+
+#else
+# include "pdnsservice.hh"
+
+#endif // WIN32
+
+#include <errno.h>
+#include "ahuexception.hh"
+
+using namespace std;
+
+//! The DynMessenger can send messages to UNIX domain sockets
+class DynMessenger
+{
+  int d_s;
+
+#ifndef WIN32
+  struct sockaddr_un d_local; // our local address
+  struct sockaddr_un d_remote; // our remote address
+
+#else
+  HANDLE m_pipeHandle; // Named pipe handle.
+
+#endif // WIN32
+  
+
+  DynMessenger(const DynMessenger &); // NOT IMPLEMENTED
+  
+public:
+  // CREATORS
+
+  DynMessenger(const string &ldir, const string &filename);  //!< Create a DynMessenger sending to this file
+  ~DynMessenger();
+
+  // ACCESSORS
+  int send(const string &message) const; //!< Send a message to a DynListener
+  string receive() const; //!< receive an answer from a DynListener
+};
+#endif
diff --git a/pdns/extra/Makefile b/pdns/extra/Makefile
new file mode 100644 (file)
index 0000000..5c2f699
--- /dev/null
@@ -0,0 +1,12 @@
+# $Id: Makefile,v 1.1 2002/11/27 15:18:37 ahu Exp $ 
+
+all:  null.o
+
+install:
+
+distdir: 
+
+distclean: clean
+
+clean:
+       rm -f null.o *.o *.so
diff --git a/pdns/extra/null.c b/pdns/extra/null.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pdns/install-sh b/pdns/install-sh
new file mode 100755 (executable)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/pdns/installer b/pdns/installer
new file mode 100755 (executable)
index 0000000..6f29cfa
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/sh 
+#
+# The installer queries the user for right places to install the software.
+# It offers three standard possibilities:
+#
+# Overwriting strategy. Binaries are overwritten, configuration files not,
+# new files are placed suffixed by '.new'. Example:
+# /etc/powerdns/pdns.conf-new
+
+if [ "x$1" != "x" ] 
+then
+       . $1
+else
+       . ./pathconfig
+fi
+
+DESTDIR=${DESTDIR:-}   # debian interface
+
+BINARIES="pdns_server pdns_control backends/bind/zone2sql"
+
+if test -n "$LD_LIBRARY_PATH" 
+then
+       LD_LIBRARY_PATH="$LD_LIBRARY_PATH:`pwd`/libs"
+else
+       LD_LIBRARY_PATH="`pwd`/libs"
+fi
+
+./binpatch ./pdns_server $CONFIGPATH
+./binpatch ./pdns_control $CONFIGPATH
+mkdir -p $DESTDIR$BINARYPATH > /dev/null 2> /dev/null
+strip $BINARIES
+cp $BINARIES $DESTDIR$BINARYPATH
+
+if test -n "$DOCPATH"
+then
+       mkdir -p $DESTDIR$DOCPATH > /dev/null 2> /dev/null
+       cp -r README LICENSE docs/pdns.txt docs/pdns.pdf docs/pdns.txt docs/html $DESTDIR$DOCPATH 2> /dev/null
+fi
+
+mkdir -p $DESTDIR$CONFIGPATH > /dev/null 2> /dev/null
+
+if test -d ./libs
+then
+       mkdir -p $DESTDIR$LIBRARYPATH > /dev/null 2> /dev/null
+       cp ./libs/* $DESTDIR$LIBRARYPATH
+fi
+
+if test -s $DESTDIR$CONFIGPATH/pdns.conf
+then
+       suf=".new"
+       echo $DESTDIR$CONFIGPATH/pdns.conf exists, making $DESTDIR$CONFIGPATH/pdns.conf$suf
+else
+       suf=""
+fi
+
+echo "# Added by install script" > $DESTDIR$CONFIGPATH/pdns.conf$suf
+echo "module-dir=$LIBRARYPATH" >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+echo "socket-dir=$SOCKETPATH" >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+echo "setuid=$PDNSUID" >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+echo "setgid=$PDNSGID" >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+echo "launch=bind" >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+
+echo "# end " >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+$DESTDIR$BINARYPATH/pdns_server --config >> $DESTDIR$CONFIGPATH/pdns.conf$suf
+
+
+mkdir -p $DESTDIR$INITDPATH/ > /dev/null 2> /dev/null
+mkdir -p $DESTDIR$SOCKETPATH/ > /dev/null 2> /dev/null
+
+echo "#!/bin/sh" > $DESTDIR$INITDPATH/pdns
+echo "BINARYPATH=$BINARYPATH" >> $DESTDIR$INITDPATH/pdns
+echo "SOCKETPATH=$SOCKETPATH" >> $DESTDIR$INITDPATH/pdns
+echo export LD_LIBRARY_PATH=$LIBRARYPATH:\$LD_LIBRARY_PATH >> $DESTDIR$INITDPATH/pdns
+
+cat pdns.in >> $DESTDIR$INITDPATH/pdns
+chmod +x $DESTDIR$INITDPATH/pdns
+
diff --git a/pdns/iputils.hh b/pdns/iputils.hh
new file mode 100644 (file)
index 0000000..674c907
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_IPUTILSHH
+#define PDNS_IPUTILSHH
+
+#include <string>
+\r
+#ifndef WIN32\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <arpa/inet.h>\r
+#endif // WIN32\r
+\r
+#include <iostream>
+#include <stdio.h>
+#include <functional>
+#include "ahuexception.hh"
+
+using namespace std;
+
+/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
+class NetmaskException: public AhuException 
+{
+public:
+  NetmaskException(const string &a) : AhuException(a) {}
+};
+
+/** This class represents a netmask and can be queried to see if a certain
+    IP address is matched by this mask */
+
+class Netmask
+{
+public:
+  //! Constructor supplies the mask, which cannot be changed 
+  Netmask(const string &mask) 
+  {
+    char *p;
+    char bits=32;
+    if((p=strchr(mask.c_str(),'/')))
+      bits=atoi(p+1);
+
+    d_mask=~((1<<(32-bits))-1);     // 1<<16 0000 0000  0000 0000  0000 0000  0000 0000
+
+    struct in_addr a;
+    if(!Utility::inet_aton(mask.substr(0,p-mask.c_str()).c_str(), &a))
+      throw NetmaskException("Unable to convert '"+mask+"' to a netmask");
+    d_network=htonl(a.s_addr);
+  }
+
+  //! If this IP address in socket address matches
+  bool match(const struct sockaddr_in *ip) const
+  {
+    return match(htonl((unsigned int)ip->sin_addr.s_addr));
+  }
+
+  //! If this ASCII IP address matches
+  bool match(const string &ip) const
+  {
+    struct in_addr a;
+    Utility::inet_aton(ip.c_str(), &a);
+    return match(htonl(a.s_addr));
+  }
+
+  //! If this IP address in native format matches
+  bool match(u_int32_t ip) const
+  {
+    return (ip & d_mask) == (d_network & d_mask);
+  }
+
+
+private:
+  u_int32_t d_network;
+  u_int32_t d_mask;
+};
+
+/** This class represents a group of supplemental Netmask classes. An IP address matchs
+    if it is matched by zero or more of the Netmask classes within.
+*/
+class NetmaskGroup
+{
+public:
+  //! If this IP address is matched by any of the classes within
+  bool match(struct sockaddr_in *ip)
+  {
+    for(container_t::const_iterator i=d_masks.begin();i!=d_masks.end();++i)
+      if(i->match(ip))
+       return true;
+
+    return false;
+  }
+  //! Add this Netmask to the list of possible matches
+  void addMask(const string &ip)
+  {
+    d_masks.push_back(Netmask(ip));
+  }
+  
+  bool empty()
+  {
+    return d_masks.empty();
+  }
+
+private:
+  typedef vector<Netmask> container_t;
+  container_t d_masks;
+  
+};
+
+#endif
diff --git a/pdns/lock.hh b/pdns/lock.hh
new file mode 100644 (file)
index 0000000..1f6c1d9
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef LOCK_HH
+#define LOCK_HH
+
+#include <pthread.h>
+#include <errno.h>
+#include "misc.hh"
+#include "ahuexception.hh"
+class Lock
+{
+  pthread_mutex_t *d_lock;
+public:
+
+  Lock(pthread_mutex_t *lock) : d_lock(lock)
+  {
+    if((errno=pthread_mutex_lock(d_lock)))
+      throw AhuException("error acquiring lock: "+stringerror());
+  }
+  ~Lock()
+  {
+    pthread_mutex_unlock(d_lock);
+  }
+};
+
+class WriteLock
+{
+  pthread_rwlock_t *d_lock;
+public:
+
+  WriteLock(pthread_rwlock_t *lock) : d_lock(lock)
+  {
+    if((errno=pthread_rwlock_wrlock(d_lock))) {
+      throw AhuException("error acquiring rwlock wrlock: "+stringerror());
+    }
+  }
+  ~WriteLock()
+  {
+    pthread_rwlock_unlock(d_lock);
+  }
+};
+
+class TryWriteLock
+{
+  pthread_rwlock_t *d_lock;
+  bool d_havelock;
+public:
+
+  TryWriteLock(pthread_rwlock_t *lock) : d_lock(lock)
+  {
+    d_havelock=false;
+    if((errno=pthread_rwlock_trywrlock(d_lock)) && errno!=EBUSY)
+      throw AhuException("error acquiring rwlock tryrwlock: "+stringerror());
+    d_havelock=(errno==0);
+  }
+  ~TryWriteLock()
+  {
+    if(d_havelock)
+      pthread_rwlock_unlock(d_lock);
+  }
+  bool gotIt()
+  {
+    return d_havelock;
+  }
+};
+
+class TryReadLock
+{
+  pthread_rwlock_t *d_lock;
+  bool d_havelock;
+public:
+
+  TryReadLock(pthread_rwlock_t *lock) : d_lock(lock)
+  {
+    
+    d_havelock=false;
+    if((errno=pthread_rwlock_tryrdlock(d_lock)) && errno!=EBUSY)
+      throw AhuException("error acquiring rwlock tryrdlock: "+stringerror());
+    d_havelock=(errno==0);
+  }
+  ~TryReadLock()
+  {
+    if(d_havelock)
+      pthread_rwlock_unlock(d_lock);
+  }
+  bool gotIt()
+  {
+    return d_havelock;
+  }
+};
+
+
+class ReadLock
+{
+  pthread_rwlock_t *d_lock;
+public:
+
+  ReadLock(pthread_rwlock_t *lock) : d_lock(lock)
+  {
+    if((errno=pthread_rwlock_rdlock(d_lock)))
+      throw AhuException("error acquiring rwlock tryrwlock: "+stringerror());
+  }
+  ~ReadLock()
+  {
+    pthread_rwlock_unlock(d_lock);
+  }
+  
+  void upgrade()
+  {
+    pthread_rwlock_unlock(d_lock);
+    pthread_rwlock_wrlock(d_lock);
+  }
+
+};
+
+
+#endif
diff --git a/pdns/logger.cc b/pdns/logger.cc
new file mode 100644 (file)
index 0000000..60ed47b
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "logger.hh"
+#include "statbag.hh"
+
+using namespace std;
+
+Logger &theL(const string &pname)
+{
+  static Logger l("");
+  if(!pname.empty())
+    l.setName(pname);
+  return l;
+}
+
+void Logger::log(const string &msg, Urgency u)
+{
+  struct tm tm;
+  time_t t;
+  time(&t);
+  tm=*localtime(&t);
+
+  if(u<=consoleUrgency) {// Sep 14 06:52:09
+    char buffer[50];
+    strftime(buffer,sizeof(buffer),"%b %d %H:%M:%S ", &tm);
+    clog<<buffer;
+    clog <<msg <<endl;
+  }
+  extern StatBag S;
+  S.ringAccount("logmessages",msg);
+  syslog(u,"%s",msg.c_str());
+}
+
+void Logger::toConsole(Urgency u)
+{
+
+  consoleUrgency=u;
+}
+
+void Logger::open()
+{
+  if(opened)
+    closelog();
+  openlog(name.c_str(),flags,d_facility);
+  opened=true;
+}
+
+void Logger::setName(const string &_name)
+{
+  name=_name;
+  open();
+}
+
+Logger::Logger(const string &n, int facility)
+{
+  opened=false;
+  flags=LOG_PID|LOG_NDELAY;
+  d_facility=facility;
+  consoleUrgency=Error;
+  name=n;
+  pthread_mutex_init(&lock,0);
+  open();
+
+}
+
+Logger& Logger::operator<<(Urgency u)
+{
+  pthread_mutex_lock(&lock);
+
+  d_outputurgencies[pthread_self()]=u;
+
+  pthread_mutex_unlock(&lock);
+  return *this;
+}
+
+Logger& Logger::operator<<(const string &s)
+{
+  pthread_mutex_lock(&lock);
+
+  if(!d_outputurgencies.count(pthread_self())) // default urgency
+    d_outputurgencies[pthread_self()]=Info;
+
+  //  if(d_outputurgencies[pthread_self()]<=(unsigned int)consoleUrgency) // prevent building strings we won't ever print
+      d_strings[pthread_self()].append(s);
+
+  pthread_mutex_unlock(&lock);
+  return *this;
+}
+
+Logger& Logger::operator<<(int i)
+{
+  ostringstream tmp;
+  tmp<<i;
+
+  *this<<tmp.str();
+
+  return *this;
+}
+
+Logger& Logger::operator<<(ostream & (&)(ostream &))
+{
+  // *this<<" ("<<(int)d_outputurgencies[pthread_self()]<<", "<<(int)consoleUrgency<<")";
+  pthread_mutex_lock(&lock);
+
+
+  log(d_strings[pthread_self()], d_outputurgencies[pthread_self()]);
+  d_strings.erase(pthread_self());  
+  d_outputurgencies.erase(pthread_self());
+
+  pthread_mutex_unlock(&lock);
+  return *this;
+}
diff --git a/pdns/logger.hh b/pdns/logger.hh
new file mode 100644 (file)
index 0000000..5af2b08
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef LOGGER_HH
+#define LOGGER_HH
+/* (C) 2002 POWERDNS.COM BV */
+
+#include <string>
+#include <map>
+#include <ctime>
+#include <iostream>
+#include <sstream>
+#include <pthread.h>
+
+#ifndef WIN32
+# include <syslog.h>
+
+#else
+# define WINDOWS_LEAN_AND_MEAN
+# include <windows.h>
+
+#endif // WIN32
+
+using namespace std;
+
+//! The Logger class can be used to log messages in various ways.
+class Logger
+{
+public:
+#ifndef WIN32
+  Logger(const string &, int facility=LOG_DAEMON); //!< pass the identification you wish to appear in the log
+
+  //! The urgency of a log message
+  enum Urgency {All=99999,NTLog=12345,Alert=LOG_ALERT, Critical=LOG_CRIT, Error=LOG_ERR, Warning=LOG_WARNING,
+               Notice=LOG_NOTICE,Info=LOG_INFO, Debug=LOG_DEBUG, None=-1};
+
+#else
+  Logger( const string &, int facility = 0 ); //!< pass the identification you wish to appear in the log
+
+  //! The urgency of a log message
+  enum Urgency 
+  {
+    All     = 99999,
+    NTLog   = 12345,
+    Alert   = EVENTLOG_ERROR_TYPE, 
+    Critical= EVENTLOG_ERROR_TYPE, 
+    Error   = EVENTLOG_ERROR_TYPE, 
+    Warning = EVENTLOG_WARNING_TYPE,
+               Notice  = EVENTLOG_INFORMATION_TYPE,
+    Info    = EVENTLOG_INFORMATION_TYPE, 
+    Debug   = EVENTLOG_INFORMATION_TYPE, 
+    None    = -1
+  };
+
+  void toNTLog( void );
+
+private:
+  //! Handle used to communicate with the event log.
+  HANDLE m_eventLogHandle;
+
+  //! Log file handle.
+  FILE *m_pLogFile;
+
+  //! Log current message to the NT log?
+  map< pthread_t, bool > m_toNTLog;
+
+public:
+
+#endif // WIN32
+
+  /** Log a message. 
+      \param msg Message you wish to log 
+      \param Urgency Urgency of the message you wish to log
+  */
+  void log(const string &msg, Urgency u=Notice); 
+
+  void setFacility(int f){d_facility=f;open();} //!< Choose logging facility
+  void setFlag(int f){flags|=f;open();} //!< set a syslog flag
+  void setName(const string &);
+
+  //! set lower limit of urgency needed for console display. Messages of this urgency, and higher, will be displayed
+  void toConsole(Urgency);
+
+  //! Log to a file.
+  void toFile( const string & filename );
+  
+  void resetFlags(){flags=0;open();} //!< zero the flags
+  /** Use this to stream to your log, like this:
+      \code
+      L<<"This is an informational message"<<endl; // logged at default loglevel (Info)
+      L<<Logger::Warning<<"Out of diskspace"<<endl; // Logged as a warning 
+      L<<"This is an informational message"<<endl; // logged AGAIN at default loglevel (Info)
+      \endcode
+  */
+  Logger& operator<<(const string &s);   //!< log a string
+  Logger& operator<<(int);   //!< log an int
+  Logger& operator<<(Urgency);    //!< set the urgency, << style
+
+#ifndef WIN32
+  Logger& operator<<(ostream & (&)(ostream &)); //!< this is to recognise the endl, and to commit the log
+#else
+  // This is a hack to keep MSVC from generating a internal compiler error.
+  Logger& operator<<(ostream & (hack)(ostream &)); //!< this is to recognise the endl, and to commit the log
+#endif // WIN32
+
+private:
+  map<pthread_t,string>d_strings;
+  map<pthread_t,Urgency> d_outputurgencies;
+  void open();
+  string name;
+  int flags;
+  int d_facility;
+  bool opened;
+  Urgency consoleUrgency;
+  pthread_mutex_t lock;
+};
+
+extern Logger &theL(const string &pname="");
+
+#ifdef VERBOSELOG
+#define DLOG(x) x
+#else
+#define DLOG(x) 
+#endif
+
+
+#endif
diff --git a/pdns/ltmain.sh b/pdns/ltmain.sh
new file mode 100644 (file)
index 0000000..a926477
--- /dev/null
@@ -0,0 +1,5029 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# 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.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.4.2a
+TIMESTAMP=" (1.922.2.79 2001/11/28 21:50:31)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \015\012 \040\040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+  save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+: ${IFS="      "}
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  echo "$modename: not configured to build any kind of library" 1>&2
+  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+  arg="$1"
+  shift
+
+  case $arg in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case $prev in
+    execute_dlfiles)
+      execute_dlfiles="$execute_dlfiles $arg"
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case $arg in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+    exit 0
+    ;;
+
+  --config)
+    sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
+    exit 0
+    ;;
+
+  --debug)
+    echo "$progname: enabling shell trace mode"
+    set -x
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+    exit 0
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
+  --quiet | --silent)
+    show=:
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+fi
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    case $nonopt in
+    *cc | *++ | gcc* | *-gcc*)
+      mode=link
+      for arg
+      do
+       case $arg in
+       -c)
+          mode=compile
+          break
+          ;;
+       esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+       if test -n "$nonopt"; then
+         $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+       else
+         $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+       fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case $mode in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    prev=
+    lastarg=
+    srcfile="$nonopt"
+    suppress_output=
+
+    user_target=no
+    for arg
+    do
+      case $prev in
+      "") ;;
+      xcompiler)
+       # Aesthetically quote the previous argument.
+       prev=
+       lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+
+       case $arg in
+       # Double-quote args containing other shell metacharacters.
+       # Many Bourne shells cannot handle close brackets correctly
+       # in scan sets, so we specify it separately.
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+
+       # Add the previous argument to base_compile.
+       if test -z "$base_compile"; then
+         base_compile="$lastarg"
+       else
+         base_compile="$base_compile $lastarg"
+       fi
+       continue
+       ;;
+      esac
+
+      # Accept any command-line options.
+      case $arg in
+      -o)
+       if test "$user_target" != "no"; then
+         $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+         exit 1
+       fi
+       user_target=next
+       ;;
+
+      -static)
+       build_old_libs=yes
+       continue
+       ;;
+
+      -prefer-pic)
+       pic_mode=yes
+       continue
+       ;;
+
+      -prefer-non-pic)
+       pic_mode=no
+       continue
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Wc,*)
+       args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+       lastarg=
+       save_ifs="$IFS"; IFS=','
+       for arg in $args; do
+         IFS="$save_ifs"
+
+         # Double-quote args containing other shell metacharacters.
+         # Many Bourne shells cannot handle close brackets correctly
+         # in scan sets, so we specify it separately.
+         case $arg in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           arg="\"$arg\""
+           ;;
+         esac
+         lastarg="$lastarg $arg"
+       done
+       IFS="$save_ifs"
+       lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+       # Add the arguments to base_compile.
+       if test -z "$base_compile"; then
+         base_compile="$lastarg"
+       else
+         base_compile="$base_compile $lastarg"
+       fi
+       continue
+       ;;
+      esac
+
+      case $user_target in
+      next)
+       # The next one is the -o target name
+       user_target=yes
+       continue
+       ;;
+      yes)
+       # We got the output file
+       user_target=set
+       libobj="$arg"
+       continue
+       ;;
+      esac
+
+      # Accept the current argument as the source file.
+      lastarg="$srcfile"
+      srcfile="$arg"
+
+      # Aesthetically quote the previous argument.
+
+      # Backslashify any backslashes, double quotes, and dollar signs.
+      # These are the only characters that are still specially
+      # interpreted inside of double-quoted scrings.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      case $lastarg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       lastarg="\"$lastarg\""
+       ;;
+      esac
+
+      # Add the previous argument to base_compile.
+      if test -z "$base_compile"; then
+       base_compile="$lastarg"
+      else
+       base_compile="$base_compile $lastarg"
+      fi
+    done
+
+    case $user_target in
+    set)
+      ;;
+    no)
+      # Get the name of the library object.
+      libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    *)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit 1
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSfmso]'
+    case $libobj in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.f90) xform=f90 ;;
+    *.for) xform=for ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case $libobj in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit 1
+      ;;
+    esac
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $libobj"
+    else
+      removelist="$libobj"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit 1" 1 2 15
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit 1" 1 2 15
+    else
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $run ln "$0" "$lockfile" 2>/dev/null; do
+       $show "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+      echo $srcfile > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+       # All platforms use -DPIC, to notify preprocessed assembler code.
+       command="$base_compile $srcfile $pic_flag -DPIC"
+      else
+       # Don't build PIC code
+       command="$base_compile $srcfile"
+      fi
+      if test "$build_old_libs" = yes; then
+       lo_libobj="$libobj"
+       dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$dir" = "X$libobj"; then
+         dir="$objdir"
+       else
+         dir="$dir/$objdir"
+       fi
+       libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+       if test -d "$dir"; then
+         $show "$rm $libobj"
+         $run $rm $libobj
+       else
+         $show "$mkdir $dir"
+         $run $mkdir $dir
+         status=$?
+         if test $status -ne 0 && test ! -d $dir; then
+           exit $status
+         fi
+       fi
+      fi
+      if test "$compiler_o_lo" = yes; then
+       output_obj="$libobj"
+       command="$command -o $output_obj"
+      elif test "$compiler_c_o" = yes; then
+       output_obj="$obj"
+       command="$command -o $output_obj"
+      fi
+
+      $run $rm "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       test -n "$output_obj" && $run $rm $removelist
+       exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+       echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test x"$output_obj" != x"$libobj"; then
+       $show "$mv $output_obj $libobj"
+       if $run $mv $output_obj $libobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # If we have no pic_flag, then copy the object into place and finish.
+      if (test -z "$pic_flag" || test "$pic_mode" != default) &&
+        test "$build_old_libs" = yes; then
+       # Rename the .lo from within objdir to obj
+       if test -f $obj; then
+         $show $rm $obj
+         $run $rm $obj
+       fi
+
+       $show "$mv $libobj $obj"
+       if $run $mv $libobj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+
+       xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$xdir" = "X$obj"; then
+         xdir="."
+       else
+         xdir="$xdir"
+       fi
+       baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
+       libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+       # Now arrange that obj and lo_libobj become the same file
+       $show "(cd $xdir && $LN_S $baseobj $libobj)"
+       if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+         # Unlock the critical section if it was locked
+         if test "$need_locks" != no; then
+           $run $rm "$lockfile"
+         fi
+         exit 0
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Allow error messages only from the first compilation.
+      suppress_output=' >/dev/null 2>&1'
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+       # Don't build PIC code
+       command="$base_compile $srcfile"
+      else
+       # All platforms use -DPIC, to notify preprocessed assembler code.
+       command="$base_compile $srcfile $pic_flag -DPIC"
+      fi
+      if test "$compiler_c_o" = yes; then
+       command="$command -o $obj"
+       output_obj="$obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       $run $rm $removelist
+       exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+       echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+
+      # Just move the object if needed
+      if test x"$output_obj" != x"$obj"; then
+       $show "$mv $output_obj $obj"
+       if $run $mv $output_obj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Create an invalid libtool object if no PIC, so that we do not
+      # accidentally link it into a program.
+      if test "$build_libtool_libs" != yes; then
+       $show "echo timestamp > $libobj"
+       $run eval "echo timestamp > \$libobj" || exit $?
+      else
+       # Move the .lo from within objdir
+       $show "$mv $libobj $lo_libobj"
+       if $run $mv $libobj $lo_libobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+    fi
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $run $rm "$lockfile"
+    fi
+
+    exit 0
+    ;;
+
+  # libtool link mode
+  link | relink)
+    modename="$modename: link"
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invokation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args="$nonopt"
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -all-static | -static)
+       if test "X$arg" = "X-all-static"; then
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+       else
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+       fi
+       build_libtool_libs=no
+       build_old_libs=yes
+       prefer_static_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test $# -gt 0; do
+      arg="$1"
+      shift
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+       ;;
+      *) qarg=$arg ;;
+      esac
+      libtool_args="$libtool_args $qarg"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case $prev in
+       output)
+         compile_command="$compile_command @OUTPUT@"
+         finalize_command="$finalize_command @OUTPUT@"
+         ;;
+       esac
+
+       case $prev in
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           compile_command="$compile_command @SYMFILE@"
+           finalize_command="$finalize_command @SYMFILE@"
+           preload=yes
+         fi
+         case $arg in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             dlfiles="$dlfiles $arg"
+           else
+             dlprefiles="$dlprefiles $arg"
+           fi
+           prev=
+           continue
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         if test ! -f "$arg"; then
+           $echo "$modename: symbol file \`$arg' does not exist"
+           exit 1
+         fi
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case $arg in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           $echo "$modename: only absolute run-paths are allowed" 1>&2
+           exit 1
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) rpath="$rpath $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) xrpath="$xrpath $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       xcompiler)
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         compile_command="$compile_command $qarg"
+         finalize_command="$finalize_command $qarg"
+         continue
+         ;;
+       xlinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $wl$qarg"
+         prev=
+         compile_command="$compile_command $wl$qarg"
+         finalize_command="$finalize_command $wl$qarg"
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi # test -n $prev
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         compile_command="$compile_command $link_static_flag"
+         finalize_command="$finalize_command $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+       continue
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         $echo "$modename: more than one -exported-symbols argument is not allowed"
+         exit 1
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+       case $with_gcc/$host in
+       no/*-*-irix* | no/*-*-nonstopux*)
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         ;;
+       esac
+       continue
+       ;;
+
+      -L*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         if test -z "$absdir"; then
+           $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+           exit 1
+         fi
+         dir="$absdir"
+         ;;
+       esac
+       case "$deplibs " in
+       *" -L$dir "*) ;;
+       *)
+         deplibs="$deplibs -L$dir"
+         lib_search_path="$lib_search_path $dir"
+         ;;
+       esac
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         case :$dllsearchpath: in
+         *":$dir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$dir";;
+         esac
+         ;;
+       esac
+       continue
+       ;;
+
+      -l*)
+       if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+         case $host in
+         *-*-cygwin* | *-*-pw32* | *-*-beos*)
+           # These systems don't actually have a C or math library (as such)
+           continue
+           ;;
+         *-*-mingw* | *-*-os2*)
+           # These systems don't actually have a C library (as such)
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-openbsd* | *-*-freebsd*)
+           # Do not include libc due to us having libc/libc_r.
+           test "X$arg" = "X-lc" && continue
+           ;;
+         esac
+        elif test "X$arg" = "X-lc_r"; then
+         case $host in
+        *-*-openbsd* | *-*-freebsd*)
+           # Do not include libc_r directly, use -pthread flag.
+           continue
+           ;;
+         esac
+       fi
+       deplibs="$deplibs $arg"
+       continue
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      -no-fast-install)
+       fast_install=no
+       continue
+       ;;
+
+      -no-install)
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         # The PATH hackery in wrapper scripts is required on Windows
+         # in order for the loader to find any dlls it needs.
+         $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+         $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+         fast_install=no
+         ;;
+       *) no_install=yes ;;
+       esac
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         $echo "$modename: only absolute run-paths are allowed" 1>&2
+         exit 1
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) xrpath="$xrpath $dir" ;;
+       esac
+       continue
+       ;;
+
+      -static)
+       # The effects of -static are defined in a previous loop.
+       # We used to do the same as -all-static on platforms that
+       # didn't have a PIC flag, but the assumption that the effects
+       # would be equivalent was wrong.  It would break on at least
+       # Digital Unix and AIX.
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+
+      -Wc,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Wl,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $wl$flag"
+         linker_flags="$linker_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Xlinker)
+       prev=xlinker
+       continue
+       ;;
+
+      # Some other compiler flag.
+      -* | +*)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+
+      *.lo | *.$objext)
+       # A library or standard object.
+       if test "$prev" = dlfiles; then
+         # This file was specified with -dlopen.
+         if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+           dlfiles="$dlfiles $arg"
+           prev=
+           continue
+         else
+           # If libtool objects are unsupported, then we need to preload.
+           prev=dlprefiles
+         fi
+       fi
+
+       if test "$prev" = dlprefiles; then
+         # Preload the old-style object.
+         dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+         prev=
+       else
+         case $arg in
+         *.lo) libobjs="$libobjs $arg" ;;
+         *) objs="$objs $arg" ;;
+         esac
+       fi
+       ;;
+
+      *.$libext)
+       # An archive.
+       deplibs="$deplibs $arg"
+       old_deplibs="$old_deplibs $arg"
+       continue
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       if test "$prev" = dlfiles; then
+         # This library was specified with -dlopen.
+         dlfiles="$dlfiles $arg"
+         prev=
+       elif test "$prev" = dlprefiles; then
+         # The library was specified with -dlpreopen.
+         dlprefiles="$dlprefiles $arg"
+         prev=
+       else
+         deplibs="$deplibs $arg"
+       fi
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+      fi
+    done # argument parsing loop
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$output_objdir" = "X$output"; then
+      output_objdir="$objdir"
+    else
+      output_objdir="$output_objdir/$objdir"
+    fi
+    # Create the object directory.
+    if test ! -d $output_objdir; then
+      $show "$mkdir $output_objdir"
+      $run $mkdir $output_objdir
+      status=$?
+      if test $status -ne 0 && test ! -d $output_objdir; then
+       exit $status
+      fi
+    fi
+
+    # Determine the type of output
+    case $output in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if test "X$duplicate_deps" = "Xyes" ; then
+       case "$libs " in
+       *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+       esac
+      fi
+      libs="$libs $deplib"
+    done
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+    case $linkmode in
+    lib)
+       passes="conv link"
+       for file in $dlfiles $dlprefiles; do
+         case $file in
+         *.la) ;;
+         *)
+           $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+           exit 1
+           ;;
+         esac
+       done
+       ;;
+    prog)
+       compile_deplibs=
+       finalize_deplibs=
+       alldeplibs=no
+       newdlfiles=
+       newdlprefiles=
+       passes="conv scan dlopen dlpreopen link"
+       ;;
+    *)  passes="conv"
+       ;;
+    esac
+    for pass in $passes; do
+      if test $linkmode = prog; then
+       # Determine which files to process
+       case $pass in
+       dlopen)
+         libs="$dlfiles"
+         save_deplibs="$deplibs" # Collect dlpreopened libraries
+         deplibs=
+         ;;
+       dlpreopen) libs="$dlprefiles" ;;
+       link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+       esac
+      fi
+      for deplib in $libs; do
+       lib=
+       found=no
+       case $deplib in
+       -l*)
+         if test $linkmode = oldlib && test $linkmode = obj; then
+           $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
+           continue
+         fi
+         if test $pass = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+         for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+           # Search the libtool library
+           lib="$searchdir/lib${name}.la"
+           if test -f "$lib"; then
+             found=yes
+             break
+           fi
+         done
+         if test "$found" != yes; then
+           # deplib doesn't seem to be a libtool library
+           if test "$linkmode,$pass" = "prog,link"; then
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             deplibs="$deplib $deplibs"
+             test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
+           fi
+           continue
+         fi
+         ;; # -l
+       -L*)
+         case $linkmode in
+         lib)
+           deplibs="$deplib $deplibs"
+           test $pass = conv && continue
+           newdependency_libs="$deplib $newdependency_libs"
+           newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           ;;
+         prog)
+           if test $pass = conv; then
+             deplibs="$deplib $deplibs"
+             continue
+           fi
+           if test $pass = scan; then
+             deplibs="$deplib $deplibs"
+             newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           ;;
+         *)
+           $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2
+           ;;
+         esac # linkmode
+         continue
+         ;; # -L
+       -R*)
+         if test $pass = link; then
+           dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+           # Make sure the xrpath contains only unique directories.
+           case "$xrpath " in
+           *" $dir "*) ;;
+           *) xrpath="$xrpath $dir" ;;
+           esac
+         fi
+         deplibs="$deplib $deplibs"
+         continue
+         ;;
+       *.la) lib="$deplib" ;;
+       *.$libext)
+         if test $pass = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         case $linkmode in
+         lib)
+           if test "$deplibs_check_method" != pass_all; then
+             echo
+             echo "*** Warning: Trying to link with static lib archive $deplib."
+             echo "*** I have the capability to make that library automatically link in when"
+             echo "*** you link to this library.  But I can only do this if you have a"
+             echo "*** shared version of the library, which you do not appear to have"
+             echo "*** because the file extensions .$libext of this argument makes me believe"
+             echo "*** that it is just a static archive that I should not used here."
+           else
+             echo
+             echo "*** Warning: Linking the shared library $output against the"
+             echo "*** static library $deplib is not portable!"
+             deplibs="$deplib $deplibs"
+           fi
+           continue
+           ;;
+         prog)
+           if test $pass != link; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           continue
+           ;;
+         esac # linkmode
+         ;; # *.$libext
+       *.lo | *.$objext)
+         if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+           # If there is no dlopen support or we're linking statically,
+           # we need to preload.
+           newdlprefiles="$newdlprefiles $deplib"
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           newdlfiles="$newdlfiles $deplib"
+         fi
+         continue
+         ;;
+       %DEPLIBS%)
+         alldeplibs=yes
+         continue
+         ;;
+       esac # case $deplib
+       if test $found = yes || test -f "$lib"; then :
+       else
+         $echo "$modename: cannot find the library \`$lib'" 1>&2
+         exit 1
+       fi
+
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         exit 1
+       fi
+
+       ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$ladir" = "X$lib" && ladir="."
+
+       dlname=
+       dlopen=
+       dlpreopen=
+       libdir=
+       library_names=
+       old_library=
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variable installed.
+       installed=yes
+
+       # Read the .la file
+       case $lib in
+       */* | *\\*) . $lib ;;
+       *) . ./$lib ;;
+       esac
+
+       if test "$linkmode,$pass" = "lib,link" ||
+          test "$linkmode,$pass" = "prog,scan" ||
+          { test $linkmode = oldlib && test $linkmode = obj; }; then
+          # Add dl[pre]opened files of deplib
+         test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+         test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+       fi
+
+       if test $pass = conv; then
+         # Only check for convenience libraries
+         deplibs="$lib $deplibs"
+         if test -z "$libdir"; then
+           if test -z "$old_library"; then
+             $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+             exit 1
+           fi
+           # It is a libtool convenience library, so add in its objects.
+           convenience="$convenience $ladir/$objdir/$old_library"
+           old_convenience="$old_convenience $ladir/$objdir/$old_library"
+           tmp_libs=
+           for deplib in $dependency_libs; do
+             deplibs="$deplib $deplibs"
+              if test "X$duplicate_deps" = "Xyes" ; then
+               case "$tmp_libs " in
+               *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+               esac
+              fi
+             tmp_libs="$tmp_libs $deplib"
+           done
+         elif test $linkmode != prog && test $linkmode != lib; then
+           $echo "$modename: \`$lib' is not a convenience library" 1>&2
+           exit 1
+         fi
+         continue
+       fi # $pass = conv
+
+       # Get the name of the library we link against.
+       linklib=
+       for l in $old_library $library_names; do
+         linklib="$l"
+       done
+       if test -z "$linklib"; then
+         $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+         exit 1
+       fi
+
+       # This library was specified with -dlopen.
+       if test $pass = dlopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+           exit 1
+         fi
+         if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking
+           # statically, we need to preload.
+           dlprefiles="$dlprefiles $lib"
+         else
+           newdlfiles="$newdlfiles $lib"
+         fi
+         continue
+       fi # $pass = dlopen
+
+       # We need an absolute path.
+       case $ladir in
+       [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+       *)
+         abs_ladir=`cd "$ladir" && pwd`
+         if test -z "$abs_ladir"; then
+           $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+           $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+           abs_ladir="$ladir"
+         fi
+         ;;
+       esac
+       laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+       # Find the relevant object directory and library name.
+       if test "X$installed" = Xyes; then
+         if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           $echo "$modename: warning: library \`$lib' was moved." 1>&2
+           dir="$ladir"
+           absdir="$abs_ladir"
+           libdir="$abs_ladir"
+         else
+           dir="$libdir"
+           absdir="$libdir"
+         fi
+       else
+         dir="$ladir/$objdir"
+         absdir="$abs_ladir/$objdir"
+         # Remove this search path later
+         notinst_path="$notinst_path $abs_ladir"
+       fi # $installed = yes
+       name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+       # This library was specified with -dlpreopen.
+       if test $pass = dlpreopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+           exit 1
+         fi
+         # Prefer using a static library (so that no silly _DYNAMIC symbols
+         # are required to link).
+         if test -n "$old_library"; then
+           newdlprefiles="$newdlprefiles $dir/$old_library"
+         # Otherwise, use the dlname, so that lt_dlopen finds it.
+         elif test -n "$dlname"; then
+           newdlprefiles="$newdlprefiles $dir/$dlname"
+         else
+           newdlprefiles="$newdlprefiles $dir/$linklib"
+         fi
+       fi # $pass = dlpreopen
+
+       if test -z "$libdir"; then
+         # Link the convenience library
+         if test $linkmode = lib; then
+           deplibs="$dir/$old_library $deplibs"
+         elif test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$dir/$old_library $compile_deplibs"
+           finalize_deplibs="$dir/$old_library $finalize_deplibs"
+         else
+           deplibs="$lib $deplibs"
+         fi
+         continue
+       fi
+
+       if test $linkmode = prog && test $pass != link; then
+         newlib_search_path="$newlib_search_path $ladir"
+         deplibs="$lib $deplibs"
+
+         linkalldeplibs=no
+         if test "$link_all_deplibs" != no || test -z "$library_names" ||
+            test "$build_libtool_libs" = no; then
+           linkalldeplibs=yes
+         fi
+
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           case $deplib in
+           -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+           esac
+           # Need to link against all dependency_libs?
+           if test $linkalldeplibs = yes; then
+             deplibs="$deplib $deplibs"
+           else
+             # Need to hardcode shared library paths
+             # or/and link against static libraries
+             newdependency_libs="$deplib $newdependency_libs"
+           fi
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done # for deplib
+         continue
+       fi # $linkmode = prog...
+
+       link_static=no # Whether the deplib will be linked statically
+       if test -n "$library_names" &&
+          { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+         # Link against this shared library
+
+         if test "$linkmode,$pass" = "prog,link" ||
+          { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+           if test $linkmode = prog; then
+             # We need to hardcode the library path
+             if test -n "$shlibpath_var"; then
+               # Make sure the rpath contains only unique directories.
+               case "$temp_rpath " in
+               *" $dir "*) ;;
+               *" $absdir "*) ;;
+               *) temp_rpath="$temp_rpath $dir" ;;
+               esac
+             fi
+           fi
+         fi # $linkmode,$pass = prog,link...
+
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+
+         if test "$installed" = no; then
+           notinst_deplibs="$notinst_deplibs $lib"
+           need_relink=yes
+         fi
+
+         if test -n "$old_archive_from_expsyms_cmds"; then
+           # figure out the soname
+           set dummy $library_names
+           realname="$2"
+           shift; shift
+           libname=`eval \\$echo \"$libname_spec\"`
+           # use dlname if we got it. it's perfectly good, no?
+           if test -n "$dlname"; then
+             soname="$dlname"
+           elif test -n "$soname_spec"; then
+             # bleh windows
+             case $host in
+             *cygwin*)
+               major=`expr $current - $age`
+               versuffix="-$major"
+               ;;
+             esac
+             eval soname=\"$soname_spec\"
+           else
+             soname="$realname"
+           fi
+
+           # Make a new name for the extract_expsyms_cmds to use
+           soroot="$soname"
+           soname=`echo $soroot | sed -e 's/^.*\///'`
+           newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a"
+
+           # If the library has no export list, then create one now
+           if test -f "$output_objdir/$soname-def"; then :
+           else
+             $show "extracting exported symbol list from \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             eval cmds=\"$extract_expsyms_cmds\"
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+
+           # Create $newlib
+           if test -f "$output_objdir/$newlib"; then :; else
+             $show "generating import library for \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             eval cmds=\"$old_archive_from_expsyms_cmds\"
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+           # make sure the library variables are pointing to the new library
+           dir=$output_objdir
+           linklib=$newlib
+         fi # test -n $old_archive_from_expsyms_cmds
+
+         if test $linkmode = prog || test "$mode" != relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           lib_linked=yes
+           case $hardcode_action in
+           immediate | unsupported)
+             if test "$hardcode_direct" = no; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = no; then
+               case $host in
+               *-*-sunos*) add_shlibpath="$dir" ;;
+               esac
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = no; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           relink)
+             if test "$hardcode_direct" = yes; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = yes; then
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = yes; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           *) lib_linked=no ;;
+           esac
+
+           if test "$lib_linked" != yes; then
+             $echo "$modename: configuration error: unsupported hardcode properties"
+             exit 1
+           fi
+
+           if test -n "$add_shlibpath"; then
+             case :$compile_shlibpath: in
+             *":$add_shlibpath:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+             esac
+           fi
+           if test $linkmode = prog; then
+             test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+             test -n "$add" && compile_deplibs="$add $compile_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+             if test "$hardcode_direct" != yes && \
+                test "$hardcode_minus_L" != yes && \
+                test "$hardcode_shlibpath_var" = yes; then
+               case :$finalize_shlibpath: in
+               *":$libdir:"*) ;;
+               *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+               esac
+             fi
+           fi
+         fi
+
+         if test $linkmode = prog || test "$mode" = relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           # Finalize command for both is simple: just hardcode it.
+           if test "$hardcode_direct" = yes; then
+             add="$libdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             add_dir="-L$libdir"
+             add="-l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case :$finalize_shlibpath: in
+             *":$libdir:"*) ;;
+             *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+             esac
+             add="-l$name"
+           else
+             # We cannot seem to hardcode it, guess we'll fake it.
+             add_dir="-L$libdir"
+             add="-l$name"
+           fi
+
+           if test $linkmode = prog; then
+             test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+             test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+           fi
+         fi
+       elif test $linkmode = prog; then
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+
+         # Try to link the static library
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_deplibs="$dir/$linklib $compile_deplibs"
+           finalize_deplibs="$dir/$linklib $finalize_deplibs"
+         else
+           compile_deplibs="-l$name -L$dir $compile_deplibs"
+           finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+         fi
+       elif test "$build_libtool_libs" = yes; then
+         # Not a shared library
+         if test "$deplibs_check_method" != pass_all; then
+           # We're trying link a shared library against a static one
+           # but the system doesn't support it.
+
+           # Just print a warning and add the library to dependency_libs so
+           # that the program can be linked against the static library.
+           echo
+           echo "*** Warning: This system can not link to static lib archive $lib."
+           echo "*** I have the capability to make that library automatically link in when"
+           echo "*** you link to this library.  But I can only do this if you have a"
+           echo "*** shared version of the library, which you do not appear to have."
+           if test "$module" = yes; then
+             echo "*** But as you try to build a module library, libtool will still create "
+             echo "*** a static module, that should work as long as the dlopening application"
+             echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+             if test -z "$global_symbol_pipe"; then
+               echo
+               echo "*** However, this would only work if libtool was able to extract symbol"
+               echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+               echo "*** not find such a program.  So, this module is probably useless."
+               echo "*** \`nm' from GNU binutils and a full rebuild may help."
+             fi
+             if test "$build_old_libs" = no; then
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         else
+           convenience="$convenience $dir/$old_library"
+           old_convenience="$old_convenience $dir/$old_library"
+           deplibs="$dir/$old_library $deplibs"
+           link_static=yes
+         fi
+       fi # link shared/static library?
+
+       if test $linkmode = lib; then
+         if test -n "$dependency_libs" &&
+            { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
+              test $link_static = yes; }; then
+           # Extract -R from dependency_libs
+           temp_deplibs=
+           for libdir in $dependency_libs; do
+             case $libdir in
+             -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+                  case " $xrpath " in
+                  *" $temp_xrpath "*) ;;
+                  *) xrpath="$xrpath $temp_xrpath";;
+                  esac;;
+             *) temp_deplibs="$temp_deplibs $libdir";;
+             esac
+           done
+           dependency_libs="$temp_deplibs"
+         fi
+
+         newlib_search_path="$newlib_search_path $absdir"
+         # Link against this library
+         test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+         # ... and its dependency_libs
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           newdependency_libs="$deplib $newdependency_libs"
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done
+
+         if test $link_all_deplibs != no; then
+           # Add the search paths of all dependency libraries
+           for deplib in $dependency_libs; do
+             case $deplib in
+             -L*) path="$deplib" ;;
+             *.la)
+               dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+               test "X$dir" = "X$deplib" && dir="."
+               # We need an absolute path.
+               case $dir in
+               [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+               *)
+                 absdir=`cd "$dir" && pwd`
+                 if test -z "$absdir"; then
+                   $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+                   absdir="$dir"
+                 fi
+                 ;;
+               esac
+               if grep "^installed=no" $deplib > /dev/null; then
+                 path="-L$absdir/$objdir"
+               else
+                 eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+                 if test -z "$libdir"; then
+                   $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                   exit 1
+                 fi
+                 if test "$absdir" != "$libdir"; then
+                   $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+                 fi
+                 path="-L$absdir"
+               fi
+               ;;
+             *) continue ;;
+             esac
+             case " $deplibs " in
+             *" $path "*) ;;
+             *) deplibs="$deplibs $path" ;;
+             esac
+           done
+         fi # link_all_deplibs != no
+       fi # linkmode = lib
+      done # for deplib in $libs
+      if test $pass = dlpreopen; then
+       # Link the dlpreopened libraries before other libraries
+       for deplib in $save_deplibs; do
+         deplibs="$deplib $deplibs"
+       done
+      fi
+      if test $pass != dlopen; then
+       test $pass != scan && dependency_libs="$newdependency_libs"
+       if test $pass != conv; then
+         # Make sure lib_search_path contains only unique directories.
+         lib_search_path=
+         for dir in $newlib_search_path; do
+           case "$lib_search_path " in
+           *" $dir "*) ;;
+           *) lib_search_path="$lib_search_path $dir" ;;
+           esac
+         done
+         newlib_search_path=
+       fi
+
+       if test "$linkmode,$pass" != "prog,link"; then
+         vars="deplibs"
+       else
+         vars="compile_deplibs finalize_deplibs"
+       fi
+       for var in $vars dependency_libs; do
+         # Add libraries to $var in reverse order
+         eval tmp_libs=\"\$$var\"
+         new_libs=
+         for deplib in $tmp_libs; do
+           case $deplib in
+           -L*) new_libs="$deplib $new_libs" ;;
+           *)
+             case " $specialdeplibs " in
+             *" $deplib "*) new_libs="$deplib $new_libs" ;;
+             *)
+               case " $new_libs " in
+               *" $deplib "*) ;;
+               *) new_libs="$deplib $new_libs" ;;
+               esac
+               ;;
+             esac
+             ;;
+           esac
+         done
+         tmp_libs=
+         for deplib in $new_libs; do
+           case $deplib in
+           -L*)
+             case " $tmp_libs " in
+             *" $deplib "*) ;;
+             *) tmp_libs="$tmp_libs $deplib" ;;
+             esac
+             ;;
+           *) tmp_libs="$tmp_libs $deplib" ;;
+           esac
+         done
+         eval $var=\"$tmp_libs\"
+       done # for var
+      fi
+      if test "$pass" = "conv" &&
+       { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then
+       libs="$deplibs" # reset libs
+       deplibs=
+      fi
+    done # for pass
+    if test $linkmode = prog; then
+      dlfiles="$newdlfiles"
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+       $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+       name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       if test "$module" = no; then
+         $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+         eval libname=\"$libname_spec\"
+       else
+         libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+       fi
+       ;;
+      esac
+
+      if test -n "$objs"; then
+       if test "$deplibs_check_method" != pass_all; then
+         $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+         exit 1
+       else
+         echo
+         echo "*** Warning: Linking the shared library $output against the non-libtool"
+         echo "*** objects $objs is not portable!"
+         libobjs="$libobjs $objs"
+       fi
+      fi
+
+      if test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test $# -gt 2; then
+       $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         libext=al
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+
+       if test -n "$vinfo"; then
+         $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+       fi
+
+       if test -n "$release"; then
+         $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+       fi
+      else
+
+       # Parse the version information argument.
+       save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       IFS="$save_ifs"
+
+       if test -n "$8"; then
+         $echo "$modename: too many parameters to \`-version-info'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       current="$2"
+       revision="$3"
+       age="$4"
+
+       # Check that each of the things are valid numbers.
+       case $current in
+       0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       case $revision in
+       0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       case $age in
+       0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       if test $age -gt $current; then
+         $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case $version_type in
+       none) ;;
+
+       darwin)
+         # Like Linux, but with the current version available in
+         # verstring for coding it into the library header
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         # Darwin ld doesn't like 0 for these options...
+         minor_current=`expr $current + 1`
+         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current";
+         ;;
+
+       irix | nonstopux)
+         case $version_type in
+           nonstopux) verstring_prefix=nonstopux ;;
+           *)         verstring_prefix=sgi ;;
+         esac
+         verstring="$verstring_prefix$major.$revision"
+
+         major=`expr $current - $age + 1`
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test $loop != 0; do
+           iface=`expr $revision - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring_prefix$major.$iface:$verstring"
+         done
+
+         # Before this point, $major must not contain `.'.
+         major=.$major
+         versuffix="$major.$revision"
+         ;;
+
+       linux)
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         major=`expr $current - $age`
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test $loop != 0; do
+           iface=`expr $current - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         verstring="$verstring:${current}.0"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       windows)
+         # Use '-' rather than '.', since we only want one
+         # extension on DOS 8.3 filesystems.
+         major=`expr $current - $age`
+         versuffix="-$major"
+         ;;
+
+       *)
+         $echo "$modename: unknown library version type \`$version_type'" 1>&2
+         echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+         exit 1
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         verstring="0.0"
+         case $version_type in
+         darwin)
+           # we can't check for "0.0" in archive_cmds due to quoting
+           # problems, so we reset it completely
+           verstring=""
+           ;;
+         *)
+           verstring="0.0"
+           ;;
+         esac
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+      fi
+
+      if test "$mode" != relink; then
+       # Remove our outputs.
+       $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+       $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      for path in $notinst_path; do
+       lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'`
+       deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'`
+       dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'`
+      done
+
+      if test -n "$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       temp_xrpath=
+       for libdir in $xrpath; do
+         temp_xrpath="$temp_xrpath -R$libdir"
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+       if test $hardcode_into_libs != yes || test $build_old_libs = yes; then
+         dependency_libs="$temp_xrpath $dependency_libs"
+       fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+       case " $dlprefiles $dlfiles " in
+       *" $lib "*) ;;
+       *) dlfiles="$dlfiles $lib" ;;
+       esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+       case "$dlprefiles " in
+       *" $lib "*) ;;
+       *) dlprefiles="$dlprefiles $lib" ;;
+       esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+       if test -n "$rpath"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+           # these systems don't actually have a c library (as such)!
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C library is in the System framework
+           deplibs="$deplibs -framework System"
+           ;;
+         *-*-netbsd*)
+           # Don't link with libc until the a.out ld.so is fixed.
+           ;;
+         *-*-openbsd* | *-*-freebsd*)
+           # Do not include libc due to us having libc/libc_r.
+           ;;
+         *)
+           # Add libc to deplibs on all other systems if necessary.
+           if test $build_libtool_need_lc = "yes"; then
+             deplibs="$deplibs -lc"
+           fi
+           ;;
+         esac
+       fi
+
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case $deplibs_check_method in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behaviour.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $rm conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $rm conftest
+         $CC -o conftest conftest.c $deplibs
+         if test $? -eq 0 ; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             name="`expr $i : '-l\(.*\)'`"
+             # If $name is empty we are operating on a -L argument.
+             if test -n "$name" && test "$name" != "0"; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               deplib_matches=`eval \\$echo \"$library_names_spec\"`
+               set dummy $deplib_matches
+               deplib_match=$2
+               if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                 newdeplibs="$newdeplibs $i"
+               else
+                 droppeddeps=yes
+                 echo
+                 echo "*** Warning: dynamic linker does not accept needed library $i."
+                 echo "*** I have the capability to make that library automatically link in when"
+                 echo "*** you link to this library.  But I can only do this if you have a"
+                 echo "*** shared version of the library, which I believe you do not have"
+                 echo "*** because a test_compile did reveal that the linker did not use it for"
+                 echo "*** its dynamic dependency list that programs get resolved with at runtime."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         else
+           # Error occured in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             name="`expr $i : '-l\(.*\)'`"
+            # If $name is empty we are operating on a -L argument.
+             if test -n "$name" && test "$name" != "0"; then
+               $rm conftest
+               $CC -o conftest conftest.c $i
+               # Did it work?
+               if test $? -eq 0 ; then
+                 ldd_output=`ldd conftest`
+                 libname=`eval \\$echo \"$libname_spec\"`
+                 deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                 set dummy $deplib_matches
+                 deplib_match=$2
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   echo
+                   echo "*** Warning: dynamic linker does not accept needed library $i."
+                   echo "*** I have the capability to make that library automatically link in when"
+                   echo "*** you link to this library.  But I can only do this if you have a"
+                   echo "*** shared version of the library, which you do not appear to have"
+                   echo "*** because a test_compile did reveal that the linker did not use this one"
+                   echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+                 fi
+               else
+                 droppeddeps=yes
+                 echo
+                 echo "*** Warning!  Library $i is needed by this library but I was not able to"
+                 echo "***  make it link in!  You will probably need to install it or some"
+                 echo "*** library that it depends on before this library will be fully"
+                 echo "*** functional.  Installing it before continuing would be even better."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method
+         file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name="`expr $a_deplib : '-l\(.*\)'`"
+           # If $name is empty we are operating on a -L argument.
+           if test -n "$name" && test "$name" != "0"; then
+             libname=`eval \\$echo \"$libname_spec\"`
+             for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                   potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                   for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null \
+                        | grep " -> " >/dev/null; then
+                       continue
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+                       case $potliblink in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+                        | sed 10q \
+                        | egrep "$file_magic_regex" > /dev/null; then
+                       newdeplibs="$newdeplibs $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                   done
+             done
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               echo
+               echo "*** Warning: linker path does not have real file for library $a_deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have"
+               echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 echo "*** with $libname but no candidates were found. (...for file magic test)"
+               else
+                 echo "*** with $libname and none of the candidates passed a file format test"
+                 echo "*** using a file magic. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       match_pattern*)
+         set dummy $deplibs_check_method
+         match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name="`expr $a_deplib : '-l\(.*\)'`"
+           # If $name is empty we are operating on a -L argument.
+           if test -n "$name" && test "$name" != "0"; then
+             libname=`eval \\$echo \"$libname_spec\"`
+             for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+               potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+               for potent_lib in $potential_libs; do
+                 potlib="$potent_lib" # see symlink-check below in file_magic test
+                 if eval echo \"$potent_lib\" 2>/dev/null \
+                     | sed 10q \
+                     | egrep "$match_pattern_regex" > /dev/null; then
+                   newdeplibs="$newdeplibs $a_deplib"
+                   a_deplib=""
+                   break 2
+                 fi
+               done
+             done
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               echo
+               echo "*** Warning: linker path does not have real file for library $a_deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have"
+               echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+               else
+                 echo "*** with $libname and none of the candidates passed a file format test"
+                 echo "*** using a regex pattern. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+              -e 's/ -[LR][^ ]*//g' -e 's/[    ]//g' |
+            grep . >/dev/null; then
+           echo
+           if test "X$deplibs_check_method" = "Xnone"; then
+             echo "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             echo "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           echo "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+         fi
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       case $host in
+       *-*-rhapsody* | *-*-darwin1.[012])
+         # On Rhapsody replace the C library is the System framework
+         newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+         ;;
+       esac
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           echo
+           echo "*** Warning: libtool could not satisfy all declared inter-library"
+           echo "*** dependencies of module $libname.  Therefore, libtool will create"
+           echo "*** a static module, that should work as long as the dlopening"
+           echo "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             echo
+             echo "*** However, this would only work if libtool was able to extract symbol"
+             echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             echo "*** not find such a program.  So, this module is probably useless."
+             echo "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           echo "*** The inter-library dependencies that have been dropped here will be"
+           echo "*** automatically added whenever a program is linked with this library"
+           echo "*** or is declared to -dlopen it."
+
+           if test $allow_undefined = no; then
+             echo
+             echo "*** Since this library must not contain undefined symbols,"
+             echo "*** because either the platform does not support them or"
+             echo "*** it was explicitly requested with -no-undefined,"
+             echo "*** libtool will only create a static version of it."
+             if test "$build_old_libs" = no; then
+               oldlibs="$output_objdir/$libname.$libext"
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       if test $hardcode_into_libs = yes; then
+         # Hardcode the library paths
+         hardcode_libdirs=
+         dep_rpath=
+         rpath="$finalize_rpath"
+         test "$mode" != relink && rpath="$compile_rpath$rpath"
+         for libdir in $rpath; do
+           if test -n "$hardcode_libdir_flag_spec"; then
+             if test -n "$hardcode_libdir_separator"; then
+               if test -z "$hardcode_libdirs"; then
+                 hardcode_libdirs="$libdir"
+               else
+                 # Just accumulate the unique libdirs.
+                 case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+                 *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+                   ;;
+                 *)
+                   hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+                   ;;
+                 esac
+               fi
+             else
+               eval flag=\"$hardcode_libdir_flag_spec\"
+               dep_rpath="$dep_rpath $flag"
+             fi
+           elif test -n "$runpath_var"; then
+             case "$perm_rpath " in
+             *" $libdir "*) ;;
+             *) perm_rpath="$perm_rpath $libdir" ;;
+             esac
+           fi
+         done
+         # Substitute the hardcoded libdirs into the rpath.
+         if test -n "$hardcode_libdir_separator" &&
+            test -n "$hardcode_libdirs"; then
+           libdir="$hardcode_libdirs"
+           eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+         fi
+         if test -n "$runpath_var" && test -n "$perm_rpath"; then
+           # We should set the runpath_var.
+           rpath=
+           for dir in $perm_rpath; do
+             rpath="$rpath$dir:"
+           done
+           eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+         fi
+         test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+       fi
+
+       shlibpath="$finalize_shlibpath"
+       test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+       if test -n "$shlibpath"; then
+         eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+       fi
+
+       # Get the real and link names of the library.
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       realname="$2"
+       shift; shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+       test -z "$dlname" && dlname=$soname
+
+       lib="$output_objdir/$realname"
+       for link
+       do
+         linknames="$linknames $link"
+       done
+
+       # Ensure that we have .o objects for linkers which dislike .lo
+       # (e.g. aix) in case we are running --disable-static
+       for obj in $libobjs; do
+         xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+         if test "X$xdir" = "X$obj"; then
+           xdir="."
+         else
+           xdir="$xdir"
+         fi
+         baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+         oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+         if test ! -f $xdir/$oldobj; then
+           $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
+           $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
+         fi
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           eval cmds=\"$export_symbols_cmds\"
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             $show "$cmd"
+             $run eval "$cmd" || exit $?
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex"; then
+             $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+             $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+             $run eval '$mv "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+       fi
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         else
+           gentop="$output_objdir/${outputname}x"
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "mkdir $gentop"
+           $run mkdir "$gentop"
+           status=$?
+           if test $status -ne 0 && test ! -d "$gentop"; then
+             exit $status
+           fi
+           generated="$generated $gentop"
+
+           for xlib in $convenience; do
+             # Extract the objects.
+             case $xlib in
+             [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+             *) xabs=`pwd`"/$xlib" ;;
+             esac
+             xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+             xdir="$gentop/$xlib"
+
+             $show "${rm}r $xdir"
+             $run ${rm}r "$xdir"
+             $show "mkdir $xdir"
+             $run mkdir "$xdir"
+             status=$?
+             if test $status -ne 0 && test ! -d "$xdir"; then
+               exit $status
+             fi
+             $show "(cd $xdir && $AR x $xabs)"
+             $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+             libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+           done
+         fi
+       fi
+
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         linker_flags="$linker_flags $flag"
+       fi
+
+       # Make a backup of the uninstalled library when relinking
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+       fi
+
+       # Do each of the archive commands.
+       if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+         eval cmds=\"$archive_expsym_cmds\"
+       else
+         eval cmds=\"$archive_cmds\"
+       fi
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+
+       # Restore the uninstalled library and exit
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+         exit 0
+       fi
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+           $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case $output in
+      *.lo)
+       if test -n "$objs$old_deplibs"; then
+         $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+         exit 1
+       fi
+       libobj="$output"
+       obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec
+      wl=
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+       else
+         gentop="$output_objdir/${obj}x"
+         $show "${rm}r $gentop"
+         $run ${rm}r "$gentop"
+         $show "mkdir $gentop"
+         $run mkdir "$gentop"
+         status=$?
+         if test $status -ne 0 && test ! -d "$gentop"; then
+           exit $status
+         fi
+         generated="$generated $gentop"
+
+         for xlib in $convenience; do
+           # Extract the objects.
+           case $xlib in
+           [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+           *) xabs=`pwd`"/$xlib" ;;
+           esac
+           xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+           xdir="$gentop/$xlib"
+
+           $show "${rm}r $xdir"
+           $run ${rm}r "$xdir"
+           $show "mkdir $xdir"
+           $run mkdir "$xdir"
+           status=$?
+           if test $status -ne 0 && test ! -d "$xdir"; then
+             exit $status
+           fi
+           $show "(cd $xdir && $AR x $xabs)"
+           $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+           reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+         done
+       fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      eval cmds=\"$reload_cmds\"
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       exit 0
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       $show "echo timestamp > $libobj"
+       $run eval "echo timestamp > $libobj" || exit $?
+       exit 0
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       eval cmds=\"$reload_cmds\"
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+      else
+       # Just create a symlink.
+       $show $rm $libobj
+       $run $rm $libobj
+       xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$xdir" = "X$libobj"; then
+         xdir="."
+       else
+         xdir="$xdir"
+       fi
+       baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+       oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+       $show "(cd $xdir && $LN_S $oldobj $baseobj)"
+       $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
+      fi
+
+      if test -n "$gentop"; then
+       $show "${rm}r $gentop"
+       $run ${rm}r $gentop
+      fi
+
+      exit 0
+      ;;
+
+    prog)
+      case $host in
+       *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;;
+      esac
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+       if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+          test "$dlopen_self_static" = unknown; then
+         $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+       fi
+      fi
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+       # On Rhapsody replace the C library is the System framework
+       compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       ;;
+      esac
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) perm_rpath="$perm_rpath $libdir" ;;
+         esac
+       fi
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         case :$dllsearchpath: in
+         *":$libdir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$libdir";;
+         esac
+         ;;
+       esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       if test -n "$NM" && test -n "$global_symbol_pipe"; then
+         dlsyms="${outputname}S.c"
+       else
+         $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+       fi
+      fi
+
+      if test -n "$dlsyms"; then
+       case $dlsyms in
+       "") ;;
+       *.c)
+         # Discover the nlist of each of the dlfiles.
+         nlist="$output_objdir/${outputname}.nm"
+
+         $show "$rm $nlist ${nlist}S ${nlist}T"
+         $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+         # Parse the name list into a source file.
+         $show "creating $output_objdir/$dlsyms"
+
+         test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+         if test "$dlself" = yes; then
+           $show "generating symbol list for \`$output'"
+
+           test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+           # Add our own program objects to the symbol list.
+           progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+           for arg in $progfiles; do
+             $show "extracting global C symbols from \`$arg'"
+             $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+           done
+
+           if test -n "$exclude_expsyms"; then
+             $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           if test -n "$export_symbols_regex"; then
+             $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           # Prepare the list of exported symbols
+           if test -z "$export_symbols"; then
+             export_symbols="$output_objdir/$output.exp"
+             $run $rm $export_symbols
+             $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+           else
+             $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+             $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+             $run eval 'mv "$nlist"T "$nlist"'
+           fi
+         fi
+
+         for arg in $dlprefiles; do
+           $show "extracting global C symbols from \`$arg'"
+           name=`echo "$arg" | sed -e 's%^.*/%%'`
+           $run eval 'echo ": $name " >> "$nlist"'
+           $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -z "$run"; then
+           # Make sure we have at least an empty file.
+           test -f "$nlist" || : > "$nlist"
+
+           if test -n "$exclude_expsyms"; then
+             egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+             $mv "$nlist"T "$nlist"
+           fi
+
+           # Try sorting and uniquifying the output.
+           if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+             :
+           else
+             grep -v "^: " < "$nlist" > "$nlist"S
+           fi
+
+           if test -f "$nlist"S; then
+             eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+           else
+             echo '/* NONE */' >> "$output_objdir/$dlsyms"
+           fi
+
+           $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+           eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+           $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+         fi
+
+         pic_flag_for_symtable=
+         case $host in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+           esac;;
+         *-*-hpux*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+           esac
+         esac
+
+         # Now compile the dynamic symbol file.
+         $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+         $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+         # Clean up the generated files.
+         $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+         $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+         # Transform the symbol file into the correct name.
+         compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+         finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+         ;;
+       *)
+         $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+         exit 1
+         ;;
+       esac
+      else
+       # We keep going just in case the user didn't refer to
+       # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+       # really was required.
+
+       # Nullify the symbol file.
+       compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+       finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+      fi
+
+      if test $need_relink = no || test "$build_libtool_libs" != yes; then
+       # Replace the output file specification.
+       compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       $show "$link_command"
+       $run eval "$link_command"
+       status=$?
+
+       # Delete the generated files.
+       if test -n "$dlsyms"; then
+         $show "$rm $output_objdir/${outputname}S.${objext}"
+         $run $rm "$output_objdir/${outputname}S.${objext}"
+       fi
+
+       exit $status
+      fi
+
+      if test -n "$shlibpath_var"; then
+       # We should set the shlibpath_var
+       rpath=
+       for dir in $temp_rpath; do
+         case $dir in
+         [\\/]* | [A-Za-z]:[\\/]*)
+           # Absolute path.
+           rpath="$rpath$dir:"
+           ;;
+         *)
+           # Relative path: add a thisdir entry.
+           rpath="$rpath\$thisdir/$dir:"
+           ;;
+         esac
+       done
+       temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$no_install" = yes; then
+       # We don't need to create a wrapper script.
+       link_command="$compile_var$compile_command$compile_rpath"
+       # Replace the output file specification.
+       link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       # Delete the old output file.
+       $run $rm $output
+       # Link the executable and exit
+       $show "$link_command"
+       $run eval "$link_command" || exit $?
+       exit 0
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+       $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+       $echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       # Preserve any variables that may affect compiler behavior
+       for var in $variables_saved_for_relink; do
+         if eval test -z \"\${$var+set}\"; then
+           relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+         elif eval var_value=\$$var; test -z "$var_value"; then
+           relink_command="$var=; export $var; $relink_command"
+         else
+           var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+           relink_command="$var=\"$var_value\"; export $var; $relink_command"
+         fi
+       done
+       relink_command="(cd `pwd`; $relink_command)"
+       relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+       case $0 in
+       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+       *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+       esac
+       qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+       qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+       esac
+       # test for cygwin because mv fails w/o .exe extensions
+       case $host in
+         *cygwin*) exeext=.exe ;;
+         *) exeext= ;;
+       esac
+       $rm $output
+       trap "$rm $output; exit 1" 1 2 15
+
+       $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+       $echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         echo >> $output "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+         echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+       $echo \"\$relink_command_output\" >&2
+       $rm \"\$progdir/\$file\"
+       exit 1
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+       else
+         echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       # fixup the dll searchpath if we need to.
+       if test -n "$dllsearchpath"; then
+         $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       $echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+       case $host in
+       # win32 systems need to use the prog path for dll
+       # lookup to work
+       *-*-cygwin* | *-*-pw32*)
+         $echo >> $output "\
+      exec \$progdir/\$program \${1+\"\$@\"}
+"
+         ;;
+
+       # Backslashes separate directories on plain windows
+       *-*-mingw | *-*-os2*)
+         $echo >> $output "\
+      exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+         ;;
+
+       *)
+         $echo >> $output "\
+      # Export the path to the program.
+      PATH=\"\$progdir:\$PATH\"
+      export PATH
+
+      exec \$program \${1+\"\$@\"}
+"
+         ;;
+       esac
+       $echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+       chmod +x $output
+      fi
+      exit 0
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       $show "${rm}r $gentop"
+       $run ${rm}r "$gentop"
+       $show "mkdir $gentop"
+       $run mkdir "$gentop"
+       status=$?
+       if test $status -ne 0 && test ! -d "$gentop"; then
+         exit $status
+       fi
+       generated="$generated $gentop"
+
+       # Add in members from convenience archives.
+       for xlib in $addlibs; do
+         # Extract the objects.
+         case $xlib in
+         [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+         *) xabs=`pwd`"/$xlib" ;;
+         esac
+         xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+         xdir="$gentop/$xlib"
+
+         $show "${rm}r $xdir"
+         $run ${rm}r "$xdir"
+         $show "mkdir $xdir"
+         $run mkdir "$xdir"
+         status=$?
+         if test $status -ne 0 && test ! -d "$xdir"; then
+           exit $status
+         fi
+         $show "(cd $xdir && $AR x $xabs)"
+         $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+         oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+       done
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       eval cmds=\"$old_archive_from_new_cmds\"
+      else
+       # Ensure that we have .o objects in place in case we decided
+       # not to build a shared library, and have fallen back to building
+       # static libs even though --disable-static was passed!
+       for oldobj in $oldobjs; do
+         if test ! -f $oldobj; then
+           xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
+           if test "X$xdir" = "X$oldobj"; then
+             xdir="."
+           else
+             xdir="$xdir"
+           fi
+           baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
+           obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+           $show "(cd $xdir && ${LN_S} $obj $baseobj)"
+           $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+         fi
+       done
+
+       eval cmds=\"$old_archive_cmds\"
+      fi
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+       if eval test -z \"\${$var+set}\"; then
+         relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+       elif eval var_value=\$$var; test -z "$var_value"; then
+         relink_command="$var=; export $var; $relink_command"
+       else
+         var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+         relink_command="$var=\"$var_value\"; export $var; $relink_command"
+       fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)"
+      relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+           # Replace all uninstalled libtool libraries with the installed ones
+           newdependency_libs=
+           for deplib in $dependency_libs; do
+             case $deplib in
+             *.la)
+               name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+               eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+               if test -z "$libdir"; then
+                 $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                 exit 1
+               fi
+               newdependency_libs="$newdependency_libs $libdir/$name"
+               ;;
+             *) newdependency_libs="$newdependency_libs $deplib" ;;
+             esac
+           done
+           dependency_libs="$newdependency_libs"
+           newdlfiles=
+           for lib in $dlfiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit 1
+             fi
+             newdlfiles="$newdlfiles $libdir/$name"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit 1
+             fi
+             newdlprefiles="$newdlprefiles $libdir/$name"
+           done
+           dlprefiles="$newdlprefiles"
+         fi
+         $rm $output
+         # place dlname in correct position for cygwin
+         tdlname=$dlname
+         case $host,$output,$installed,$module,$dlname in
+           *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+         esac
+         $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+         if test "$installed" = no && test $need_relink = yes; then
+           $echo >> $output "\
+relink_command=\"$relink_command\""
+         fi
+       done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+      ;;
+    esac
+    exit 0
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg="$nonopt"
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case $arg in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*)
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+       files="$files $dest"
+       dest="$arg"
+       continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f) prev="-f" ;;
+      -g) prev="-g" ;;
+      -m) prev="-m" ;;
+      -o) prev="-o" ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*) ;;
+
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         prev=
+       else
+         dest="$arg"
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       $echo "$modename: no file or destination specified" 1>&2
+      else
+       $echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test $# -gt 2; then
+       $echo "$modename: \`$dest' is not a directory" 1>&2
+       $echo "$help" 1>&2
+       exit 1
+      fi
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case $file in
+       *.lo) ;;
+       *)
+         $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+       # Do the static libraries later.
+       staticlibs="$staticlibs $file"
+       ;;
+
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       library_names=
+       old_library=
+       relink_command=
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) current_libdirs="$current_libdirs $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) future_libdirs="$future_libdirs $libdir" ;;
+         esac
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+       test "X$dir" = "X$file/" && dir=
+       dir="$dir$objdir"
+
+       if test -n "$relink_command"; then
+         $echo "$modename: warning: relinking \`$file'" 1>&2
+         $show "$relink_command"
+         if $run eval "$relink_command"; then :
+         else
+           $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+           continue
+         fi
+       fi
+
+       # See the names of the shared library.
+       set dummy $library_names
+       if test -n "$2"; then
+         realname="$2"
+         shift
+         shift
+
+         srcname="$realname"
+         test -n "$relink_command" && srcname="$realname"T
+
+         # Install the shared library and build the symlinks.
+         $show "$install_prog $dir/$srcname $destdir/$realname"
+         $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+         if test -n "$stripme" && test -n "$striplib"; then
+           $show "$striplib $destdir/$realname"
+           $run eval "$striplib $destdir/$realname" || exit $?
+         fi
+
+         if test $# -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           for linkname
+           do
+             if test "$linkname" != "$realname"; then
+               $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+               $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+             fi
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         eval cmds=\"$postinstall_cmds\"
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || exit $?
+         done
+         IFS="$save_ifs"
+       fi
+
+       # Install the pseudo-library for information purposes.
+       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+       instname="$dir/$name"i
+       $show "$install_prog $instname $destdir/$name"
+       $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case $destfile in
+       *.lo)
+         staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+         ;;
+       *.$objext)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       if test -n "$destfile"; then
+         $show "$install_prog $file $destfile"
+         $run eval "$install_prog $file $destfile" || exit $?
+       fi
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+         $show "$install_prog $staticobj $staticdest"
+         $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+       fi
+       exit 0
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Do a test to see if this is really a libtool program.
+       case $host in
+       *cygwin*|*mingw*)
+           wrapper=`echo $file | sed -e 's,.exe$,,'`
+           ;;
+       *)
+           wrapper=$file
+           ;;
+       esac
+       if (sed -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+         notinst_deplibs=
+         relink_command=
+
+         # If there is no directory component, then add one.
+         case $file in
+         */* | *\\*) . $wrapper ;;
+         *) . ./$wrapper ;;
+         esac
+
+         # Check the variables that should have been set.
+         if test -z "$notinst_deplibs"; then
+           $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+           exit 1
+         fi
+
+         finalize=yes
+         for lib in $notinst_deplibs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             # If there is no directory component, then add one.
+             case $lib in
+             */* | *\\*) . $lib ;;
+             *) . ./$lib ;;
+             esac
+           fi
+           libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+             finalize=no
+           fi
+         done
+
+         relink_command=
+         # If there is no directory component, then add one.
+         case $file in
+         */* | *\\*) . $wrapper ;;
+         *) . ./$wrapper ;;
+         esac
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           if test "$finalize" = yes && test -z "$run"; then
+             tmpdir="/tmp"
+             test -n "$TMPDIR" && tmpdir="$TMPDIR"
+             tmpdir="$tmpdir/libtool-$$"
+             if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+             else
+               $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+               continue
+             fi
+             file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+             outputname="$tmpdir/$file"
+             # Replace the output file specification.
+             relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+             $show "$relink_command"
+             if $run eval "$relink_command"; then :
+             else
+               $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+               ${rm}r "$tmpdir"
+               continue
+             fi
+             file="$outputname"
+           else
+             $echo "$modename: warning: cannot relink \`$file'" 1>&2
+           fi
+         else
+           # Install the binary that we compiled earlier.
+           file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       # remove .exe since cygwin /usr/bin/install will append another
+       # one anyways
+       case $install_prog,$host in
+       /usr/bin/install*,*cygwin*)
+         case $file:$destfile in
+         *.exe:*.exe)
+           # this is ok
+           ;;
+         *.exe:*)
+           destfile=$destfile.exe
+           ;;
+         *:*.exe)
+           destfile=`echo $destfile | sed -e 's,.exe$,,'`
+           ;;
+         esac
+         ;;
+       esac
+       $show "$install_prog$stripme $file $destfile"
+       $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+       test -n "$outputname" && ${rm}r "$tmpdir"
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      if test -n "$stripme" && test -n "$striplib"; then
+       $show "$old_striplib $oldlib"
+       $run eval "$old_striplib $oldlib" || exit $?
+      fi
+
+      # Do each command in the postinstall commands.
+      eval cmds=\"$old_postinstall_cmds\"
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $0 --finish$current_libdirs'
+    else
+      exit 0
+    fi
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+       libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         eval cmds=\"$finish_cmds\"
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+         done
+         IFS="$save_ifs"
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    test "$show" = ":" && exit 0
+
+    echo "----------------------------------------------------------------------"
+    echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      echo "   $libdir"
+    done
+    echo
+    echo "If you ever happen to want to link against installed libraries"
+    echo "in a given directory, LIBDIR, you must either use libtool, and"
+    echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    echo
+    echo "See any operating system documentation about shared libraries for"
+    echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    echo "----------------------------------------------------------------------"
+    exit 0
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit 1
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+       $echo "$modename: \`$file' is not a file" 1>&2
+       $echo "$help" 1>&2
+       exit 1
+      fi
+
+      dir=
+      case $file in
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+
+       if test -f "$dir/$objdir/$dlname"; then
+         dir="$dir/$objdir"
+       else
+         $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+         exit 1
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+       ;;
+
+      *)
+       $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         # If there is no directory component, then add one.
+         case $file in
+         */* | *\\*) . $file ;;
+         *) . ./$file ;;
+         esac
+
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+       # Export the shlibpath_var.
+       eval "export $shlibpath_var"
+      fi
+
+      # Restore saved enviroment variables
+      if test "${save_LC_ALL+set}" = set; then
+       LC_ALL="$save_LC_ALL"; export LC_ALL
+      fi
+      if test "${save_LANG+set}" = set; then
+       LANG="$save_LANG"; export LANG
+      fi
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+       eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+       $echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit 0
+    fi
+    ;;
+
+  # libtool clean and uninstall mode
+  clean | uninstall)
+    modename="$modename: $mode"
+    rm="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) rm="$rm $arg"; rmforce=yes ;;
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    rmdirs=
+
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$dir" = "X$file"; then
+       dir=.
+       objdir="$objdir"
+      else
+       objdir="$dir/$objdir"
+      fi
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+      test $mode = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test $mode = clean; then
+       case " $rmdirs " in
+         *" $objdir "*) ;;
+         *) rmdirs="$rmdirs $objdir" ;;
+       esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if (test -L "$file") >/dev/null 2>&1 \
+       || (test -h "$file") >/dev/null 2>&1 \
+       || test -f "$file"; then
+       :
+      elif test -d "$file"; then
+       exit_status=1
+       continue
+      elif test "$rmforce" = yes; then
+       continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         . $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           rmfiles="$rmfiles $objdir/$n"
+         done
+         test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+         test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+         if test $mode = uninstall; then
+           if test -n "$library_names"; then
+             # Do each command in the postuninstall commands.
+             eval cmds=\"$postuninstall_cmds\"
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test $? != 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+
+           if test -n "$old_library"; then
+             # Do each command in the old_postuninstall commands.
+             eval cmds=\"$old_postuninstall_cmds\"
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test $? != 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+           # FIXME: should reinstall the best remaining shared library.
+         fi
+       fi
+       ;;
+
+      *.lo)
+       if test "$build_old_libs" = yes; then
+         oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+         rmfiles="$rmfiles $dir/$oldobj"
+       fi
+       ;;
+
+      *)
+       # Do a test to see if this is a libtool program.
+       if test $mode = clean &&
+          (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         relink_command=
+         . $dir/$file
+
+         rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+         if test "$fast_install" = yes && test -n "$relink_command"; then
+           rmfiles="$rmfiles $objdir/lt-$name"
+         fi
+       fi
+       ;;
+      esac
+      $show "$rm $rmfiles"
+      $run $rm $rmfiles || exit_status=1
+    done
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+       $show "rmdir $dir"
+       $run rmdir $dir >/dev/null 2>&1
+      fi
+    done
+
+    exit $exit_status
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit 1
+    ;;
+  esac
+
+  if test -z "$exec_cmd"; then
+    $echo "$modename: invalid operation mode \`$mode'" 1>&2
+    $echo "$generic_help" 1>&2
+    exit 1
+  fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+  eval exec $exec_cmd
+  exit 1
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --version         print version information
+
+MODE must be one of the following:
+
+      clean           remove files from the build directory
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+  exit 0
+  ;;
+
+clean)
+  $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                   try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                   try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                   specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+  ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/pdns/misc.cc b/pdns/misc.cc
new file mode 100644 (file)
index 0000000..5bcb117
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "misc.hh"
+#include <vector>
+#include <sstream>
+#include <errno.h>
+#include <sys/param.h>
+#include <cstring>\r
+\r
+#include <iomanip>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+\r
+#ifndef WIN32\r
+# include <sys/time.h>\r
+# include <time.h>\r
+# include <netinet/in.h>
+# include <unistd.h>
+#endif // WIN32\r
+
+#include "utility.hh"
+
+
+
+int sendData(const char *buffer, int replen, int outsock)
+{
+  u_int16_t nlen=htons(replen);
+  Utility::iovec iov[2];
+  iov[0].iov_base=(char*)&nlen;
+  iov[0].iov_len=2;
+  iov[1].iov_base=(char*)buffer;
+  iov[1].iov_len=replen;
+  int ret=Utility::writev(outsock,iov,2);
+
+  if(ret<0) {
+    return -1;
+  }
+  if(ret!=replen+2) {
+    return -1;
+  }
+  return 0;
+}
+
+
+void parseService(const string &descr, ServiceTuple &st)
+{
+  vector<string>parts;
+  stringtok(parts,descr,":");
+  st.host=parts[0];
+  if(parts.size()>1)
+    st.port=atoi(parts[1].c_str());
+}
+
+int matchNetmask(const char *address, const char *omask)
+{
+  struct in_addr a,m;
+  int bits=32;
+  char *sep;
+
+  char *mask=strdup(omask);
+  sep=strchr(mask,'/');
+
+  if(sep) {
+    bits=atoi(sep+1);
+    *sep=0;
+  }
+
+  if(!Utility::inet_aton(address, &a) || !Utility::inet_aton(mask, &m))\r
+  {\r
+    free(mask);
+    return -1;
+  }
+
+  free(mask);
+
+  // bits==32 -> 0xffffffff
+  // bits==16 -> 0xffff0000
+  // bits==0 ->  0x00000000
+  unsigned int bmask=~((1<<(32-bits))-1);     // 1<<16 0000 0000  0000 0000  0000 0000  0000 0000
+
+  /*
+  fprintf(stderr,"%x\n",bmask);
+  fprintf(stderr,"%x\n",(htonl((unsigned int)a.s_addr) & bmask));
+  fprintf(stderr,"%x\n",(htonl((unsigned int)m.s_addr) & bmask));
+  */
+
+  return ((htonl((unsigned int)a.s_addr) & bmask) == (htonl((unsigned int)m.s_addr) & bmask));
+}
+
+int waitForData(int fd, int seconds)
+{
+  struct timeval tv;\r
+  int ret;\r
+\r
+  tv.tv_sec   = seconds;\r
+  tv.tv_usec  = 0;\r
+\r
+  fd_set readfds;\r
+  FD_ZERO( &readfds );\r
+  FD_SET( fd, &readfds );\r
+\r
+  ret = select( fd + 1, &readfds, NULL, NULL, &tv );\r
+  if ( ret == -1 )\r
+  {\r
+    ret = -1;\r
+    errno = ETIMEDOUT;\r
+  }\r
+\r
+  return ret;
+}
+
+
+string humanDuration(time_t passed)
+{
+  ostringstream ret;
+  if(passed<60)
+    ret<<passed<<" seconds";
+  else if(passed<3600)
+    ret<<setprecision(2)<<passed/60.0<<" minutes";
+  else if(passed<86400)
+    ret<<setprecision(3)<<passed/3600.0<<" hours";
+  else if(passed<(86400*30.41))
+    ret<<setprecision(3)<<passed/86400.0<<" days";
+  else
+    ret<<setprecision(3)<<passed/(86400*30.41)<<" months";
+
+  return ret.str();
+}
+
+DTime::DTime()
+{
+//  set();
+}
+
+DTime::DTime(const DTime &dt)
+{
+  d_set=dt.d_set;
+}
+
+time_t DTime::time()
+{
+  return d_set.tv_sec;
+}
+
+// Make s uppercase:
+void upperCase(string& s) {
+  for(unsigned int i = 0; i < s.length(); i++)
+    s[i] = toupper(s[i]);
+}
+
+
+void chomp(string &line, const string &delim)
+{
+  string::reverse_iterator i;
+  for( i=line.rbegin();i!=line.rend();++i) 
+    if(delim.find(*i)==string::npos) 
+      break;
+  
+  line.resize(line.rend()-i);
+}
+
+
+
+
+void stripLine(string &line)
+{
+  unsigned int pos=line.find_first_of("\r\n");
+  if(pos!=string::npos) {
+    line.resize(pos);
+  }
+}
+
+string urlEncode(const string &text)
+{
+  string ret;
+  for(string::const_iterator i=text.begin();i!=text.end();++i)
+    if(*i==' ')ret.append("%20");
+    else ret.append(1,*i);
+  return ret;
+}
+
+string getHostname()
+{
+  char tmp[MAXHOSTNAMELEN];
+  if(gethostname(tmp, MAXHOSTNAMELEN))
+    return "UNKNOWN";
+
+  return tmp;
+}
+
+string itoa(int i)
+{
+  ostringstream o;
+  o<<i;
+  return o.str();
+}
+
+string stringerror()
+{
+  return strerror(errno);
+}
+
+void cleanSlashes(string &str)
+{
+  string::const_iterator i;
+  string out;
+  for(i=str.begin();i!=str.end();++i) {
+    if(*i=='/' && i!=str.begin() && *(i-1)=='/')
+      continue;
+    out.append(1,*i);
+  }
+  str=out;
+}
+
+const string sockAddrToString(struct sockaddr_in *remote, socklen_t socklen) 
+{    
+  if(socklen==sizeof(struct sockaddr_in))
+     return inet_ntoa(((struct sockaddr_in *)remote)->sin_addr);
+
+  // TODO: Add ipv6 support here.
+#ifndef WIN32
+  else {
+    char tmp[128];
+    
+    if(!inet_ntop(AF_INET6, (void*)&((struct sockaddr_in6 *)remote)->sin6_addr, tmp, sizeof(tmp)))
+      return "IPv6 untranslateable";
+
+    return tmp;
+  }
+#endif // WIN32
+
+  return "untranslateable";
+}
diff --git a/pdns/misc.hh b/pdns/misc.hh
new file mode 100644 (file)
index 0000000..6e30724
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef MISC_HH
+#define MISC_HH
+/* (C) 2002 POWERDNS.COM BV */
+\r
+
+#include "utility.hh"
+
+#ifndef WIN32
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <time.h>\r
+\r
+#else\r
+# pragma warning ( disable: 4786 )\r
+# define WINDOWS_LEAN_AND_MEAN\r
+# include <windows.h>\r
+# include "utility.hh"\r
+\r
+\r
+#endif // WIN32\r
+\r
+
+#include <string>
+#include <ctype.h>
+using namespace std;
+int matchNetmask(const char *address, const char *omask);
+string humanDuration(time_t passed);
+void chomp(string &line, const string &delim);
+void stripLine(string &line);
+string getHostname();
+string urlEncode(const string &text);
+int waitForData(int fd, int seconds);
+
+void upperCase(string& s);
+
+struct ServiceTuple
+{
+  string host;
+  u_int16_t port;
+};
+void parseService(const string &descr, ServiceTuple &st);
+
+template <typename Container>
+void
+stringtok (Container &container, string const &in,
+           const char * const delimiters = " \t\n")
+{
+  const string::size_type len = in.length();
+  string::size_type i = 0;
+  
+  while (i<len) {
+    // eat leading whitespace
+    i = in.find_first_not_of (delimiters, i);
+    if (i == string::npos)
+      return;   // nothing left but white space
+    
+    // find the end of the token
+    string::size_type j = in.find_first_of (delimiters, i);
+    
+    // push token
+    if (j == string::npos) {
+      container.push_back (in.substr(i));
+      return;
+    } else
+      container.push_back (in.substr(i, j-i));
+    
+    // set up for next loop
+    i = j + 1;
+  }
+}
+string toLower(const string &upper);
+
+string stringerror();
+string itoa(int i);
+
+void dropPrivs(int uid, int gid);
+int makeGidNumeric(const string &group);
+int makeUidNumeric(const string &user);
+void cleanSlashes(string &str);
+
+/** The DTime class can be used for timing statistics with microsecond resolution. 
+On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
+class DTime 
+{
+public:
+  DTime(); //!< This constructor calls set() for you so the timer is set on construction
+  DTime(const DTime &dt);
+  time_t time();
+  inline void set();  //!< Reset the timer
+  inline int udiff(); //!< Return the number of microseconds since the timer was last set.
+private:
+  struct timeval d_set;
+};
+const string sockAddrToString(struct sockaddr_in *remote, socklen_t socklen);
+int sendData(const char *buffer, int replen, int outsock);
+
+
+inline void DTime::set()
+{
+  Utility::gettimeofday(&d_set,0);
+}
+
+inline int DTime::udiff()
+{
+  struct timeval now;
+  Utility::gettimeofday(&now,0);
+
+  return 1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
+}
+
+inline string toLower(const string &upper)
+{
+  string reply(upper);
+  for(unsigned int i = 0; i < reply.length(); i++)
+    reply[i] = tolower(reply[i]);
+  return reply;
+}
+
+
+#endif
diff --git a/pdns/missing b/pdns/missing
new file mode 100755 (executable)
index 0000000..0a7fb5a
--- /dev/null
@@ -0,0 +1,283 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program 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, 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# 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.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing 0.3 - GNU automake"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f y.tab.h ]; then
+       echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+        you modified a dependency of a manual page.  You may need the
+        \`Help2man' package in order for those modifications to take
+        effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+       file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo ".ab help2man is required to generate this page"
+       exit 1
+    fi
+    ;;
+
+  makeinfo)
+    if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+       # We have makeinfo, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  tar)
+    shift
+    if test -n "$run"; then
+      echo 1>&2 "ERROR: \`tar' requires --run"
+      exit 1
+    fi
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar ${1+"$@"} && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar ${1+"$@"} && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+       case "$firstarg" in
+       *o*)
+           firstarg=`echo "$firstarg" | sed s/o//`
+           tar "$firstarg" ${1+"$@"} && exit 0
+           ;;
+       esac
+       case "$firstarg" in
+       *h*)
+           firstarg=`echo "$firstarg" | sed s/h//`
+           tar "$firstarg" ${1+"$@"} && exit 0
+           ;;
+       esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/pdns/mkbindist.in b/pdns/mkbindist.in
new file mode 100755 (executable)
index 0000000..75c9ae1
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+DIR=pdns-nameserver-$(uname -m -s | tr L l | tr ' ' '-')-@VERSION@
+rm -rf $DIR
+mkdir $DIR
+cp backends/bind/zone2sql pdns_server pdns_control binpatch $DIR
+strip $DIR/*
+cp choosepaths installer pdns.in pathconfig LICENSE README $DIR
+
+
+if file ./pdns_server | grep -q dynamic 
+then 
+       mkdir $DIR/libs
+       cp libs/* $DIR/libs     # backends
+       strip $DIR/libs/*.so
+#      ldd ./pdns_server | cut -f2 -d\> | cut -f1 -d\( | grep -v ld-linux.so | \
+#      grep -v libm.so | grep -v libc.so | grep -v libpthread.so | grep -v libdl.so \
+#      > libs.tmp
+#      cp $(cat libs.tmp) $DIR/libs
+#      rm libs.tmp
+fi
+
+
+mkdir $DIR/docs
+cp docs/pdns.pdf $DIR/docs
+cp docs/pdns.txt $DIR/docs
+cp docs/html.tar.gz $DIR/docs
+
+tar cvzf $DIR.tar.gz $DIR
diff --git a/pdns/mkinstalldirs b/pdns/mkinstalldirs
new file mode 100755 (executable)
index 0000000..3994129
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1 2002/11/27 15:18:30 ahu Exp $
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/pdns/mtasker.cc b/pdns/mtasker.cc
new file mode 100644 (file)
index 0000000..6bf9617
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "mtasker.hh"
+#include <stdio.h>
+#include <iostream>
+
+/** \mainpage
+    Simple system for implementing cooperative multitasking of functions, with 
+    support for waiting on events which can return values.
+
+    \section copyright Copyright and License
+    MTasker is (c) 2002 by bert hubert. It is licensed to you under the terms of the GPL version 2.
+
+    \section overview High level overview
+    MTasker is designed to support very simple cooperative multitasking to facilitate writing 
+    code that would ordinarily require a statemachine, for which the author does not consider 
+    himself smart enough.
+
+    This class does not perform any magic it only makes calls to makecontext() and swapcontext(). 
+    Getting the details right however is complicated and MTasker does that for you.
+
+    If preemptive multitasking or more advanced concepts such as semaphores, locks or mutexes
+    are required, the use of POSIX threads is advised.
+
+    MTasker is designed to offer the performance of statemachines while maintaining simple thread semantics. It is not
+    a replacement for a full threading system.
+
+    \section concepts Concepts
+
+    There are two important concepts, the 'kernel' and the 'thread'. Each thread starts out as a function,
+    which is passed to MTasker::makeThread(), together with a possible argument.
+
+    This function is now free to do whatever it wants, but realise that MTasker implements cooperative
+    multitasking, which means that the coder has the responsiblilty of not taking the CPU overly long.
+    Other threads can only get the CPU if MTasker::yield() is called or if a thread sleeps to wait for an event, 
+    using the MTasker::waitEvent() method.
+
+    \section kernel The Kernel
+    The Kernel consists of functions that do housekeeping, but also of code that the client coder 
+    can call to report events. A minimal kernel loop looks like this:
+    \code
+    for(;;) {
+       MT.schedule();
+       if(MT.noProcesses())  // exit if no processes are left
+          break;
+    }
+    \endcode
+
+    The kernel typically starts from the main() function of your program. New threads are also
+    created from the kernel. This can also happen before entering the main loop. To start a thread,
+    the method MTasker::makeThread is provided.
+
+    \section events Events
+    By default, Events are recognized by an int and their value is also an int.
+    This can be overriden by specifying the EventKey and EventVal template parameters.
+    
+    An event can be a keypress, but also a UDP packet, or a bit of data from a TCP socket. The
+    sample code provided works with keypresses, but that is just a not very useful example.
+
+    A thread can also wait for an event only for a limited time, and receive a timeout of that 
+    event did not occur within the specified timeframe.
+
+    \section example A simple menu system
+    \code
+MTasker<> MT;
+
+void menuHandler(void *p)
+{
+  int num=(int)p;
+  cout<<"Key handler for key "<<num<<" launched"<<endl;
+  MT.waitEvent(num);
+  cout<<"Key "<<num<<" was pressed!"<<endl;
+}
+
+
+int main()
+{
+  char line[10];
+
+  for(int i=0;i<10;++i) 
+    MT.makeThread(menuHandler,(void *)i);
+  
+  for(;;) {
+    while(MT.schedule()); // do everything we can do
+    if(MT.noProcesses())  // exit if no processes are left
+      break;
+
+    if(!fgets(line,sizeof(line),stdin))
+      break;
+    
+    MT.sendEvent(*line-'0');
+  }
+}
+\endcode
+
+\section example2 Canonical multitasking example
+This implements the canonical multitasking example, alternately printing an 'A' and a 'B'. The Linux kernel
+  started this way too.
+\code
+void printer(void *p)
+{
+  char c=(char)p;
+  for(;;) {
+    cout<<c<<endl;
+    MT.yield();
+  }
+
+}
+
+int main()
+{
+  MT.makeThread(printer,(void*)'a');
+  MT.makeThread(printer,(void*)'b');
+
+  for(;;) {
+    while(MT.schedule()); // do everything we can do
+    if(MT.noProcesses())  // exit if no processes are left
+      break;
+  }
+}
+\endcode
+
+*/
+
+//! puts a thread to sleep waiting until a specified event arrives
+/** Threads can call waitEvent to register that they are waiting on an event with a certain key.
+    If so desidered, the event can carry data which is returned in val in case that is non-zero.
+    
+    Furthermore, a timeout can be specified in seconds.
+    
+    Only one thread can be waiting on a key, results of trying to have more threads
+    waiting on the same key are undefined.
+    
+    \param key Event key to wait for. Needs to match up to a key reported to sendEvent
+    \param val If non-zero, the value of the event will be stored in *val
+    \param timeout If non-zero, number of seconds to wait for an event.
+    
+    \return returns -1 in case of error, 0 in case of timeout, 1 in case of an answer 
+*/
+
+template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(const EventKey &key, EventVal *val, unsigned int timeout)
+{
+  Waiter w;
+  w.context=new ucontext_t;
+  w.ttd= timeout ? time(0)+timeout : 0;
+  w.tid=d_tid;
+  
+  d_waiters[key]=w;
+  
+  swapcontext(d_waiters[key].context,&d_kernel); // 'A' will return here when 'key' has arrived, hands over control to kernel first
+  if(val && d_waitstatus==Answer) 
+    *val=d_waitval;
+  return d_waitstatus;
+}
+
+//! yields control to the kernel or other threads
+/** Hands over control to the kernel, allowing other processes to run, or events to arrive */
+
+template<class Key, class Val>void MTasker<Key,Val>::yield()
+{
+  d_runQueue.push(d_tid);
+  swapcontext(d_threads[d_tid],&d_kernel); // give control to the kernel
+}
+
+//! reports that an event took place for which threads may be waiting
+/** From the kernel loop, sendEvent can be called to report that something occured for which there may be waiters.
+    \param key Key of the event for which threads may be waiting
+    \param val If non-zero, pointer to the content of the event
+    \return Returns -1 in case of error, 0 if there were no waiters, 1 if a thread was woken up.
+*/
+template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::sendEvent(const EventKey& key, const EventVal* val)
+{
+  if(!d_waiters.count(key)) {
+    return 0;
+  }
+  
+  d_waitstatus=Answer;
+  if(val)
+    d_waitval=*val;
+  
+  ucontext_t *userspace=d_waiters[key].context;
+  d_tid=d_waiters[key].tid;         // set tid 
+  
+  d_waiters.erase(key);             // removes the waitpoint 
+  swapcontext(&d_kernel,userspace); // swaps back to the above point 'A'
+  
+  delete userspace;
+  return 1;
+}
+
+//! launches a new thread
+/** The kernel can call this to make a new thread, which starts at the function start and gets passed the val void pointer.
+    \param start Pointer to the function which will form the start of the thread
+    \param val A void pointer that can be used to pass data to the thread
+*/
+template<class Key, class Val>void MTasker<Key,Val>::makeThread(tfunc_t *start, void* val)
+{
+  ucontext_t *uc=new ucontext_t;
+  getcontext(uc);
+  
+  uc->uc_link = &d_kernel; // come back to kernel after dying
+  uc->uc_stack.ss_sp = new char[d_stacksize];
+  
+  uc->uc_stack.ss_size = d_stacksize;
+  makecontext (uc, (void (*)(void))threadWrapper, 4, this, start, d_maxtid, val);
+  d_threads[d_maxtid]=uc;
+  d_runQueue.push(d_maxtid++); // will run at next schedule invocation
+}
+
+
+//! needs to be called periodically so threads can run and housekeeping can be performed
+/** The kernel should call this function every once in a while. It makes sense
+    to call this function if you:
+    - reported an event
+    - called makeThread
+    - want to have threads running waitEvent() to get a timeout if enough time passed 
+    
+    \return Returns if there is more work scheduled and recalling schedule now would be useful
+      
+*/
+template<class Key, class Val>bool MTasker<Key,Val>::schedule()
+{
+
+  if(!d_runQueue.empty()) {
+    d_tid=d_runQueue.front();
+    swapcontext(&d_kernel, d_threads[d_tid]);
+    d_runQueue.pop();
+    return true;
+  }
+  if(!d_zombiesQueue.empty()) {
+    delete (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
+    delete d_threads[d_zombiesQueue.front()];
+    d_threads.erase(d_zombiesQueue.front());
+    d_zombiesQueue.pop();
+    return true;
+  }
+  if(!d_waiters.empty()) {
+    time_t now=time(0);
+    for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();++i) {
+      if(i->second.ttd && i->second.ttd<now) {
+       d_waitstatus=TimeOut;
+       swapcontext(&d_kernel,i->second.context); // swaps back to the above point 'A'
+       delete i->second.context;              
+       d_waiters.erase(i->first);                  // removes the waitpoint 
+      }
+    }
+  }
+  return false;
+}
+
+//! returns true if there are no processes
+/** Call this to check if no processes are running anymore
+    \return true if no processes are left
+ */
+template<class Key, class Val>bool MTasker<Key,Val>::noProcesses()
+{
+  return d_threads.empty();
+}
+
+//! gives access to the list of Events threads are waiting for
+/** The kernel can call this to get a list of Events threads are waiting for. This is very useful
+    to setup 'select' or 'poll' or 'aio' events needed to satisfy these requests.
+    getEvents clears the events parameter before filling it.
+
+    \param events Vector which is to be filled with keys threads are waiting for
+*/
+template<class Key, class Val>void MTasker<Key,Val>::getEvents(std::vector<Key>& events)
+{
+  events.clear();
+  for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();++i) {
+    events.push_back(i->first);
+  }
+}
+
+
+template<class Key, class Val>void MTasker<Key,Val>::threadWrapper(MTasker *self, tfunc_t *tf, int tid, void* val)
+{
+  (*tf)(val);
+  self->d_zombiesQueue.push(tid);
+  
+  // we now jump to &kernel, automatically
+}
+
diff --git a/pdns/nameserver.cc b/pdns/nameserver.cc
new file mode 100644 (file)
index 0000000..dc215d5
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: nameserver.cc,v 1.1 2002/11/27 15:18:31 ahu Exp $ \r
+#include "utility.hh"
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cerrno>
+#include <iostream>
+#include <string>
+#include <sys/types.h>
+
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "dnspacket.hh"
+#include "nameserver.hh"
+#include "distributor.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "statbag.hh"
+
+extern StatBag S;
+
+/** \mainpage 
+    ahudns is a very versatile nameserver that can answer questions from different backends. To implement your
+    own backend, see the documentation for the DNSBackend class.
+
+    \section copyright Copyright and License
+    AhuDNS is (C) 2002 PowerDNS BV.
+
+    AhuDNS is NOT open source (yet), so treat this code as a trade secret. If it has been supplied to you for evaluation,
+    this does not mean that you can deploy the code!
+
+    \section overview High level overview
+
+    AhuDNS is highly threaded, which means that several tasks each have their own process thread. Two of the pivotal
+    threads are the qthread() and the athread().
+
+    - The qthread() receives questions over the network (via the Nameserver class, which returns DNSPacket objects), and gives them to the Distributor.
+    - The athread() waits on the Distributor to return answers, ready to send back over the network, again via UDPNameserver.
+
+    The Distributor contains a configurable number of PacketHandler instances, each in its own thread, for connection pooling
+
+    The PacketHandler implements the RFC1034 algorithm and converts question packets into DNSBackend queries.
+
+    A DNSBackend is an entity that returns DNSResourceRecord objects in return to explicit questions for domains with a specified QType
+
+    AhuDNS uses the UeberBackend as its DNSBackend. The UeberBackend by default has no DNSBackends within itself, those are loaded
+    using the dynloader tool. This way DNSBackend implementations can be kept completely separate.
+
+    If one or more DNSBackends are loaded, the UeberBackend fields the queries to all of them until one answers.
+
+    \section TCP TCP Operations
+
+    The TCP operation runs within a single thread called tcpreceiver(), that also queries the PacketHandler. 
+
+    \section Cache Caching
+    On its own, this setup is not suitable for high performance operations. A single DNS query can turn into many DNSBackend questions,
+    each taking many miliseconds to complete. This is why the qthread() first checks the PacketCache to see if an answer is known to a packet
+    asking this question. If so, the entire Distributor is shunted, and the answer is sent back *directly*, within a few microseconds.
+
+    In turn, the athread() offers each outgoing packet to the PacketCache for possible inclusion.
+
+    \section misc Miscellaneous
+    Configuration details are available via the ArgvMap instance arg. Statistics are created by making calls to the StatBag object called S. 
+    These statistics are made available via the UeberBackend on the same socket that is used for dynamic module commands.
+
+    \section Main Main 
+    The main() of AhuDNS can be found in receiver.cc - start reading there for further insights into the operation of the nameserver
+
+
+*/
+
+void UDPNameserver::bindIPv4()
+{
+  vector<string>locals;
+  stringtok(locals,arg()["local-address"]," ,");
+
+  if(locals.empty())
+    throw AhuException("No local address specified");
+
+  int s;
+  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
+    string localname(*i);
+    struct sockaddr_in locala;
+
+    s=socket(AF_INET,SOCK_DGRAM,0);
+    if(s<0)
+      throw AhuException("Unable to acquire a UDP socket: "+string(strerror(errno)));
+  
+    memset(&locala,0,sizeof(locala));
+    locala.sin_family=AF_INET;
+
+    if(localname=="0.0.0.0") {
+      L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
+
+      locala.sin_addr.s_addr = INADDR_ANY;
+    }
+    else
+    {
+      struct hostent *h=0;
+      h=gethostbyname(localname.c_str());
+      if(!h)
+        throw AhuException("Unable to resolve local address"); 
+    
+      locala.sin_addr.s_addr=*(int*)h->h_addr;
+    }
+
+    locala.sin_port=htons(arg().asNum("local-port"));
+    
+    if(bind(s, (sockaddr*)&locala,sizeof(locala))<0) {
+      L<<Logger::Error<<"binding to UDP socket: "<<strerror(errno)<<endl;
+      throw AhuException("Unable to bind to UDP socket");
+    }
+    d_highfd=max(s,d_highfd);
+    d_sockets.push_back(s);
+    L<<Logger::Error<<"UDP server bound to "<<localname<<":"<<arg()["local-port"]<<endl;
+    FD_SET(s, &d_rfds);
+  }
+}
+
+void UDPNameserver::bindIPv6()
+{
+  // TODO: Add Windows ipv6 support.
+#ifndef WIN32
+  vector<string>locals;
+  stringtok(locals,arg()["local-ipv6"]," ,");
+
+  if(locals.empty())
+    return;
+
+
+  int s;
+  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
+    string localname(*i);
+    struct sockaddr_in6 locala;
+
+    s=socket(AF_INET6,SOCK_DGRAM,0);
+    if(s<0)
+      throw AhuException("Unable to acquire a UDPv6 socket: "+string(strerror(errno)));
+  
+    memset(&locala,0,sizeof(locala));
+    locala.sin6_family=AF_INET6;
+
+    if(localname=="::0") {
+      L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-ipv6 option"<<endl;
+    }
+
+    struct hostent *h;
+
+    h=gethostbyname2(localname.c_str(),AF_INET6);
+
+    if(!h)
+      throw AhuException("Unable to resolve local IPv6 address"); 
+    
+    memcpy(&locala.sin6_addr.s6_addr,h->h_addr,16);
+
+    locala.sin6_port=htons(arg().asNum("local-port"));
+    
+    if(bind(s, (sockaddr*)&locala,sizeof(locala))<0) {
+      L<<Logger::Error<<"binding to UDP ipv6 socket: "<<strerror(errno)<<endl;
+      throw AhuException("Unable to bind to UDP ipv6 socket");
+    }
+    d_highfd=max(s,d_highfd);
+    d_sockets.push_back(s);
+    L<<Logger::Error<<"UDPv6 server bound to "<<localname<<":"<<arg()["local-port"]<<endl;
+    FD_SET(s, &d_rfds);
+  }
+#endif // WIN32
+}
+
+UDPNameserver::UDPNameserver()
+{
+  d_highfd=0;
+  FD_ZERO(&d_rfds);  
+  if(!arg()["local-address"].empty())
+    bindIPv4();
+  if(!arg()["local-ipv6"].empty())
+    bindIPv6();
+
+  if(arg()["local-address"].empty() && arg()["local-ipv6"].empty()) 
+    L<<Logger::Critical<<"PDNS is deaf and mute! Not listening on any interfaces"<<endl;
+    
+}
+
+void UDPNameserver::send(DNSPacket *p)
+{
+  const char *buffer=p->getData();
+  DLOG(L<<Logger::Notice<<"Sending a packet to "<<inet_ntoa( reinterpret_cast< sockaddr_in * >(( p->remote ))->sin_addr)<<" ("<<p->len<<" octets)"<<endl);
+  if(p->len>512) {
+    p=new DNSPacket(*p);
+    p->truncate(512);
+    buffer=p->getData();
+    if(sendto(p->getSocket(),buffer,p->len,0,(struct sockaddr *)(p->remote),p->d_socklen)<0)
+      L<<Logger::Error<<"Error sending reply with sendto (socket="<<p->getSocket()<<"): "<<strerror(errno)<<endl;
+    delete p;
+  }
+  else {
+
+    if(sendto(p->getSocket(),buffer,p->len,0,(struct sockaddr *)(p->remote),p->d_socklen)<0)
+      L<<Logger::Error<<"Error sending reply with sendto (socket="<<p->getSocket()<<"): "<<strerror(errno)<<endl;
+
+
+
+  }
+}
+
diff --git a/pdns/nameserver.hh b/pdns/nameserver.hh
new file mode 100644 (file)
index 0000000..d15b406
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: nameserver.hh,v 1.1 2002/11/27 15:18:32 ahu Exp $
+#ifndef NAMESERVER_HH
+#define NAMESERVER_HH
+\r
+#ifndef WIN32
+# include <sys/select.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <sys/time.h>
+# include <unistd.h>\r
+# include <arpa/inet.h>\r
+# include <netdb.h>\r
+\r
+#endif // WIN32\r
+
+#include <vector>
+#include "statbag.hh"
+using namespace std;
+
+/** This is the main class. It opens a socket on udp port 53 and waits for packets. Those packets can 
+    be retrieved with the receive() member function, which returns a DNSPacket.
+
+    Some sample code in main():
+    \code
+    typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor;
+    DNSDistributor D(6); // the big dispatcher!
+    
+    pthread_t qtid, atid;
+    N=new UDPNameserver;
+    
+    pthread_create(&qtid,0,qthread,static_cast<void *>(&D)); // receives packets
+    pthread_create(&atid,0,athread,static_cast<void *>(&D)); // sends packets
+    \endcode
+
+    Code for qthread:
+    \code
+    void *qthread(void *p)
+    {
+      DNSDistributor *D=static_cast<DNSDistributor *>(p);
+    
+      DNSPacket *P;
+    
+      while((P=N->receive())) // receive a packet
+      {
+         D->question(P); // and give to the distributor, they will delete it
+      }
+      return 0;
+    }
+
+    \endcode
+
+*/
+
+class UDPNameserver
+{
+public:
+  UDPNameserver();  //!< Opens the socket
+  inline DNSPacket *receive(DNSPacket *prefilled=0); //!< call this in a while or for(;;) loop to get packets
+  void send(DNSPacket *); //!< send a DNSPacket. Will call DNSPacket::truncate() if over 512 bytes
+  
+private:
+  vector<int> d_sockets;
+  void bindIPv4();
+  void bindIPv6();
+  fd_set d_rfds;
+  int d_highfd;
+};
+
+inline DNSPacket *UDPNameserver::receive(DNSPacket *prefilled)
+{
+  char remote[ 30 ];
+  extern StatBag S;
+
+  Utility::socklen_t addrlen;
+  int len=-1;
+  char mesg[513];
+  Utility::sock_t sock=-1;
+
+  memset( remote, 0, sizeof( remote ));
+  
+  if(d_sockets.size()>1) {
+    fd_set rfds=d_rfds;
+    
+    select(d_highfd+1, &rfds, 0, 0,  0); // blocks
+
+    for(vector<int>::const_iterator i=d_sockets.begin();i!=d_sockets.end();++i) {
+      if(FD_ISSET(*i, &rfds)) {
+       sock=*i;
+       addrlen=sizeof(remote);
+       
+       len=0;
+       if((len=recvfrom(sock,mesg,512,0,(sockaddr*) remote, &addrlen))<0) {
+         L<<Logger::Error<<"recvfrom gave error, ignoring: "<<strerror(errno)<<endl;
+         return 0;
+       }
+       break;
+      }
+    }
+    if(sock==-1)
+      throw AhuException("select betrayed us! (should not happen)");
+  }
+  else {
+    sock=d_sockets[0];
+    addrlen=sizeof(remote);
+    len=0;
+    if((len=recvfrom(sock,mesg,512,0,(sockaddr*) remote, &addrlen))<0) {
+      L<<Logger::Error<<"recvfrom gave error, ignoring: "<<strerror(errno)<<endl;
+      return 0;
+    }
+  }
+  
+  DLOG(L<<"Received a packet " << len <<" bytes long from "<<inet_ntoa( reinterpret_cast< sockaddr_in * >( &remote )->sin_addr )<<endl);
+  
+  DNSPacket *packet;
+  if(prefilled)  // they gave us a preallocated packet
+    packet=prefilled;
+  else
+    packet=new DNSPacket; // don't forget to free it!
+  packet->d_dt.set(); // timing
+  packet->setSocket(sock);
+  packet->setRemote((struct sockaddr *)remote, addrlen);
+  if(packet->parse(mesg, len)<0) {
+    S.inc("corrupt-packets");
+    S.ringAccount("remotes-corrupt", packet->getRemote());
+
+    if(!prefilled)
+      delete packet;
+    return 0; // unable to parse
+  }
+  
+  return packet;
+}
+
+
+
+#endif
diff --git a/pdns/packetcache.cc b/pdns/packetcache.cc
new file mode 100644 (file)
index 0000000..ce72af9
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "packetcache.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "statbag.hh"
+#include <map>
+
+extern StatBag S;
+
+PacketCache::PacketCache()
+{
+  pthread_rwlock_init(&d_mut,0);
+  pthread_mutex_init(&d_dellock,0);
+  d_hit=d_miss=0;
+
+  d_ttl=-1;
+  d_recursivettl=-1;
+
+  S.declare("packetcache-hit");
+  S.declare("packetcache-miss");
+  S.declare("packetcache-size");
+
+  statnumhit=S.getPointer("packetcache-hit");
+  statnummiss=S.getPointer("packetcache-miss");
+  statnumentries=S.getPointer("packetcache-size");
+}
+
+
+void PacketCache::insert(DNSPacket *q, DNSPacket *r)
+{
+  
+  if(ntohs(q->d.qdcount)!=1) {
+    L<<"Warning - tried to cache a packet with wrong number of questions: "<<ntohs(q->d.qdcount)<<endl;
+    return; // do not try to cache packets with multiple questions
+  }
+
+  bool packetMeritsRecursion=d_doRecursion && q->d.rd;
+
+  char ckey[512];
+  int len=q->qdomain.length();
+  memcpy(ckey,q->qdomain.c_str(),len); // add TOLOWER HERE FIXME XXX
+  ckey[len]='|';
+  ckey[len+1]=packetMeritsRecursion ? 'r' : 'n';
+  ckey[len+2]=(q->qtype.getCode()>>8) & 0xff;
+  ckey[len+3]=(q->qtype.getCode()) & 0xff;
+  string key;
+  key.assign(ckey,q->qdomain.length()+4);
+
+  insert(key,r->getString(), packetMeritsRecursion ? d_recursivettl : d_ttl);
+}
+
+void PacketCache::getTTLS()
+{
+  d_ttl=arg().asNum("cache-ttl");
+  d_recursivettl=arg().asNum("recursive-cache-ttl");
+
+  d_doRecursion=arg().mustDo("recursor"); 
+}
+
+void PacketCache::insert(const char *packet, int length) 
+{
+  if(d_ttl<0)
+    getTTLS();
+
+  DNSPacket p;
+  p.parse(packet,length);
+
+  bool packetMeritsRecursion=d_doRecursion && p.d.rd;
+
+  char ckey[512];
+  int len=p.qdomain.length();
+  memcpy(ckey,p.qdomain.c_str(),len); // add TOLOWER HERE FIXME XXX
+  ckey[len]='|';
+  ckey[len+1]=packetMeritsRecursion ? 'r' : 'n';
+  ckey[len+2]=(p.qtype.getCode()>>8) & 0xff;
+  ckey[len+3]=(p.qtype.getCode()) & 0xff;
+  string key;
+  key.assign(ckey,p.qdomain.length()+4);
+  //  string key=toLower(p.qdomain+"|"+(packetMeritsRecursion ? "R" : "N")+"|"+p.qtype.getName());
+
+  string buffer;
+  buffer.assign(packet,length);
+  insert(key,buffer, packetMeritsRecursion ? d_recursivettl : d_ttl);
+}
+
+void PacketCache::insert(const string &key, const string &packet, unsigned int ttl)
+{
+  if(!ttl)
+    return;
+
+  cvalue_t val;
+  val.ttd=time(0)+ttl;
+  val.value=packet;
+
+  TryWriteLock l(&d_mut);
+  if(l.gotIt())  
+    d_map[key]=val;
+  else 
+    S.inc("deferred-cache-inserts"); 
+}
+
+/** purges entries from the packetcache. If prefix ends on a $, it is treated as a suffix */
+int PacketCache::purge(const string &f_prefix)
+{
+  Lock pl(&d_dellock);
+
+  string prefix(f_prefix);
+  if(prefix.empty()) {
+    cmap_t *tmp=new cmap_t;
+    {
+      DTime dt;
+      dt.set();
+      WriteLock l(&d_mut);
+      tmp->swap(d_map);
+      L<<Logger::Error<<"cache clean time: "<<dt.udiff()<<"usec"<<endl;
+    }
+
+    int size=tmp->size();
+    delete tmp;
+
+    *statnumentries=0;
+    return size;
+  }
+
+  bool suffix=false;
+  if(prefix[prefix.size()-1]=='$') {
+    prefix=prefix.substr(0,prefix.size()-1);
+    suffix=true;
+  }
+  string check=prefix+"|";
+
+  vector<cmap_t::iterator> toRemove;
+
+  ReadLock l(&d_mut);
+
+  for(cmap_t::iterator i=d_map.begin();i!=d_map.end();++i) {
+    string::size_type pos=i->first.find(check);
+
+    if(!pos || (suffix && pos!=string::npos)) 
+      toRemove.push_back(i);
+  }
+
+  l.upgrade();  
+
+  for(vector<cmap_t::iterator>::const_iterator i=toRemove.begin();i!=toRemove.end();++i) 
+    d_map.erase(*i);
+  *statnumentries=d_map.size();
+  return toRemove.size();
+}
+
+bool PacketCache::getKey(const string &key, string &content)
+{
+  TryReadLock l(&d_mut); // take a readlock here
+  if(!l.gotIt()) {
+    S.inc("deferred-cache-lookup");
+    return false;
+  }
+
+  // needs to do ttl check here
+  cmap_t::const_iterator i=d_map.find(key);
+  time_t now=time(0);
+  bool ret=(i!=d_map.end() && i->second.ttd>now);
+  if(ret)
+    content=i->second.value;
+  return ret;
+}
+
+map<char,int> PacketCache::getCounts()
+{
+  ReadLock l(&d_mut);
+  int counts[256];
+  unsigned int offset;
+  memset(counts,0,256*sizeof(counts[0]));
+  char key;
+  for(cmap_t::const_iterator i=d_map.begin();i!=d_map.end();++i) {
+    if((offset=i->first.find_first_of("|"))==string::npos || offset+1>i->first.size())
+      continue;
+    
+    key=i->first[offset+1];
+    if((key=='Q' || key=='q') && !i->second.value.empty())
+      key='!';
+    counts[key]++;
+  }
+
+  map<char,int>ret;
+  for(int i=0;i<256;++i)
+    if(counts[i])
+      ret[i]=counts[i];
+  return ret;
+
+}
+
+
+int PacketCache::size()
+{
+  ReadLock l(&d_mut);
+  return d_map.size();
+}
+
+/** readlock for figuring out which iterators to delete, upgrade to writelock when actually cleaning */
+void PacketCache::cleanup()
+{
+  Lock pl(&d_dellock); // ALWAYS ACQUIRE DELLOCK FIRST
+  ReadLock l(&d_mut);
+
+  *statnumentries=d_map.size();
+
+  time_t now=time(0);
+
+  DLOG(L<<"Starting cache clean"<<endl);
+  if(d_map.begin()==d_map.end()) {
+    return; // clean
+  }
+
+  vector<cmap_t::iterator> toRemove;
+
+  for(cmap_t::iterator i=d_map.begin();i!=d_map.end();++i) {
+    if(now>i->second.ttd)
+      toRemove.push_back(i);
+  }
+
+  l.upgrade(); 
+
+  for(vector<cmap_t::iterator>::const_iterator i=toRemove.begin();i!=toRemove.end();++i) 
+    d_map.erase(*i);
+    
+  *statnumentries=d_map.size();
+  DLOG(L<<"Done with cache clean"<<endl);
+}
diff --git a/pdns/packetcache.hh b/pdns/packetcache.hh
new file mode 100644 (file)
index 0000000..8b52b98
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PACKETCACHE_HH
+#define PACKETCACHE_HH
+
+#include <string>
+#include <utility>
+#include <map>
+
+#ifndef WIN32
+# if __GNUC__ >= 3
+#   include <ext/hash_map>
+using namespace __gnu_cxx;
+# else
+#   include <hash_map>
+# endif // __GNUC__
+
+#else
+# include <map>
+
+#endif // WIN32
+
+using namespace std;
+
+#include "dnspacket.hh"
+#include "lock.hh"
+#include "statbag.hh"
+
+/** This class performs 'whole packet caching'. Feed it a question packet and it will
+    try to find an answer. If you have an answer, insert it to have it cached for later use. 
+    Take care not to replace existing cache entries. While this works, it is wasteful. Only
+    insert packets that where not found by get()
+
+    Locking! 
+
+    The cache itself is protected by a read/write lock. Because deleting is a two step process, which 
+    first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes.
+
+    Overloading!
+
+    The packet cache contains packets but also negative UeberBackend queries. Those last are recognized
+    because they start with a | and have empty content. One day, this content may also contain queries.
+
+*/
+class PacketCache
+{
+public:
+  PacketCache();
+  void insert(DNSPacket *q, DNSPacket *r);  //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources
+  void PacketCache::insert(const char *packet, int length);
+
+  inline int get(DNSPacket *p, DNSPacket *q); //!< We return a dynamically allocated copy out of our cache. You need to delete it. You also need to spoof in the right ID with the DNSPacket.spoofID() method.
+  bool getKey(const string &key, string &content);
+  int size(); //!< number of entries in the cache
+  void cleanup(); //!< force the cache to preen itself from expired packets
+  int purge(const string &prefix="");
+  void insert(const string &key, const string &packet, unsigned int ttl);
+  map<char,int> getCounts();
+private:
+  typedef string ckey_t;
+
+  class CacheContent
+  {
+  public:
+    time_t ttd;
+    string value;
+  };
+
+  typedef CacheContent cvalue_t;
+  void getTTLS();
+#ifndef WIN32
+
+  struct compare_string
+  {
+    bool operator()(const string& s1, const string& s2) const
+    {
+      return s1 == s2;
+    }
+  };
+
+  struct hash_string
+  {
+    size_t operator()(const string& s) const
+    {
+      return __stl_hash_string(s.c_str());
+    }
+  };
+
+  typedef hash_map<ckey_t,cvalue_t, hash_string, compare_string > cmap_t;
+
+#else
+  typedef map< ckey_t, cvalue_t > cmap_t;
+
+#endif // WIN32
+
+  cmap_t d_map;
+
+  pthread_rwlock_t d_mut;
+  pthread_mutex_t d_dellock;
+
+  int d_hit;
+  int d_miss;
+  int d_ttl;
+  int d_recursivettl;
+  bool d_doRecursion;
+  int *statnumhit;
+  int *statnummiss;
+  int *statnumentries;
+};
+
+inline int PacketCache::get(DNSPacket *p, DNSPacket *cached)
+{
+  extern StatBag S;
+  if(!((d_hit+d_miss)%5000)) {
+    cleanup();
+  }
+
+  if(d_ttl<0) 
+    getTTLS();
+
+  if(d_doRecursion && p->d.rd) { // wants recursion
+    if(!d_recursivettl) {
+      (*statnummiss)++;
+      d_miss++;
+      return 0;
+    }
+  }
+  else { // does not
+    if(!d_ttl) {
+      (*statnummiss)++;
+      d_miss++;
+      return 0;
+    }
+  }
+    
+  bool packetMeritsRecursion=d_doRecursion && p->d.rd;
+  char ckey[512];
+  int len=p->qdomain.length();
+  memcpy(ckey,p->qdomain.c_str(),len); // add TOLOWER HERE FIXME XXX
+  ckey[len]='|';
+  ckey[len+1]=packetMeritsRecursion ? 'r' : 'n';
+  ckey[len+2]=(p->qtype.getCode()>>8)&0xff;
+  ckey[len+3]=(p->qtype.getCode())&0xff;
+  string key;
+
+  key.assign(ckey,p->qdomain.length()+4);
+  //  cout<<"key lookup: '"<<key<<"'"<<endl;
+  //  string key=toLower(p->qdomain+"|"+(packetMeritsRecursion ? "R" : "N")+ "|"+p->qtype.getName());
+
+  if(ntohs(p->d.qdcount)!=1) // we get confused by packets with more than one question
+    return 0;
+
+  {
+    TryReadLock l(&d_mut); // take a readlock here
+    if(!l.gotIt()) {
+      S.inc("deferred-cache-lookup");
+      return 0;
+    }
+
+    if(!((d_hit+d_miss)%1000)) {
+      *statnumentries=d_map.size(); // needs lock
+    }
+    cmap_t::const_iterator i;
+    if((i=d_map.find(key))!=d_map.end()) { // HIT!
+
+      if(i->second.ttd>time(0)) { // it is still fresh
+       (*statnumhit)++;
+       d_hit++;
+       cached->parse(i->second.value.c_str(),i->second.value.size());  
+       cached->spoofQuestion(p->qdomain); // for correct case
+       return 1;
+      }
+    }
+  }
+  (*statnummiss)++;
+  d_miss++;
+  return 0; // bummer
+}
+
+
+#endif /* PACKETCACHE_HH */
+
diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc
new file mode 100644 (file)
index 0000000..a70e2f1
--- /dev/null
@@ -0,0 +1,784 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"
+#include <string>
+#include <sys/types.h>
+
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "ueberbackend.hh"
+#include "dnspacket.hh"
+#include "nameserver.hh"
+#include "distributor.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "packethandler.hh"
+#include "statbag.hh"
+#include "resolver.hh"
+#include "communicator.hh"
+#include "dnsproxy.hh"
+
+extern StatBag S;
+extern PacketCache PC;  
+extern CommunicatorClass Communicator;
+extern DNSProxy *DP;
+
+int PacketHandler::s_count;
+extern string s_programname;
+
+
+PacketHandler::PacketHandler():B(s_programname)
+{
+  s_count++;
+  d_doFancyRecords = (arg()["fancy-records"]!="no");
+  d_doWildcards = (arg()["wildcards"]!="no");
+  d_doCNAME = (arg()["skip-cname"]=="no");
+  d_doRecursion= arg().mustDo("recursor");
+  d_doLazyRecursion= arg().mustDo("lazy-recursion");
+  d_logDNSDetails= arg().mustDo("log-dns-details");
+}
+
+DNSBackend *PacketHandler::getBackend()
+{
+  return &B;
+}
+
+PacketHandler::~PacketHandler()
+{
+  --s_count;
+  DLOG(L<<Logger::Error<<"PacketHandler destructor called - "<<s_count<<" left"<<endl);
+
+}
+
+
+int PacketHandler::findMboxFW(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+  bool wedoforward=false;
+
+  B.lookup("MBOXFW",string("%@")+target,p);
+      
+  while(B.get(rr))
+    wedoforward=true;
+
+  if(wedoforward) {
+    rr.content=arg()["smtpredirector"];
+    rr.priority=25;
+    rr.ttl=7200;
+    rr.qtype=QType::MX;
+    rr.qname=target;
+    
+    r->addRecord(rr);
+  }
+
+  return wedoforward;
+}
+
+int PacketHandler::findUrl(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+
+  bool found=false;
+      
+  B.lookup("URL",target,p); // search for a URL before we search for an A
+        
+  while(B.get(rr)) {
+    found=true;
+    DLOG(L << "Found a URL!" << endl);
+    rr.content=arg()["urlredirector"];
+    rr.qtype=QType::A; 
+    rr.qname=target;
+         
+    r->addRecord(rr);
+  }  
+
+  if(found)
+    return 1;
+      
+  // now try CURL
+  
+  B.lookup("CURL",target,p); // search for a URL before we search for an A
+      
+  while(B.get(rr)) {
+    found=true;
+    DLOG(L << "Found a CURL!" << endl);
+    rr.content=arg()["urlredirector"];
+    rr.qtype=1; // A
+    rr.qname=target;
+    rr.ttl=300;
+    r->addRecord(rr);
+  }  
+
+  if(found)
+    return found;
+  return 0;
+}
+
+/** Returns 0 if nothing was found, -1 if an error occured or 1 if the search
+    was satisfied */
+int PacketHandler::doFancyRecords(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+
+  if(p->qtype.getCode()==QType::MX)  // check if this domain has smtp service from us
+    return findMboxFW(p,r,target);
+  
+  if(p->qtype.getCode()==QType::A)   // search for a URL record for an A
+    return findUrl(p,r,target);
+
+  return 0;
+}
+
+int PacketHandler::doDNSCheckRequest(DNSPacket *p, DNSPacket *r, string &target)
+{
+  int result = 0;
+  DNSResourceRecord rr;
+
+  if (p->qclass == 3 && p->qtype.getName() == "HINFO") {
+    rr.content = "PowerDNS $Id: packethandler.cc,v 1.1 2002/11/27 15:18:31 ahu Exp $";
+    rr.ttl = 5;
+    rr.qname=target;
+    rr.qtype=13; // hinfo
+    r->addRecord(rr);
+    result = 1;
+  }
+  
+  return result;
+}
+
+/** This catches version requests. Returns 1 if it was handled, 0 if it wasn't */
+int PacketHandler::doVersionRequest(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+  if(p->qtype.getCode()==QType::TXT && target=="version.bind") {// TXT
+    rr.content="Served by POWERDNS "VERSION" $Id: packethandler.cc,v 1.1 2002/11/27 15:18:31 ahu Exp $";
+    rr.ttl=5;
+    rr.qname=target;
+    rr.qtype=QType::TXT; // TXT
+    r->addRecord(rr);
+    
+    return 1;
+  }
+  return 0;
+}
+
+/** Determines if we are authoritative for a zone, and at what level */
+bool PacketHandler::getTLDAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId)
+{
+  static string theSOA="."+arg()["only-soa"];
+  static SOAData cachedSD;
+  static bool haveIt;
+
+  if((target.size()-toLower(target).rfind(toLower(theSOA)))!=theSOA.size()) {
+    //    cerr<<"target '"<<target<<"' does not end on '"<<theSOA<<"'"<<endl;
+    return false;
+  }
+  if(!haveIt) {
+    if(B.getSOA(arg()["only-soa"], cachedSD)) {
+      cachedSD.qname=arg()["only-soa"];
+
+      haveIt=true;
+    }
+  }
+  if(haveIt) {
+    *zoneId=sd->domain_id;  
+    *sd=cachedSD;
+  }
+  return haveIt;
+}
+
+/** Determines if we are authoritative for a zone, and at what level */
+bool PacketHandler::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId)
+{
+  DNSResourceRecord rr;
+
+  vector<string>parts;
+  stringtok(parts,target,".");  // www.us.powerdns.com -> 'www' 'us' 'powerdns' 'com'
+  
+  unsigned int spos=0;
+  string subdomain;
+
+  while(spos<=parts.size()) {
+    if(spos<parts.size()) { // www.us.powerdns.com -> us.powerdns.com -> powerdns.com -> com ->
+      subdomain=parts[spos++];
+      for(unsigned int i=spos;i<parts.size();++i) {
+       subdomain+=".";
+       subdomain+=parts[i];
+      }
+    }
+    else {
+      subdomain=""; // ROOT!
+      spos++;
+    }
+    if(B.getSOA(subdomain, *sd)) {
+      sd->qname=subdomain;
+      *zoneId=sd->domain_id;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/** returns 1 in case of a straight match, 2 in case of a wildcard CNAME (groan), 0 in case of no hit */
+int PacketHandler::doWildcardRecords(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+  bool found=false, retargeted=false;
+
+  // try chopping off domains and look for wildcard matches
+
+  // *.pietje.nl IN  A 1.2.3.4
+  // pietje.nl should now NOT match, but www.pietje.nl should
+
+  string subdomain=target;
+  unsigned int pos;
+  while((pos=subdomain.find("."))!=string::npos) {
+    subdomain=subdomain.substr(pos+1);
+    // DLOG();
+
+    string searchstr=string("*.")+subdomain;
+
+    B.lookup(QType(QType::ANY), searchstr,p); // start our search at the backend
+
+    while(B.get(rr)) { // read results
+      found=true;
+      if(rr.qtype==p->qtype || rr.qtype.getCode()==QType::CNAME) {
+       rr.qname=target;
+       r->addRecord(rr);  // and add
+       if(rr.qtype.getCode()==QType::CNAME) {
+         if(target==rr.content) {
+           L<<Logger::Error<<"Ignoring wildcard CNAME '"<<rr.qname<<"' pointing at itself"<<endl;
+           r->setRcode(RCode::ServFail);
+           continue;
+         }
+         
+         DLOG(L<<Logger::Error<<"Retargeting because of wildcard cname, from "<<target<<" to "<<rr.content<<endl);
+         
+         target=rr.content; // retarget 
+         retargeted=true;
+       }
+      }
+      else if(d_doFancyRecords && arg().mustDo("wildcard-url") && p->qtype.getCode()==QType::A && rr.qtype.getName()=="URL") {
+       rr.content=arg()["urlredirector"];
+       rr.qtype=QType::A; 
+       rr.qname=target;
+       
+       r->addRecord(rr);
+      }
+    }
+    if(found) {
+      DLOG(L<<"Wildcard match on '"<<string("*.")+subdomain<<"'"<<endl);
+      return retargeted ? 2 : 1;
+    }
+  }
+  return 0;
+}
+
+/** dangling is declared true if we were unable to resolve everything */
+int PacketHandler::doAdditionalProcessing(DNSPacket *p, DNSPacket *r, bool &dangling)
+{
+  DNSResourceRecord rr;
+  dangling=false;
+  if(p->qtype.getCode()!=QType::AXFR && r->needAP()) { // this packet needs additional processing
+    DLOG(L<<Logger::Warning<<"This packet needs additional processing!"<<endl);
+
+    vector<DNSResourceRecord> arrs=r->getAPRecords();
+    
+    for(vector<DNSResourceRecord>::const_iterator i=arrs.begin();
+       i!=arrs.end();
+       ++i) {
+      B.lookup("A",i->content,p);  
+      bool foundOne=false;
+      while(B.get(rr)) {
+       foundOne=true;
+       if(rr.domain_id!=i->domain_id && arg()["out-of-zone-additional-processing"]=="no") {
+         DLOG(L<<Logger::Warning<<"Not including out-of-zone additional processing of "<<i->qname<<" ("<<rr.qname<<")"<<endl);
+         continue; // not adding out-of-zone additional data
+       }
+       
+       rr.d_place=DNSResourceRecord::ADDITIONAL;
+       r->addRecord(rr);
+
+      }
+      if(!foundOne)
+       dangling=true;
+    }
+  }
+  return 1;
+}
+
+/* returns 1 if everything is done & ready, 0 if the search should continue */
+int PacketHandler::makeCanonic(DNSPacket *p, DNSPacket *r, string &target)
+{
+  DNSResourceRecord rr;
+
+  bool found=false, rfound=false;
+
+  if(p->qtype.getCode()!=QType::CNAME && !d_doCNAME)
+    return 0;
+
+  // Traverse a CNAME chain if needed
+  for(int numloops=0;;numloops++) {
+    if(numloops==10) {
+      L<<Logger::Error<<"Detected a CNAME loop involving "<<target<<", sending SERVFAIL"<<endl;
+      r->setRcode(2);
+      return 1;
+    }
+
+    B.lookup(QType(QType::ANY),target,p);
+        
+    bool shortcut=p->qtype.getCode()!=QType::SOA && p->qtype.getCode()!=QType::ANY;
+
+    while(B.get(rr)) {
+      if(!rfound && rr.qtype.getCode()==QType::CNAME) {
+       found=true;
+       r->addRecord(rr);
+       target=rr.content; // for retargeting
+      }
+      if(shortcut && !found && rr.qtype==p->qtype) {
+       rfound=true;
+       r->addRecord(rr);
+      }
+    }
+    if(rfound)
+      return 1; // ANY lookup found the right answer immediately
+
+    if(found) {
+      if(p->qtype.getCode()==QType::CNAME) // they really wanted a CNAME!
+       return 1;
+      DLOG(L<<"Looping because of a CNAME to "<<target<<endl);
+      found=false;
+    }
+    else break;
+  }
+
+  // we now have what we really search for ready in 'target'
+  return 0;
+}
+
+/* Semantics:
+   
+- only one backend owns the SOA of a zone
+- only one AXFR per zone at a time - double startTransaction should fail
+- backends need to implement transaction semantics
+
+
+How BindBackend would implement this:
+   startTransaction makes a file 
+   feedRecord sends everything to that file 
+   commitTransaction moves that file atomically over the regular file, and triggers a reload
+   rollbackTransaction removes the file
+
+
+How PostgreSQLBackend would implement this:
+   startTransaction starts a sql transaction, which also deletes all records
+   feedRecord is an insert statement
+   commitTransaction commits the transaction
+   rollbackTransaction aborts it
+
+How MySQLBackend would implement this:
+   (good question!)
+   
+*/     
+
+int PacketHandler::trySuperMaster(DNSPacket *p)
+{
+  Resolver::res_t nsset;
+  try {
+    Resolver resolver;
+    u_int32_t theirserial;
+    int res=resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);  
+    if(res<=0) {
+      L<<Logger::Error<<"Unable to determine SOA serial for "<<p->qdomain<<" at potential supermaster "<<p->getRemote()<<endl;
+      return RCode::ServFail;
+    }
+  
+    resolver.resolve(p->getRemote(),p->qdomain.c_str(), QType::NS);
+
+    nsset=resolver.result();
+  }
+  catch(ResolverException &re) {
+    L<<Logger::Error<<"Error resolving SOA or NS for '"<<p->qdomain<<"' at "<<p->getRemote()<<endl;
+    return RCode::ServFail;
+  }
+
+  string account;
+  DNSBackend *db;
+  if(!B.superMasterBackend(p->getRemote(), p->qdomain, nsset, &account, &db)) {
+   L<<Logger::Error<<"Unable to find backend willing to host "<<p->qdomain<<" for potential supermaster "<<p->getRemote()<<endl;
+    return RCode::Refused;
+  }
+  db->createSlaveDomain(p->getRemote(),p->qdomain,account);
+  Communicator.addSuckRequest(p->qdomain, p->getRemote());  
+  L<<"Created new slave zone '"<<p->qdomain<<"' from supermaster "<<p->getRemote()<<", queued axfr"<<endl;
+  return RCode::NoError;
+}
+
+int PacketHandler::doNotify(DNSPacket *p)
+{
+  /* now what? 
+     was this notification from an approved address?
+     We determine our internal SOA id (via UeberBackend)
+     We determine the SOA at our (known) master
+     if master is higher -> do stuff
+  */
+  if(!arg().mustDo("slave")) {
+    L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from "<<p->getRemote()<<" but slave support is disabled in the configuration"<<endl;
+    return RCode::NotImp;
+  }
+  SOAData sd;
+  sd.serial=0;
+  DNSBackend *db=0;
+  DomainInfo di;
+  if(!B.getDomainInfo(p->qdomain,di) || !(db=di.backend)) {
+    L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from "<<p->getRemote()<<" for which we are not authoritative"<<endl;
+    return trySuperMaster(p);
+  }
+    
+  if(!db->isMaster(p->qdomain, p->getRemote())) {
+    L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from "<<p->getRemote()<<" which is not a master"<<endl;
+    return RCode::Refused;
+  }
+
+  u_int32_t theirserial=0;
+
+  Resolver resolver;
+  int res=resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
+  if(res<=0) {
+    L<<Logger::Error<<"Unable to determine SOA serial for "<<p->qdomain<<" at "<<p->getRemote()<<endl;
+    return RCode::ServFail;
+  }
+       
+  if(theirserial<=sd.serial) {
+    L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from master "<<p->getRemote()<<", we are up to date: "<<
+      theirserial<<"<="<<sd.serial<<endl;
+    return RCode::NoError;
+  }
+  else {
+    L<<Logger::Error<<"Received valid NOTIFY for "<<p->qdomain<<" (id="<<sd.domain_id<<") from master "<<p->getRemote()<<": "<<
+      theirserial<<" > "<<sd.serial<<endl;
+
+    Communicator.addSuckRequest(p->qdomain, p->getRemote());
+  }
+  return -1; 
+}
+
+
+//! Called by the Distributor to ask a question. Returns 0 in case of an error
+DNSPacket *PacketHandler::question(DNSPacket *p)
+{
+  DNSResourceRecord rr;
+  SOAData sd;
+  
+  string subdomain="";
+  string soa;
+  int retargetcount=0;
+  bool noSameLevelNS;
+
+  DNSPacket *r=0;
+  try {    
+    DLOG(L << Logger::Notice<<"Remote "<<inet_ntoa( reinterpret_cast< struct sockaddr_in * >( &( p->remote ))->sin_addr )<<" wants a type " << p->qtype.getName() << " ("<<p->qtype.getCode()<<") about '"<<p->qdomain << "'" << endl);
+
+    if(p->d.qr) { // QR bit from dns packet (thanks RA from N)
+      L<<Logger::Error<<"Received an answer (non-query) packet from "<<p->getRemote()<<", dropping"<<endl;
+      S.inc("corrupt-packets");
+      return 0;
+    }
+
+    // XXX FIXME do this in DNSPacket::parse ?
+
+    if(!p->qdomain.empty() && (p->qdomain[0]=='%' || p->qdomain.find('|')!=string::npos) ) {
+      L<<Logger::Error<<"Received a malformed qdomain from "<<p->getRemote()<<", '"<<p->qdomain<<"': dropping"<<endl;
+      S.inc("corrupt-packets");
+      return 0;
+    }
+    if(p->d.opcode) { // non-zero opcode (again thanks RA!)
+      if(p->d.opcode==Opcode::Update) {
+       if(arg().mustDo("log-failed-updates"))
+         L<<Logger::Notice<<"Received an UPDATE opcode from "<<p->getRemote()<<" for "<<p->qdomain<<", sending NOTIMP"<<endl;
+       r=p->replyPacket(); 
+       r->setRcode(RCode::NotImp); // notimp;
+       return r; 
+      }
+      else if(p->d.opcode==Opcode::Notify) {
+       int res=doNotify(p);
+       if(res>=0) {
+         DNSPacket *r=p->replyPacket();
+         r->setRcode(res);
+         return r;
+       }
+       return 0;
+      }
+      
+      L<<Logger::Error<<"Received an unknown opcode "<<p->d.opcode<<" from "<<p->getRemote()<<" for "<<p->qdomain<<endl;
+
+      r=p->replyPacket(); 
+      r->setRcode(RCode::NotImp); 
+      return r; 
+    }
+    
+    r=p->replyPacket();  // generate an empty reply packet
+    bool found=false;
+    
+    string target=p->qdomain;
+    
+    if (doDNSCheckRequest(p, r, target))
+      goto sendit;
+    
+    if(doVersionRequest(p,r,target)) // catch version.bind requests
+      goto sendit;
+
+    // now we start doing things
+    // if the packet wants to be recursed, and we do recursion (but not lazy recursion!), hand it off
+    if(p->d.rd && !d_doLazyRecursion && d_doRecursion && DP->sendPacket(p)) {
+      // handed off to our recursor friend and forget all about it
+      return 0;   // p will now be deleted, it is safe to answer 0 here
+    }
+    
+    if(p->qclass==255) // any class query 
+      r->setA(false);
+    else if(p->qclass!=1) // we only know about IN, so we don't find anything
+      goto sendit;
+
+  retargeted:;
+    if(retargetcount++>10) {
+      L<<Logger::Error<<"Detected wildcard CNAME loop involving '"<<target<<"'"<<endl;
+      r->setRcode(RCode::ServFail);
+      goto sendit;
+    }
+
+    if(makeCanonic(p,r,target)>0) // traverse CNAME chain until we have a useful record (may actually give the correct answer!)
+      goto sendit; // this might be the end of it (client requested a CNAME, or we found the answer already)
+    
+    if(d_doFancyRecords) { // MBOXFW, URL <- fake records, emulated with MX and A
+      int res=doFancyRecords(p,r,target);
+      if(res) { // had a result
+       if(res<0) // it was an error
+         r->setRcode(RCode::ServFail);
+       goto sendit;  
+      }
+    }
+    
+    // now ready to start the real direct search
+
+    if(p->qtype.getCode()==QType::SOA || p->qtype.getCode()==QType::ANY) { // this is special
+
+      if(B.getSOA(target,sd)) {
+       rr.qname=target;
+       rr.qtype=QType::SOA;
+       rr.content=DNSPacket::serializeSOAData(sd);
+       rr.ttl=sd.ttl;
+       rr.domain_id=sd.domain_id;
+       rr.d_place=DNSResourceRecord::ANSWER;
+       r->addRecord(rr);
+       if(p->qtype.getCode()==QType::SOA) { // we are done
+         goto sendit;
+       }
+      }
+    }
+
+    noSameLevelNS=true;
+
+    if(p->qtype.getCode()!=QType::SOA) { // regular direct lookup
+      B.lookup(QType(QType::ANY), target,p);
+      
+      while(B.get(rr)) {
+       if(rr.qtype.getCode()==QType::SOA) // skip any direct SOA responses as they may be different
+         continue;
+       if(rr.qtype==p->qtype || p->qtype.getCode()==QType::ANY ) {
+         DLOG(L<<"Found a direct answer: "<<rr.content<<endl);
+         found=true;
+         r->addRecord(rr);  // and add
+       }
+       else
+         if(rr.qtype.getCode()==QType::NS)
+           noSameLevelNS=false;
+      }
+      
+      if(p->qtype.getCode()==QType::ANY) {
+       if(d_doFancyRecords) { 
+         int res=findMboxFW(p,r,target);
+         if(res<0)
+           L<<Logger::Error<<"Error finding a mailbox record after an ANY query"<<endl;
+         if(res>0) {
+           DLOG(L<<Logger::Error<<"Frobbed an MX in!"<<endl);
+           found=true;
+         }
+       }
+      }
+
+      if(found) 
+       goto sendit;
+    }
+    
+    // not found yet, try wildcards (we only try here in case of recursion)
+
+    if(p->d.rd && d_doRecursion && d_doLazyRecursion && d_doWildcards) { 
+      int res=doWildcardRecords(p,r,target);
+      if(res) { // had a result
+
+       // FIXME: wildCard may retarget us in the future
+       if(res==1)  // had a straight result
+         goto sendit;  
+       if(res==2)
+         goto retargeted;
+       goto sendit;  
+      }
+    }
+
+    // LAZY RECURSION CUT-OUT! 
+
+    if(p->d.rd && d_doRecursion && d_doLazyRecursion && DP->sendPacket(p)) {
+      delete r;
+      return 0;
+    }
+
+    unsigned int pos;
+    
+    DLOG(L<<"Nothing found so far for '"<<target<<"', do we even have authority over this domain?"<<endl);
+    
+    bool weAuth;
+    int zoneId;
+
+    weAuth=getAuth(p, &sd, target, &zoneId); // TLDAuth perhaps
+    if(weAuth) {
+      DLOG(L<<Logger::Warning<<"Soa found: "<<soa<<endl);
+      ;
+    }
+    
+    if(!weAuth) {
+      if(p->d.rd || target==p->qdomain) { // only servfail if we didn't follow a CNAME
+       if(d_logDNSDetails)
+         L<<Logger::Warning<<"Not authoritative for '"<< target<<"', sending servfail to "<<
+           p->getRemote()<< (p->d.rd ? " (recursion was desired)" : "") <<endl;
+
+       r->setA(false);
+       r->setRcode(RCode::ServFail);  // 'sorry' - this is where we might send out a root referral
+      }
+                                      
+      S.ringAccount("unauth-queries",p->qdomain+"/"+p->qtype.getName());
+      S.ringAccount("remotes-unauth",p->getRemote());
+    }
+    else {
+      DLOG(L<<Logger::Warning<<"We ARE authoritative for a subdomain of '"<<target<<"' ("<<sd.qname<<"), perhaps we have a suitable NS record then"<<endl);
+      subdomain=target;
+      found=0;
+      pos=0; 
+      
+      do {
+       if(pos) // skip dot
+         pos++;
+       
+       subdomain=subdomain.substr(pos);
+       if(noSameLevelNS) { // skip first lookup if it is known not to exist
+         noSameLevelNS=false;
+         continue;
+       }
+         
+       if(!Utility::strcasecmp(subdomain.c_str(),sd.qname.c_str())) // about to break out of our zone
+         break; 
+
+       B.lookup("NS", subdomain,p,zoneId);  // start our search at the backend
+       
+       while(B.get(rr)) {
+         found=true;
+         rr.d_place=DNSResourceRecord::AUTHORITY; // this for the authority section
+         r->addRecord(rr);
+       }
+       if(found || (!subdomain.empty() && subdomain[0]=='.')) {  // this catches '..'
+         r->setA(false);  // send out an NS referral, which should be unauth
+         break;
+       }
+      }while((pos=subdomain.find("."))!=string::npos);
+      
+      if(!found) {
+       // try wildcards then 
+       if(d_doWildcards) { 
+         int res=doWildcardRecords(p,r,target);
+
+         if(res==1)  // had a straight result
+           goto sendit; 
+         if(res==2)
+           goto retargeted;
+       }
+
+       // we have authority but no answer, so we add the SOA for negative caching
+       rr.qname=sd.qname;
+       rr.qtype=QType::SOA;
+       rr.content=DNSPacket::serializeSOAData(sd);
+       rr.ttl=sd.ttl;
+       rr.domain_id=sd.domain_id;
+       rr.d_place=DNSResourceRecord::AUTHORITY;
+       r->addRecord(rr);
+
+
+       // need to send NXDOMAIN if there are 0 records for whatever type for target
+       
+       B.lookup("ANY",target,p);
+       while(B.get(rr))
+         found=true;
+       
+       if(!found) {
+         SOAData sd2;
+         if(B.getSOA(target,sd2)) // is there a SOA perhaps? (which may not appear in an ANY query)
+           found=true;
+       }
+
+       if(!found) { 
+         if(d_logDNSDetails)
+           L<<Logger::Notice<<"Authoritative NXDOMAIN to "<< p->getRemote() <<" for '"<<target<<"' ("<<p->qtype.getName()<<")"<<endl;
+
+         r->setRcode(RCode::NXDomain); 
+         S.ringAccount("nxdomain-queries",p->qdomain+"/"+p->qtype.getName());
+       }
+       else {
+         if(d_logDNSDetails)
+           L<<Logger::Notice<<"Authoritative empty NO ERROR to "<< p->getRemote() <<" for '"<<target<<"' ("<<p->qtype.getName()<<"), other types do exist"<<endl;
+         S.ringAccount("noerror-queries",p->qdomain+"/"+p->qtype.getName());
+       }
+      }
+    }
+    
+    // whatever we've built so far, do additional processing
+    
+  sendit:;
+    bool dangling=false;
+    if(doAdditionalProcessing(p,r, dangling)<0)
+      return 0;
+    
+    /* we were unable to resolve everything, so give it away */
+    if(p->d.rd && dangling && d_doRecursion && d_doLazyRecursion && DP->sendPacket(p)) {
+      delete r;
+      return 0;
+    }
+
+    r->wrapup(); // needed for inserting in cache
+    PC.insert(p,r); // in the packet cache
+  }
+  catch(DBException &e) {
+    L<<Logger::Error<<"Database module reported condition which prevented lookup - sending out servfail"<<endl;
+    r->setRcode(RCode::ServFail);
+    S.inc("servfail-packets");
+    S.ringAccount("servfail-queries",p->qdomain);
+  }
+  return r; 
+
+}
+
diff --git a/pdns/packethandler.hh b/pdns/packethandler.hh
new file mode 100644 (file)
index 0000000..1146ce9
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PACKETHANDLER_HH
+#define PACKETHANDLER_HH
+\r
+#ifndef WIN32\r
+# include <sys/socket.h>\r
+# include <netinet/in.h>\r
+# include <arpa/inet.h>\r
+#endif // WIN32\r
+\r
+#include "ueberbackend.hh"
+#include "dnspacket.hh"
+#include "packetcache.hh"
+
+using namespace std;
+
+/** Central DNS logic according to RFC1034. Ask this class a question in the form of a DNSPacket
+    and it will return, synchronously, a DNSPacket answer, suitable for 
+    sending out over the network. 
+
+    The PacketHandler gives your question to the PacketCache for possible inclusion
+    in the cache.
+
+    In order to do so, the PacketHandler contains a reference to the global extern PacketCache PC
+
+    It also contains an UeberBackend instance for answering the subqueries needed to generate
+    a complete reply.
+
+*/
+
+class PacketHandler
+{
+public:
+  template<class T> class Guard
+  {
+  public:
+    Guard(T **guard)
+    {
+      d_guard=guard;
+    }
+    
+    ~Guard()
+    {
+      if(*d_guard)
+       delete *d_guard;
+    }
+    
+  private:
+    T **d_guard;
+  };
+
+
+  DNSPacket *question(DNSPacket *); //!< hand us a DNS packet with a question, we give you an answer
+  PacketHandler(); 
+  ~PacketHandler(); // defined in packethandler.cc, and does --count
+  static int numRunning(){return s_count;}; //!< Returns the number of running PacketHandlers
+  void soaMagic(DNSResourceRecord *rr);
+  DNSBackend *getBackend();
+  class DBException{};
+
+private:
+  int doNotify(DNSPacket *);
+  int PacketHandler::trySuperMaster(DNSPacket *p);
+  int makeCanonic(DNSPacket *p, DNSPacket *r, string &target);
+  int doWildcardRecords(DNSPacket *p, DNSPacket *r, string &target);
+  int findMboxFW(DNSPacket *p, DNSPacket *r, string &target);
+  int findUrl(DNSPacket *p, DNSPacket *r, string &target);
+  int doFancyRecords(DNSPacket *p, DNSPacket *r, string &target);
+  int doDNSCheckRequest(DNSPacket *p, DNSPacket *r, string &target);
+  int doVersionRequest(DNSPacket *p, DNSPacket *r, string &target);
+  bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);
+  bool getTLDAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);
+  int doAdditionalProcessing(DNSPacket *p, DNSPacket *r, bool &dangling);
+
+  
+  static int s_count;
+  bool d_doFancyRecords;
+  bool d_doRecursion;
+  bool d_doLazyRecursion;
+  bool d_doWildcards;
+  bool d_doCNAME;
+  bool d_logDNSDetails;
+
+  UeberBackend B; // every thread an own instance
+};
+
+#endif /* PACKETHANDLER */
diff --git a/pdns/pathconfig b/pdns/pathconfig
new file mode 100644 (file)
index 0000000..6060da3
--- /dev/null
@@ -0,0 +1,8 @@
+INITDPATH=/etc/init.d
+BINARYPATH=/usr/sbin
+CONFIGPATH=/etc/powerdns
+SOCKETPATH=/var/run/
+DOCPATH=/usr/doc/pdns
+LIBRARYPATH=/usr/lib/powerdns
+PDNSUID=pdns
+PDNSGID=pdns
diff --git a/pdns/pathconfig.bsd b/pdns/pathconfig.bsd
new file mode 100644 (file)
index 0000000..bc53a2a
--- /dev/null
@@ -0,0 +1,8 @@
+INITDPATH=/usr/local/etc/rc.d/
+BINARYPATH=/usr/local/sbin
+CONFIGPATH=/usr/local/etc/powerdns
+SOCKETPATH=/var/run/
+DOCPATH=/usr/local/share/doc/powerdns
+LIBRARYPATH=/usr/local/lib/powerdns
+PDNSUID=pdns
+PDNSGID=pdns
diff --git a/pdns/pathconfig.debian b/pdns/pathconfig.debian
new file mode 100644 (file)
index 0000000..2beaa25
--- /dev/null
@@ -0,0 +1,8 @@
+INITDPATH=/etc/init.d
+BINARYPATH=/usr/sbin
+CONFIGPATH=/etc/powerdns
+SOCKETPATH=/var/run/
+DOCPATH=""
+LIBRARYPATH=/usr/lib/powerdns
+PDNSUID=pdns
+PDNSGID=pdns
diff --git a/pdns/pathconfig.redhat b/pdns/pathconfig.redhat
new file mode 100644 (file)
index 0000000..6060da3
--- /dev/null
@@ -0,0 +1,8 @@
+INITDPATH=/etc/init.d
+BINARYPATH=/usr/sbin
+CONFIGPATH=/etc/powerdns
+SOCKETPATH=/var/run/
+DOCPATH=/usr/doc/pdns
+LIBRARYPATH=/usr/lib/powerdns
+PDNSUID=pdns
+PDNSGID=pdns
diff --git a/pdns/pdns.conf-dist b/pdns/pdns.conf-dist
new file mode 100644 (file)
index 0000000..ed0c9ee
--- /dev/null
@@ -0,0 +1,26 @@
+# Generated automatically from pdns.conf-dist.in by configure.
+
+#  cache-ttl=...
+#      Seconds to store packets in the PacketCache
+#  default-soa-name=...
+#      name to insert in the SOA record if none set in the backend
+#  distributor-threads=...
+#      Default number of Distributor (backend) threads to start
+#  fancy-records=...
+#      Process URL and MBOXFW records
+#  help=...
+#      Provide a helpful message
+#  localaddress=...
+#      Local IP address to which we bind
+#  localport=...
+#      The port on which we listen
+#  loglevel=...
+#      Amount of logging. Higher is more. Do not set below 3
+#  out-of-zone-additional-processing | out-of-zone-additional-processing=yes | out-of-zone-additional-processing=no
+#      Do out of zone additional processing
+#  smtpredirector=...
+#      Our smtpredir MX host
+#  urlredirector=...
+#      Where we send hosts to that need to be url redirected
+#  wildcards=...
+#      Honor wildcards in the database
diff --git a/pdns/pdns.conf-dist.in b/pdns/pdns.conf-dist.in
new file mode 100644 (file)
index 0000000..2ff3a4e
--- /dev/null
@@ -0,0 +1,26 @@
+# @configure_input@
+
+#  cache-ttl=...
+#      Seconds to store packets in the PacketCache
+#  default-soa-name=...
+#      name to insert in the SOA record if none set in the backend
+#  distributor-threads=...
+#      Default number of Distributor (backend) threads to start
+#  fancy-records=...
+#      Process URL and MBOXFW records
+#  help=...
+#      Provide a helpful message
+#  localaddress=...
+#      Local IP address to which we bind
+#  localport=...
+#      The port on which we listen
+#  loglevel=...
+#      Amount of logging. Higher is more. Do not set below 3
+#  out-of-zone-additional-processing | out-of-zone-additional-processing=yes | out-of-zone-additional-processing=no
+#      Do out of zone additional processing
+#  smtpredirector=...
+#      Our smtpredir MX host
+#  urlredirector=...
+#      Where we send hosts to that need to be url redirected
+#  wildcards=...
+#      Honor wildcards in the database
diff --git a/pdns/pdns.in b/pdns/pdns.in
new file mode 100755 (executable)
index 0000000..c0bd7fa
--- /dev/null
@@ -0,0 +1,167 @@
+# chkconfig: - 80 75
+# description: PDNS is a versatile high performance authoritative nameserver
+
+cd $SOCKETPATH
+suffix=`basename $0 | awk -F- '{print $2}'`
+if [ $suffix ] 
+then
+       EXTRAOPTS=--config-name=$suffix
+       PROGNAME=pdns-$suffix
+else
+       PROGNAME=pdns
+fi
+
+pdns_server="$BINARYPATH/pdns_server $EXTRAOPTS"
+
+doPC()
+{
+       ret=$($BINARYPATH/pdns_control $EXTRAOPTS $1 $2 2> /dev/null)
+}
+
+
+if [ "$1" != "mrtg" -a "$1" != "cricket" ] 
+then
+       echo -n "$PROGNAME: "
+fi
+
+doPC ping
+NOTRUNNING=$?
+
+case "$1" in
+       status)
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC status
+                       echo $ret
+               else
+                       echo "not running"
+               fi 
+       ;;      
+
+       stop)
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC quit
+                       echo $ret
+               else
+                       echo "not running"
+               fi 
+       ;;              
+
+       force-stop)
+               killall -v -9 pdns_server
+       ;;
+
+       start)
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       echo "already running"
+               else
+                       $pdns_server --daemon --guardian=yes
+                       if test "$?" = "0"
+                       then
+                               echo "started"  
+                       fi
+               fi 
+       ;;              
+
+       force-reload | restart)
+               echo -n stopping and waiting
+               doPC quit
+               sleep 3
+               echo 
+               $0 start
+       ;;
+
+       reload) 
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC cycle
+                       echo requested reload
+               else
+                       echo not running yet
+                       $0 start
+               fi 
+       ;;              
+               
+       monitor)
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       echo "already running"
+               else
+                       $pdns_server --daemon=no --guardian=no --control-console --loglevel=9
+               fi 
+       ;;              
+
+       dump)
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC list
+                       echo $ret
+               else
+                       echo "not running"
+               fi 
+       ;;              
+
+       show)
+               if [ $# -lt 2 ]
+               then
+                       echo Insufficient parameters
+                       exit
+               fi 
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       echo -n "$2="
+                       doPC show $2 ; echo $ret
+               else
+                       echo "not running"
+               fi 
+       ;;              
+
+       mrtg)
+               if [ $# -lt 2 ]
+               then
+                       echo Insufficient parameters
+                       exit
+               fi 
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC show $2 ; echo $ret
+                       if [ "$3x" != "x" ]
+                       then
+                               doPC show $3 ; echo $ret
+                       else
+                               echo 0
+                       fi
+                       doPC uptime ; echo $ret
+                       echo PowerDNS daemon
+               else
+                       echo "not running"
+               fi 
+       
+       ;;              
+
+       cricket)
+               if [ $# -lt 2 ]
+               then
+                       echo Insufficient parameters
+                       exit
+               fi 
+               if test "$NOTRUNNING" = "0" 
+               then 
+                       doPC show $2 ; echo $ret
+               else
+                       echo "not running"
+               fi 
+       
+       ;;              
+
+
+
+       *)
+       echo pdns [start\|stop\|restart\|status\|dump\|show\|mrtg]
+
+       ;;
+esac
+
+
diff --git a/pdns/pdns.spec b/pdns/pdns.spec
new file mode 100644 (file)
index 0000000..474cd39
--- /dev/null
@@ -0,0 +1,39 @@
+Buildroot: /tmp/pdns
+Name: pdns
+Version: 2.8
+Release: 1
+Summary: extremely powerful and versatile nameserver
+Copyright: see /usr/doc/pdns/copyright
+Distribution: Neutral
+Vendor: PowerDNS.COM BV
+Group: System/DNS
+AutoReqProv: no
+
+%define _rpmdir ../
+%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
+
+%description
+PowerDNS is a versatile nameserver which supports a large number
+of different backends ranging from simple zonefiles to relational
+databases and load balancing/failover algorithms.
+
+This RPM is statically compiled and should work on all Linux distributions.
+It comes with support for MySQL, PostgreSQL, Bind zonefiles and the 'pipe
+backend'.
+
+%files
+%defattr(-,root,root)
+"/usr/sbin/pdns_server"
+"/usr/sbin/pdns_control"
+"/usr/sbin/zone2sql"
+"/usr/doc/pdns/LICENSE"
+"/usr/doc/pdns/README"
+"/usr/doc/pdns/html/"
+"/usr/doc/pdns/pdns.txt"
+"/usr/doc/pdns/pdns.pdf"
+%dir "/etc/powerdns/"
+%config(noreplace) "/etc/powerdns/pdns.conf"
+%config "/etc/init.d/pdns"
+
+%post
+echo Remember to create a 'pdns' user before starting pdns
diff --git a/pdns/qtype.cc b/pdns/qtype.cc
new file mode 100644 (file)
index 0000000..931eee7
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include <iostream>
+#include <string>
+#include <vector>
+#include <utility>
+#include <sstream>
+#include "qtype.hh"
+#include "misc.hh"
+
+bool QType::uninit=true;
+vector<QType::namenum> QType::names;
+
+void QType::insert(char *p, int n)
+{
+  names.push_back(make_pair(string(p),n));
+}
+\r
+
+QType::QType()
+{
+  if(uninit)
+    {
+      uninit=false;
+      insert("A",1);
+      insert("NS",2);
+      insert("CNAME",5);
+      insert("SOA",6);
+      insert("PTR",12);
+      insert("HINFO",13);
+      insert("MX",15);
+      insert("TXT",16);
+      insert("RP",17);
+      insert("SRV",33);
+      insert("A6",38);
+      insert("AAAA",28);
+      insert("NAPTR",35);
+      insert("AXFR",252);
+      insert("ANY",255);
+      insert("URL",256);
+      insert("MBOXFW",257);
+      insert("CURL",258);
+    }
+}
+
+int QType::getCode() const
+{
+  return code;
+}
+
+string QType::getName() const
+{\r
+  vector<namenum>::iterator pos;
+  for(pos=names.begin();pos<names.end();++pos)
+    if(pos->second==code)
+      return pos->first;
+
+  return "#"+itoa(code);
+}
+
+QType &QType::operator=(int n)
+{
+  code=n;
+  return *this;
+}
+
+int QType::chartocode(const char *p)
+{
+  vector<namenum>::iterator pos;
+  for(pos=names.begin();pos<names.end();++pos)
+    if(pos->first==p)
+      return pos->second;
+
+  return 0;
+}
+
+QType &QType::operator=(const char *p)
+{
+  code=chartocode(p);
+  return *this;
+}
+
+bool QType::operator==(const QType &comp) const
+{
+  return(comp.code==code);
+}
+
+QType &QType::operator=(const string &s)
+{
+  code=chartocode(s.c_str());
+  return *this;
+}
+
+
+QType::QType(int n)
+{
+  QType();
+  code=n;
+}
+
+QType::QType(char *p)
+{
+  QType();
+  code=chartocode(p);
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+  QType t;
+
+  cout << endl;
+  cout << "Assiging a '6'" << endl;
+  t=6;
+  cout << "Code is now " << t.getCode() << endl;
+  cout << "Name is now " << t.getName() << endl;
+
+  cout << endl;
+
+  cout << "Assiging a 'CNAME'" << endl;
+  t="CNAME";
+  cout << "Code is now " << t.getCode() << endl;
+  cout << "Name is now " << t.getName() << endl;
+
+  QType u;
+  u="SOA";
+  cout << u.getCode() << endl;
+
+
+}
+#endif
diff --git a/pdns/qtype.hh b/pdns/qtype.hh
new file mode 100644 (file)
index 0000000..bfdffb5
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef QTYPE_HH
+#define QTYPE_HH
+/* (C) 2002 POWERDNS.COM BV */
+// $Id: qtype.hh,v 1.1 2002/11/27 15:18:32 ahu Exp $
+#include <string>
+#include <vector>
+#include <utility>
+
+using namespace std;
+
+/** The QType class is meant to deal easily with the different kind of resource types, like 'A', 'NS',
+ *  'CNAME' etcetera. These types have both a name and a number. This class can seemlessly move between
+ *   them. Use it like this:
+
+\code
+   QType t;
+   t="CNAME";
+   cout<<t.getCode()<<endl; // prints '5'
+   t=6;
+   cout<<t.getName()<<endl; // prints 'SOA'
+\endcode
+
+*/
+
+
+
+class QType
+{
+public:
+  QType(); //!< Naked constructor
+  explicit QType(int); //!< convert from an integer to a QType
+  QType(char *p);  //!< convert from a char* to a QType\r
+
+  QType &operator=(int);  //!< Assigns integers to us
+  QType &operator=(const char *); //!< Assings strings to us
+  QType &operator=(const string &); //!< Assings strings to us
+  bool operator==(const QType &) const; //!< equality operator
+
+  string getName() const; //!< Get a string representation of this type
+  int getCode() const; //!< Get the integer representation of this type
+
+  static int chartocode(const char *p); //!< convert a character string to a code
+  
+  enum {A=1,NS=2,CNAME=5,SOA=6,PTR=12,MX=15,TXT=16,AAAA=28,NAPTR=35,AXFR=252, ANY=255} types;
+private:
+  short int code;
+  typedef pair<string,int> namenum; 
+  void insert(char *p, int n);
+
+  static vector<namenum> names;
+  static bool uninit;
+};
+
+
+#endif
diff --git a/pdns/randombackend.cc b/pdns/randombackend.cc
new file mode 100644 (file)
index 0000000..2643281
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "dnsbackend.hh"
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "dnspacket.hh"
+#include "ahuexception.hh"
+#include "logger.hh"
+
+/* FIRST PART */
+class RandomBackend : public DNSBackend
+{
+public:
+  RandomBackend(const string &suffix="") 
+  {
+    setArgPrefix("random"+suffix);
+    d_ourname=getArg("hostname");
+  }
+
+  bool list(int id) {
+    return false; // we don't support AXFR
+  }
+    
+  void lookup(const QType &type, const string &qdomain, DNSPacket *p, int zoneId)
+  {
+    if((type.getCode()!=QType::ANY && type.getCode()!=QType::A) || qdomain!=d_ourname)  // we only know about random.powerdns.com A
+      d_answer="";                                                  // no answer
+    else {
+      ostringstream os;
+      os<<Utility::random()%256<<"."<<Utility::random()%256<<"."<<Utility::random()%256<<"."<<Utility::random()%256;
+      d_answer=os.str();                                           // our random ip address
+    }
+
+  }
+
+  bool get(DNSResourceRecord &rr)
+  {
+    if(!d_answer.empty()) {
+      rr.qname=d_ourname;                                           // fill in details
+      rr.qtype=QType::A;                                            // A record
+      rr.ttl=5;                                                 // 5 seconds
+      rr.content=d_answer;
+
+      d_answer="";                                                  // this was the last answer
+      
+      return true;
+    }
+    return false;                                                   // no more data
+  }
+  
+private:
+  string d_answer;
+  string d_ourname;
+};
+
+/* SECOND PART */
+
+class RandomFactory : public BackendFactory
+{
+public:
+  RandomFactory() : BackendFactory("random") {}
+  void declareArguments(const string &suffix="")
+  {
+    declare(suffix,"hostname","Hostname which is to be random","random.example.com");
+  }
+  DNSBackend *make(const string &suffix="")
+  {
+    return new RandomBackend(suffix);
+  }
+};
+
+/* THIRD PART */
+
+class RandomLoader
+{
+public:
+  RandomLoader()
+  {
+    BackendMakers().report(new RandomFactory);
+    
+    L<<Logger::Info<<" [RandomBackend] This is the randombackend version "VERSION" ("__DATE__", "__TIME__") reporting"<<endl;
+  }  
+};
+
+static RandomLoader randomLoader;
+
diff --git a/pdns/receiver.cc b/pdns/receiver.cc
new file mode 100644 (file)
index 0000000..6f73256
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: receiver.cc,v 1.1 2002/11/27 15:18:32 ahu Exp $
+#include <cstdio>
+#include <signal.h>
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <iostream>
+#include <string>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <fstream>
+
+#include "config.h"
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "ueberbackend.hh"
+#include "dnspacket.hh"
+#include "nameserver.hh"
+#include "distributor.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "packethandler.hh"
+#include "statbag.hh"
+#include "tcpreceiver.hh"
+#include "packetcache.hh"
+#include "ws.hh"
+#include "misc.hh"
+#include "dynlistener.hh"
+#include "dynhandler.hh"
+#include "communicator.hh"
+#include "dnsproxy.hh"
+#include "utility.hh"\r
+#include "common_startup.hh"
+
+time_t s_starttime;
+
+string s_programname="pdns"; // used in packethandler.cc
+
+char *funnytext=
+"*****************************************************************************\n"\
+"Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\
+"Well, you found one. \n"\
+"Two ions are flying through their particle accelerator, says the one to the\n"
+"other 'I think I've lost an electron!' \n"\
+"So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\
+"                                            the pdns crew - pdns@powerdns.com\n"
+"*****************************************************************************\n";
+
+
+// start (sys)logging
+
+/** \var Logger L 
+\brief All logging is done via L, a Logger instance
+*/
+
+
+/**
+\file receiver.cc
+\brief The main loop of powerdns 
+
+This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread()
+*/
+
+void daemonize(void)
+{
+  if(fork())
+    exit(0); // bye bye
+  
+  setsid(); 
+
+  // cleanup open fds, but skip sockets 
+  close(0);
+  close(1);
+  close(2);
+
+}
+
+
+static int cpid;
+
+static void takedown(int i)
+{
+  if(cpid) {
+    L<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl;
+    kill(cpid,SIGKILL);
+    exit(1);
+  }
+}
+
+static void writePid(void)
+{
+  string fname=arg()["socket-dir"]+"/"+s_programname+".pid";
+  ofstream of(fname.c_str());
+  if(of)
+    of<<getpid()<<endl;
+  else
+    L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
+}
+
+int d_fd1[2], d_fd2[2];
+FILE *d_fp;
+
+static string DLRestHandler(const vector<string>&parts, pid_t ppid)
+{
+  string line;
+  
+  for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
+    if(i!=parts.begin())
+      line.append(1,' ');
+    line.append(*i);
+  }
+  line.append(1,'\n');
+  
+  write(d_fd1[1],line.c_str(),line.size()+1);
+  char mesg[512];
+  fgets(mesg,sizeof(mesg),d_fp);
+  line=mesg;
+  chomp(line,"\n");
+  return line;
+}
+
+static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
+{
+  kill(cpid,SIGKILL);
+  return "ok";
+}
+
+static int guardian(int argc, char **argv)
+{
+  if(isGuarded(argv))
+    return 0;
+
+  int infd=0, outfd=1;
+
+  DynListener dlg(s_programname);
+  dlg.registerFunc("QUIT",&DLQuitHandler);
+  dlg.registerFunc("CYCLE",&DLCycleHandler);
+  dlg.registerFunc("PING",&DLPingHandler);
+  dlg.registerFunc("STATUS",&DLStatusHandler);
+  dlg.registerRestFunc(&DLRestHandler);
+  dlg.go();
+  string progname=argv[0];
+
+  bool first=true;
+  cpid=0;
+
+  for(;;) {
+    int pid;
+    setStatus("Launching child");
+
+    if(pipe(d_fd1)<0 || pipe(d_fd2)<0) {
+      L<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl;
+      exit(1);
+    }
+
+    if(!(pid=fork())) { // child
+      signal(SIGTERM, SIG_DFL);
+
+      signal(SIGHUP, SIG_DFL);
+      signal(SIGUSR1, SIG_DFL);
+      signal(SIGUSR2, SIG_DFL);
+
+      char **const newargv=new char*[argc+2];
+      int n;
+
+      if(arg()["config-name"]!="") {
+       progname+="-"+arg()["config-name"];
+       L<<Logger::Error<<"Virtual configuration name: "<<arg()["config-name"]<<endl;
+      }
+
+      newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
+      for(n=1;n<argc;n++) {
+       newargv[n]=argv[n];
+      }
+      newargv[n]=0;
+      
+      L<<Logger::Error<<"Guardian is launching an instance"<<endl;
+      close(d_fd1[1]);
+      close(d_fd2[0]);
+
+      if(d_fd1[0]!= infd) {
+       dup2(d_fd1[0], infd);
+       close(d_fd1[0]);
+      }
+
+      if(d_fd2[1]!= outfd) {
+       dup2(d_fd2[1], outfd);
+       close(d_fd2[1]);
+      }
+      if(execv(argv[0], newargv)<0) {
+       L<<Logger::Error<<"Unable to execv '"<<argv[0]<<"': "<<strerror(errno)<<endl;
+       char **p=newargv;
+       while(*p)
+         L<<Logger::Error<<*p++<<endl;
+
+       exit(1);
+      }
+      L<<Logger::Error<<"execve returned!!"<<endl;
+      // never reached
+    }
+    else if(pid>0) { // parent
+      close(d_fd1[0]);
+      close(d_fd2[1]);
+      if(!(d_fp=fdopen(d_fd2[0],"r"))) {
+       L<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
+       exit(1);
+      }
+      setbuf(d_fp,0); // no buffering please, confuses select
+
+      if(first) {
+       first=false;
+       signal(SIGTERM, takedown);
+
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGUSR1, SIG_IGN);
+       signal(SIGUSR2, SIG_IGN);
+
+       writePid();
+      }
+
+      int status;
+      cpid=pid;
+      for(;;) {
+       int ret=waitpid(pid,&status,WNOHANG);
+
+       if(ret<0) {
+         L<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
+         L<<Logger::Error<<"Dying"<<endl;
+         exit(1);
+       }
+       else if(ret) // something exited
+         break;
+       else { // child is alive
+         // execute some kind of ping here 
+         if(DLQuitPlease())
+           takedown(1);
+         setStatus("Child running on pid "+itoa(pid));
+         sleep(1);
+       }
+      }
+      close(d_fd1[1]);
+      fclose(d_fp);
+
+      if(WIFEXITED(status)) {
+       int ret=WEXITSTATUS(status);
+
+       if(ret==99) {
+         L<<Logger::Error<<"Child requested a stop, exiting"<<endl;
+         exit(1);
+       }
+       setStatus("Child died with code "+itoa(ret));
+       L<<Logger::Error<<"Our pdns instance exited with code "<<ret<<endl;
+       L<<Logger::Error<<"Respawning"<<endl;
+
+       sleep(1);
+       continue;
+      }
+      if(WIFSIGNALED(status)) {
+       int sig=WTERMSIG(status);
+       setStatus("Child died because of signal "+itoa(sig));
+       L<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
+#ifdef WCOREDUMP
+       if(WCOREDUMP(status)) 
+         L<<Logger::Error<<"Dumped core"<<endl;
+#endif
+
+       L<<Logger::Error<<"Respawning"<<endl;
+       sleep(1);
+       continue;
+      }
+      L<<Logger::Error<<"No clue what happened! Respawning"<<endl;
+    }
+    else {
+      L<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
+      exit(1);
+    }
+  }
+}
+
+static void UNIX_declareArguments()
+{
+  static char pietje[128]="!@@SYSCONFDIR@@:";
+  arg().set("config-dir","Location of configuration directory (pdns.conf)")=
+    strcmp(pietje+1,"@@SYSCONFDIR@@:") ? pietje+strlen("@@SYSCONFDIR@@:")+1 : SYSCONFDIR;
+  
+  arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
+  arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
+  arg().set("module-dir","Default directory for modules")=BINDIR+string("/../lib");
+  arg().set("chroot","If set, chroot to this directory for more security")="";
+  arg().set("setuid","If set, change user id to this uid for more security")="";
+  arg().set("setgid","If set, change group id to this gid for more security")="";
+  arg().set("logging-facility","Log under a specific facility")="";
+  arg().set("daemon","Operate as a daemon")="no";
+
+}
+
+static void loadModules()
+{
+  if(!arg()["load-modules"].empty()) { 
+    vector<string>modules;
+    
+    stringtok(modules,arg()["load-modules"],",");
+    
+    for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) {
+      bool res;
+      const string &module=*i;
+      
+      if(module.find(".")==string::npos)
+       res=UeberBackend::loadmodule(arg()["module-dir"]+"/lib"+module+"backend.so");
+      else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.'))    // absolute or current path
+       res=UeberBackend::loadmodule(module);
+      else
+       res=UeberBackend::loadmodule(arg()["module-dir"]+"/"+module);
+      
+      if(res==false) {
+       L<<Logger::Error<<"Unable to load module "<<module<<endl;
+       exit(1);
+      }
+    }
+  }
+}
+
+
+
+#ifdef __linux__
+#include <execinfo.h>
+static void tbhandler(int num)
+{
+  L<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
+  void *array[20]; //only care about last 17 functions (3 taken with tracing support)
+  size_t size;
+  char **strings;
+  size_t i;
+  
+  size = backtrace (array, 20);
+  strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
+  
+  for (i = 0; i < size; i++) //skip useless functions
+    L<<Logger::Error<<strings[i]<<endl;
+  
+  
+  signal(SIGABRT, SIG_DFL);
+  abort();//hopefully will give core
+
+}
+#endif
+
+//! The main function of pdns, the pdns process
+int main(int argc, char **argv)
+{ 
+  s_programname="pdns";
+  s_starttime=time(0);
+
+#ifdef __linux__
+  signal(SIGSEGV,tbhandler);
+  signal(SIGFPE,tbhandler);
+  signal(SIGABRT,tbhandler);
+  signal(SIGILL,tbhandler);
+#endif
+
+
+  L.toConsole(Logger::Warning);
+  try {
+    declareArguments();
+    UNIX_declareArguments();
+      
+    arg().laxParse(argc,argv); // do a lax parse
+    
+    if(arg()["config-name"]!="") 
+      s_programname+="-"+arg()["config-name"];
+    
+    (void)theL(s_programname);
+    
+    string configname=arg()["config-dir"]+"/"+s_programname+".conf";
+    cleanSlashes(configname);
+
+    if(!arg().mustDo("config") && !arg().mustDo("no-config")) // "config" == print a configuration file
+      arg().laxFile(configname.c_str());
+    
+    arg().laxParse(argc,argv); // reparse so the commandline still wins
+    if(!arg()["logging-facility"].empty()) {
+      int facility=arg().asNum("logging-facility");
+      switch(facility) {
+      case 0:
+       theL().setFacility(LOG_LOCAL0);
+       break;
+      case 1:
+       theL().setFacility(LOG_LOCAL1);
+       break;
+      case 2:
+       theL().setFacility(LOG_LOCAL2);
+       break;
+      case 3:
+       theL().setFacility(LOG_LOCAL3);
+       break;
+      case 4:
+       theL().setFacility(LOG_LOCAL4);
+       break;
+      case 5:
+       theL().setFacility(LOG_LOCAL5);
+       break;
+      case 6:
+       theL().setFacility(LOG_LOCAL6);
+       break;
+      case 7:
+       theL().setFacility(LOG_LOCAL7);
+       break;
+      default:
+       L<<Logger::Error<<"Unknown logging facility level"<<facility<<endl;
+       break;
+      }
+    }
+
+    L.toConsole((Logger::Urgency)(arg().asNum("loglevel")));  
+
+    if(arg().mustDo("help") || arg().mustDo("config")) {
+      arg().set("daemon")="no";
+      arg().set("guardian")="no";
+    }
+
+    if(arg().mustDo("guardian") && !isGuarded(argv)) {
+      if(arg().mustDo("daemon")) {
+       L.toConsole(Logger::Critical);
+       daemonize();
+      }
+      guardian(argc, argv);  
+      // never get here, guardian will reinvoke process
+      cerr<<"Um, we did get here!"<<endl;
+    }
+    
+    // we really need to do work - either standalone or as an instance
+    
+    loadModules();
+    BackendMakers().launch(arg()["launch"]); // vrooooom!
+      
+    if(arg().mustDo("help")) {
+      cerr<<"syntax:"<<endl<<endl;
+      cerr<<arg().helpstring(arg()["help"])<<endl;
+      exit(99);
+    }
+    
+    if(arg().mustDo("config")) {
+      cout<<arg().configstring()<<endl;
+      exit(99);
+    }
+
+    if(arg().mustDo("list-modules")) {
+      vector<string>modules=BackendMakers().getModules();
+      cerr<<"Modules available:"<<endl;
+      for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i)
+       cout<<*i<<endl;
+
+      exit(99);
+    }
+    if(!BackendMakers().numLauncheable()) {
+      L<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
+       exit(99); // this isn't going to fix itself either
+    }    
+    if(arg().mustDo("daemon")) {
+      L.toConsole(Logger::None);
+      if(!isGuarded(argv))
+       daemonize();
+    }
+
+    if(isGuarded(argv)) {
+      L<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
+      dl=new DynListener; // listens on stdin 
+    }
+    else {
+      L<<Logger::Warning<<"This is a standalone pdns"<<endl; 
+      
+      if(arg().mustDo("control-console"))
+       dl=new DynListener();
+      else
+       dl=new DynListener(s_programname);
+      
+      writePid();
+    }
+    dl->registerFunc("SHOW",&DLShowHandler);
+    dl->registerFunc("RPING",&DLPingHandler);
+    dl->registerFunc("QUIT",&DLRQuitHandler);
+    dl->registerFunc("UPTIME",&DLUptimeHandler);
+    dl->registerFunc("NOTIFY-HOST",&DLNotifyHostHandler);
+    dl->registerFunc("NOTIFY",&DLNotifyHandler);
+    dl->registerFunc("RELOAD",&DLReloadHandler);
+    dl->registerFunc("REDISCOVER",&DLRediscoverHandler);
+    dl->registerFunc("VERSION",&DLVersionHandler);
+    dl->registerFunc("PURGE",&DLPurgeHandler);
+    dl->registerFunc("CCOUNTS",&DLCCHandler);
+    dl->registerFunc("SET",&DLSettingsHandler);
+
+    
+    // reparse, with error checking
+    if(!arg().mustDo("no-config"))
+      arg().file(configname.c_str());
+    arg().parse(argc,argv);
+    UeberBackend::go();
+    N=new UDPNameserver; // this fails when we are not root, throws exception
+    
+    if(!arg().mustDo("disable-tcp"))
+      TN=new TCPNameserver; 
+  }
+  catch(const ArgException &A) {
+    L<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
+    exit(1);
+  }
+  
+  declareStats();
+  DLOG(L<<Logger::Warning<<"Verbose logging in effect"<<endl);
+  
+  L<<Logger::Warning<<"PowerDNS "<<VERSION<<" (C) 2002 PowerDNS.COM BV ("<<__DATE__", "__TIME__<<") starting up"<<endl;
+
+  L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
+    "This is free software, and you are welcome to redistribute it "
+    "according to the terms of the GPL version 2."<<endl;
+
+
+  try {
+
+    mainthread();
+  }
+  catch(AhuException &AE) {
+    if(!arg().mustDo("daemon"))
+      cerr<<"Exiting because: "<<AE.reason<<endl;
+    L<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
+  }      
+  catch(exception &e) {
+    if(!arg().mustDo("daemon"))
+      cerr<<"Exiting because of STL error: "<<e.what()<<endl;
+    L<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
+  }
+  catch(...) {
+    cerr<<"Uncaught exception of unknown type - sorry"<<endl;
+  }
+
+  exit(1);
+  
+}
+
+
diff --git a/pdns/release-scripts/ld b/pdns/release-scripts/ld
new file mode 100644 (file)
index 0000000..026cbe1
--- /dev/null
@@ -0,0 +1 @@
+-ldl -L/opt/oracle/lib -ldl -lclient8  -ldl -lclntst8
diff --git a/pdns/release-scripts/make-freebsd-static b/pdns/release-scripts/make-freebsd-static
new file mode 100644 (file)
index 0000000..ef236a0
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/local/bin/gmake -f
+
+all: compile package
+
+compile:  compilation
+
+precompile:
+       gmake clean
+       gmake -k distclean
+       ./bootstrap
+       ./configure --enable-static-binaries
+       cd ../pdns-pipebackend ;        gmake clean;    gmake
+       cd ../ahudns-mysqlbackend ; gmake clean ;       gmake
+       cd ../pdns-gpgsqlbackend; gmake clean  ;        gmake
+       cd ../pdns-gmysqlbackend; gmake clean  ;        gmake
+       # cd backends/bind ; gmake
+
+extras:  precompile
+       -rm extra/*.o
+       cd extra ; ln -s ../backends/bind/bindbackend.o .
+       cd extra ; ln -s ../backends/bind/zoneparser2.o .
+       cd extra ; ln -s ../backends/bind/bindparser.o .
+       cd extra ; ln -s ../backends/bind/bindlexer.o .
+       cd extra ; ln -s ../backends/bind/huffman.o .
+       cd extra ; ln -s ../../pdns-pipebackend/*.o .
+       cd extra; ln -s ../../ahudns-mysqlbackend/*.o .
+       cd extra; ln -s ../../pdns-gpgsqlbackend/*.o .
+       cd extra; ln -s ../../pdns-gmysqlbackend/*.o .
+       echo "-L/usr/local/lib -lz -L/usr/local/lib/mysql -lmysqlclient -lz -lpq++ -lpq -lssl -lcrypt -lcrypto" > extra/ld
+       -rm libs/*
+
+compilation: extras
+       gmake 
+       gmake mkbindist
+
+
+package:
+       mkdir -p release-files/freebsd-static
+       cp backends/bind/zone2sql .
+       
+       -rm pdns*tar.gz
+       cp pathconfig.bsd pathconfig
+       . ./mkbindist
+       mv pdns*tar.gz release-files/freebsd-static
+                       
+
diff --git a/pdns/release-scripts/make-linux-dynamics b/pdns/release-scripts/make-linux-dynamics
new file mode 100755 (executable)
index 0000000..1874462
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/make -f
+
+all: compile package
+
+compile:
+       make clean
+       make -k distclean
+       ./bootstrap
+       ./configure 
+       cd ../pdns-pipebackend ;        make clean;     make
+       cd ../ahudns-mysqlbackend ; make clean ;        make
+       cd  ../ahudns-pdnsbackend ; make clean ;        make
+       cd ../pdns-gpgsqlbackend; make clean  ;         make
+       cd ../pdns-gmysqlbackend; make clean  ;         make
+
+       cd extra ; make clean ; make
+       -rm libs/*
+       cd libs ; ln -s ../backends/bind/.libs/libbindbackend.so .
+       cd libs ; ln -s ../../pdns-pipebackend/.libs/libpipebackend.so .
+       cd libs; ln -s ../../ahudns-mysqlbackend/.libs/libmysqlbackend.so .
+       cd libs; ln -s ../../ahudns-pdnsbackend/.libs/libpdnsbackend.so .
+       cd libs; ln -s ../../pdns-gpgsqlbackend/*.so .
+       cd libs; ln -s ../../pdns-gmysqlbackend/*.so .
+       echo "" > extra/ld
+       make 
+       make mkbindist
+
+
+package:
+       mkdir -p release-files/deb/unstable
+       mkdir -p release-files/rpm-dynamic
+       mkdir -p release-files/linux-dynamic
+
+       rm -rf ../pdns_*deb
+       rm -rf ../pdns-*rpm
+
+       cp backends/bind/zone2sql .
+       
+       sudo debian/rules clean
+       sudo debian/rules binary
+
+       mv ../pdns_*deb release-files/deb/unstable
+       DESTDIR=/tmp/pdns sudo ./installer
+       sudo rpm -bb ./pdns-dynamic.spec
+       mv ../pdns-*rpm release-files/rpm-dynamic
+
+       . ./mkbindist
+       mv pdns*tar.gz release-files/linux-dynamic
+
diff --git a/pdns/release-scripts/make-linux-oracle-static b/pdns/release-scripts/make-linux-oracle-static
new file mode 100644 (file)
index 0000000..7e83a5c
--- /dev/null
@@ -0,0 +1,14 @@
+make clean
+make -k distclean
+./bootstrap
+./configure --enable-static-binaries
+cd extra
+ln -sf ../backends/bind/{bindbackend.o,zoneparser2.o,bindparser.o,bindlexer.o} .
+ln -sf ../backends/bind/huffman.o .
+ln -sf ../../pdns-oraclebackend/*.o .
+echo "-ldl -L/opt/oracle/lib -ldl -lclient8  -ldl -lclntst8" > ld
+cd ..
+rm libs/*
+make 
+cp backends/bind/zone2sql .
+
diff --git a/pdns/release-scripts/make-linux-static b/pdns/release-scripts/make-linux-static
new file mode 100644 (file)
index 0000000..5bdf319
--- /dev/null
@@ -0,0 +1,17 @@
+make clean
+make -k distclean
+./bootstrap
+./configure --enable-static-binaries
+cd extra
+ln -sf ../backends/bind/{bindbackend.o,zoneparser2.o,bindparser.o,bindlexer.o} .
+ln -sf ../backends/bind/huffman.o .
+ln -sf ../../pdns-pipebackend/*.o .
+ln -sf ../../ahudns-mysqlbackend/*.o .
+ln -sf ../../ahudns-pdnsbackend/*.o .
+ln -sf ../../pdns-gpgsqlbackend/*.o .
+echo "-lmysqlclient -L/opt/postgresql/lib -lpq++ -lpq -lssl -lcrypt -lcrypto" > ld
+cd ..
+rm libs/*
+make 
+cp backends/bind/zone2sql .
+
diff --git a/pdns/release-scripts/make-linux-statics b/pdns/release-scripts/make-linux-statics
new file mode 100755 (executable)
index 0000000..fbcde46
--- /dev/null
@@ -0,0 +1,52 @@
+#!/usr/bin/make -f
+
+all: compile package
+
+compile:
+       make distclean
+       ./configure --enable-static-binaries
+       cd ../pdns-pipebackend ; ./configure ; make clean;      make 
+       cd ../ahudns-mysqlbackend ; ./configure ; make clean ;  make && cd -
+       cd  ../ahudns-pdnsbackend ; ./configure ; make clean ;  make && cd -
+       cd ../pdns-gpgsqlbackend; ./configure ; make clean  ;   make && cd -
+       cd ../pdns-gmysqlbackend; ./configure ; make clean  ;   make && cd -
+       rm -f extra/*.o 
+       cd extra; ln -s ../backends/bind/{bindbackend.o,zoneparser2.o,bindparser.o,bindlexer.o} . ; cd -
+       cd extra ; ln -s ../backends/bind/huffman.o . ; cd -
+       cd extra ; ln -s ../../pdns-pipebackend/*.o . ; cd -
+       cd extra; ln -s ../../ahudns-mysqlbackend/*.o . ; cd -
+       cd extra; ln -s ../../ahudns-pdnsbackend/*.o . ; cd -
+       cd extra; ln -s ../../pdns-gpgsqlbackend/*.o . ; cd -
+       cd extra; ln -s ../../pdns-gmysqlbackend/*.o . ; cd -
+       echo "-lmysqlclient  -L/opt/postgresql/lib -lpq++ -lpq -lssl -lcrypt -lcrypto" > extra/ld
+       rm -f libs/*
+       make 
+       make mkbindist
+
+
+package:
+       mkdir -p release-files/deb/stable
+       mkdir -p release-files/linux-static
+       mkdir -p release-files/rpm
+
+       rm -rf ../pdns_*deb
+       rm -rf ../pdns-*rpm
+
+       cp backends/bind/zone2sql .
+       
+       sudo debian/rules.stable clean
+       sudo debian/rules.stable binary
+
+       mv ../pdns_*deb release-files/deb/stable
+
+       cp pathconfig.redhat pathconfig
+       DESTDIR=/tmp/pdns sudo ./installer
+       sudo rpm -bb ./pdns.spec
+       mv ../pdns-*rpm release-files/rpm
+
+       rm -f pdns*tar.gz
+
+       . ./mkbindist
+       mv pdns*tar.gz release-files/linux-static
+                       
+
diff --git a/pdns/release-scripts/make-linux-statics-3.2 b/pdns/release-scripts/make-linux-statics-3.2
new file mode 100755 (executable)
index 0000000..5468bc1
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/make -f
+
+all: compile package
+
+compile: prepare realcompile
+
+prepare:
+       make distclean
+       ./configure --enable-static-binaries
+       cd ../pdns-pipebackend ; ./configure ; make clean;      make 
+       cd ../ahudns-mysqlbackend ; ./configure ; make clean ;  make && cd -
+       cd  ../ahudns-pdnsbackend ; ./configure ; make clean ;  make && cd -
+       cd ../pdns-gpgsqlbackend; ./configure ; make clean  ;   make && cd -
+       cd ../pdns-xdbbackend;  make clean  ;   make && cd -
+       cd ../pdns-gmysqlbackend; ./configure ; make clean  ;   make && cd -
+       rm -f extra/*.o 
+       cd extra ; ln -s ../../pdns-pipebackend/*.o . ; cd -
+       cd extra; ln -s ../../ahudns-mysqlbackend/*.o . ; cd -
+       cd extra; ln -s ../../ahudns-pdnsbackend/*.o . ; cd -
+       cd extra; ln -s ../../pdns-gpgsqlbackend/*.o . ; cd -
+       cd extra; ln -s ../../pdns-gmysqlbackend/*.o . ; cd -
+#      cd extra; ln -s ../../pdns-xdbbackend/*.o . ; cd -
+       echo "-lmysqlclient  -L/opt/postgresql-with-3.2/lib -lpq++ -lpq -lssl -lcrypt -lcrypto" > extra/ld
+       rm -f libs/*
+
+realcompile: 
+       make 
+       make mkbindist
+
+
+package:
+       mkdir -p release-files/deb/stable
+       mkdir -p release-files/linux-static
+       mkdir -p release-files/rpm
+
+       rm -rf ../pdns_*deb
+       rm -rf ../pdns-*rpm
+
+       cp backends/bind/zone2sql .
+       
+       sudo debian/rules clean
+       sudo debian/rules binary
+
+       mv ../pdns_*deb release-files/deb/stable
+
+       cp pathconfig.redhat pathconfig
+       DESTDIR=/tmp/pdns sudo ./installer
+       sudo rpm -bb ./pdns.spec
+       mv ../pdns-*rpm release-files/rpm
+
+       rm -f pdns*tar.gz
+
+       . ./mkbindist
+       mv pdns*tar.gz release-files/linux-static
+                       
+
diff --git a/pdns/resolver.cc b/pdns/resolver.cc
new file mode 100644 (file)
index 0000000..1528e1e
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "resolver.hh"
+#include <pthread.h>
+#include <semaphore.h>
+#include <iostream>
+#include <errno.h>
+#include "misc.hh"
+#include <algorithm>
+#include <sstream>
+#include <cstring>
+#include <string>
+#include <vector>
+#include "dnspacket.hh"
+#include "dns.hh"
+#include "qtype.hh"
+#include "tcpreceiver.hh"
+#include "ahuexception.hh"
+#include "statbag.hh"
+#include "arguments.hh"
+
+void Resolver::makeUDPSocket()
+{
+  makeSocket(SOCK_DGRAM);
+}
+
+void Resolver::makeSocket(int type)
+{
+  static u_int16_t port_counter=5000;
+  if(d_sock>0)
+    return;
+
+  d_sock=socket(AF_INET, type,0);
+  if(d_sock<0) 
+    throw AhuException("Making a socket for resolver: "+stringerror());
+
+  struct sockaddr_in sin;
+  memset((char *)&sin,0, sizeof(sin));
+  
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = INADDR_ANY;
+
+  int tries=10;
+  while(--tries) {
+    sin.sin_port = htons(10000+(port_counter++)%10000); // should be random!
+  
+    if (bind(d_sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 
+      break;
+
+  }
+  if(!tries)
+    throw AhuException("Resolver binding to local socket: "+stringerror());
+}
+
+Resolver::Resolver()
+{
+  d_sock=-1;
+  d_timeout=500000;
+  d_buf=new unsigned char[66000];
+}
+
+Resolver::~Resolver()
+{
+  if(d_sock>=0)
+    Utility::closesocket(d_sock);
+  delete[] d_buf;
+}
+
+void Resolver::timeoutReadn(char *buffer, int bytes)
+{
+  time_t start=time(0);
+  int n=0;
+  int numread;
+  while(n<bytes) {
+    if(waitForData(d_sock, 10-(time(0)-start))<0)
+      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
+
+    numread=recv(d_sock,buffer+n,bytes-n,0);
+    if(numread<0)
+      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
+    if(numread==0)
+      throw ResolverException("Remote nameserver closed TCP connection");
+    n+=numread;
+  }
+}
+
+char* Resolver::sendReceive(const string &ip, u_int16_t remotePort, const char *packet, int length, unsigned int *replen)
+{
+  makeTCPSocket(ip, remotePort);
+
+  if(sendData(packet,length,d_sock)<0) 
+    throw ResolverException("Unable to send packet to remote nameserver "+ip+": "+stringerror());
+
+  int plen=getLength();
+  if(plen<0)
+    throw ResolverException("EOF trying to get length of answer from remote TCP server");
+
+  char *answer=new char[plen];
+  try {
+    timeoutReadn(answer,plen);
+    *replen=plen;
+    return answer;
+  }
+  catch(...) {
+    delete answer;
+    throw; // whop!
+  }
+  return 0;
+}
+
+int Resolver::notify(int sock, const string &domain, const string &ip, u_int16_t id)
+{
+  DNSPacket p;
+  p.setQuestion(Opcode::Notify,domain,QType::SOA);
+  p.wrapup();
+  p.spoofID(id);
+
+  struct in_addr inp;
+  Utility::inet_aton(ip.c_str(),&inp);
+
+  struct sockaddr_in toaddr;
+  toaddr.sin_addr.s_addr=inp.s_addr;
+
+  toaddr.sin_port=htons(53);
+  toaddr.sin_family=AF_INET;
+
+  if(sendto(sock, p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr))<0) {
+    throw ResolverException("Unable to send notify to "+ip+": "+stringerror());
+  }
+  return true;
+}
+
+
+int Resolver::resolve(const string &ip, const char *domain, int type)
+{
+  makeUDPSocket();
+  DNSPacket p;
+  p.setQuestion(Opcode::Query,domain,type);
+  p.wrapup();
+
+  d_domain=domain;
+  d_type=type;
+  d_inaxfr=false;
+
+  struct sockaddr_in toaddr;
+  struct in_addr inp;
+  Utility::inet_aton(ip.c_str(),&inp);
+  toaddr.sin_addr.s_addr=inp.s_addr;
+
+  toaddr.sin_port=htons(53);
+  toaddr.sin_family=AF_INET;
+
+  if(sendto(d_sock, p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr))<0) {
+    throw ResolverException("Unable to ask query of "+ip+": "+stringerror());
+  }
+
+  Utility::socklen_t addrlen=sizeof(toaddr);
+
+  fd_set rd;
+  FD_ZERO(&rd);
+  FD_SET(d_sock, &rd);
+
+  struct timeval timeout;
+  timeout.tv_sec=1;
+  timeout.tv_usec=500000;
+
+  int res=select(d_sock+1,&rd,0,0,&timeout);
+  if(!res)
+    throw ResolverException("Timeout waiting for answer from "+ip);
+  if(res<0)
+    throw ResolverException("Error waiting for answer: "+stringerror());
+
+
+  if((d_len=recvfrom(d_sock, reinterpret_cast< char * >( d_buf ), 512,0,(struct sockaddr*)(&toaddr), &addrlen))<0) 
+    throw ResolverException("recvfrom error waiting for answer: "+stringerror());
+
+  return 1;
+}
+
+void Resolver::makeTCPSocket(const string &ip, u_int16_t port)
+{
+  if(d_sock>=0)
+    return;
+  struct sockaddr_in toaddr;
+  struct in_addr inp;
+  Utility::inet_aton(ip.c_str(),&inp);
+  toaddr.sin_addr.s_addr=inp.s_addr;
+
+  toaddr.sin_port=htons(port);
+  toaddr.sin_family=AF_INET;
+  
+
+  d_sock=socket(AF_INET,SOCK_STREAM,0);
+  if(d_sock<0)
+    throw ResolverException("Unable to make a TCP socket for resolver: "+stringerror());
+  
+  Utility::setNonBlocking( d_sock );
+
+  int err;
+#ifndef WIN32
+  if((err=connect(d_sock,(struct sockaddr*)&toaddr,sizeof(toaddr)))<0 && errno!=EINPROGRESS) {
+#else
+  if((err=connect(d_sock,(struct sockaddr*)&toaddr,sizeof(toaddr)))<0 && WSAGetLastError() != WSAEWOULDBLOCK ) {
+#endif // WIN32
+    throw ResolverException("connect: "+stringerror());
+  }
+
+  if(!err)
+    goto done;
+
+  fd_set rset,wset;
+  struct timeval tval;
+
+  FD_ZERO(&rset);
+  FD_SET(d_sock, &rset);
+  wset=rset;
+  tval.tv_sec=10;
+  tval.tv_usec=0;
+
+  if(!select(d_sock+1,&rset,&wset,0,tval.tv_sec ? &tval : 0)) {
+    Utility::closesocket(d_sock); // timeout
+    d_sock=-1;
+    errno=ETIMEDOUT;
+    
+    throw ResolverException("Timeout connecting to server");
+  }
+  
+  if(FD_ISSET(d_sock, &rset) || FD_ISSET(d_sock, &wset))
+    {
+    Utility::socklen_t len=sizeof(err);
+      if(getsockopt(d_sock, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
+       throw ResolverException("Error connecting: "+stringerror()); // Solaris
+
+      if(err)
+       throw ResolverException("Error connecting: "+string(strerror(err)));
+
+    }
+  else
+    throw ResolverException("nonblocking connect failed");
+
+ done:
+  Utility::setBlocking( d_sock );
+  // d_sock now connected
+}
+
+
+//! returns -1 for permanent error, 0 for timeout, 1 for success
+int Resolver::axfr(const string &ip, const char *domain)
+{
+  d_domain=domain;
+
+  makeTCPSocket(ip);
+
+  d_type=QType::AXFR;
+  DNSPacket p;
+  p.setQuestion(Opcode::Query,domain,QType::AXFR);
+  p.wrapup();
+
+  int replen=htons(p.len);
+  Utility::iovec iov[2];
+  iov[0].iov_base=(char*)&replen;
+  iov[0].iov_len=2;
+  iov[1].iov_base=(char*)p.getData();
+  iov[1].iov_len=p.len;
+
+  int ret=Utility::writev(d_sock,iov,2);
+  if(ret<0)
+    throw ResolverException("Error sending question to "+ip+": "+stringerror());
+
+  fd_set rd;
+  FD_ZERO(&rd);
+  FD_SET(d_sock, &rd);
+
+  struct timeval timeout;
+  timeout.tv_sec=10;
+  timeout.tv_usec=0;
+
+  int res=select(d_sock+1,&rd,0,0,&timeout);
+  if(!res)
+    throw ResolverException("Timeout waiting for answer from "+ip+" during AXFR");
+  if(res<0)
+    throw ResolverException("Error waiting for answer from "+ip+": "+stringerror());
+
+  d_soacount=0;
+  d_inaxfr=true;
+  return 1;
+}
+
+int Resolver::getLength()
+{
+  int bytesLeft=2;
+  unsigned char buf[2];
+  
+  while(bytesLeft) {
+    int ret=waitForData(d_sock, 10);
+    if(ret<0) {
+      Utility::closesocket(d_sock);
+      throw ResolverException("Waiting on data from remote TCP client: "+stringerror());
+    }
+  
+    ret=recv(d_sock, reinterpret_cast< char * >( buf ) +2-bytesLeft, bytesLeft,0);
+    if(ret<0)
+      throw ResolverException("Trying to read data from remote TCP client: "+stringerror());
+    if(!ret) 
+      return -1;
+    
+    bytesLeft-=ret;
+  }
+  return buf[0]*256+buf[1];
+}
+
+int Resolver::axfrChunk(Resolver::res_t &res)
+{
+  // d_sock is connected and is about to spit out a packet
+  int len=getLength();
+  if(len<0)
+    return 0;
+  
+  timeoutReadn((char *)d_buf,len); 
+  d_len=len;
+  res=result();
+  if(!res.empty())
+    if(res.begin()->qtype.getCode()==QType::SOA || res.end()->qtype.getCode()==QType::SOA)
+      d_soacount++;
+
+  if(d_soacount==2) {
+    Utility::closesocket(d_sock);
+    d_sock=-1;
+    return 0;
+  }
+
+  return 1;
+}
+
+
+Resolver::res_t Resolver::result()
+{
+  try {
+    DNSPacket p;
+    
+    if(p.parse((char *)d_buf, d_len)<0)
+      throw ResolverException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
+    
+    if(p.d.rcode)
+      if(d_inaxfr)
+       throw ResolverException("Remote nameserver unable/unwilling to AXFR with us: RCODE="+itoa(p.d.rcode));
+      else
+       throw ResolverException("Remote nameserver reported error: RCODE="+itoa(p.d.rcode));
+    
+    if(!d_inaxfr) {
+      if(ntohs(p.d.qdcount)!=1)
+       throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(ntohs(p.d.qdcount))+")");
+      
+      if(p.qdomain!=d_domain)
+       throw ResolverException(string("resolver: received an answer to another question (")+p.qdomain+"!="+d_domain+")");
+    }
+    return p.getAnswers();
+  }
+  catch(AhuException &ae) { // translate
+    throw ResolverException(ae.reason);
+  }
+}
+
+
+int Resolver::getSoaSerial(const string &ip, const string &domain, u_int32_t *serial)
+{
+  resolve(ip,domain.c_str(),QType::SOA);
+  res_t res=result();
+  if(res.empty())
+    return 0;
+  
+  vector<string>parts;
+  stringtok(parts,res[0].content);
+  if(parts.size()<3)
+    return 0;
+  
+  *serial=atoi(parts[2].c_str());
+  return 1;
+}
+
diff --git a/pdns/resolver.hh b/pdns/resolver.hh
new file mode 100644 (file)
index 0000000..0f0bedd
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+\r
+#include <string>
+#include <vector>
+#include <sys/types.h>\r
+\r
+#ifndef WIN32\r
+
+# include <arpa/nameser.h>\r
+# include <resolv.h>\r
+# include <netdb.h> \r
+# include <unistd.h>\r
+# include <sys/time.h>\r
+# include <sys/uio.h>\r
+# include <fcntl.h>\r
+# include <sys/socket.h>\r
+# include <netinet/in.h>\r
+# include <arpa/inet.h>\r
+# undef res_mkquery
+#endif // WIN32\r
+
+#include "ahuexception.hh"
+#include "dns.hh"
+using namespace std;
+
+class ResolverException : public AhuException
+{
+public:
+  ResolverException(const string &reason) : AhuException(reason){}
+};
+
+//! Resolver class 
+class Resolver
+{
+public:
+  Resolver();
+  ~Resolver();
+  string i;
+
+  typedef vector<DNSResourceRecord> res_t;
+  void makeSocket(int type);
+  void makeUDPSocket();
+  void makeTCPSocket(const string &ip, u_int16_t port=53);
+  int notify(int sock, const string &domain, const string &ip, u_int16_t id);
+  int resolve(const string &ip, const char *domain, int type);
+  char* sendReceive(const string &ip, u_int16_t remotePort, const char *packet, int length, unsigned int *replylen);
+  int getSoaSerial(const string &, const string &, u_int32_t *);
+  int axfrChunk(Resolver::res_t &res);
+  vector<DNSResourceRecord> result();
+  
+  void setRemote(const string &remote);
+  int axfr(const string &ip, const char *domain);
+  
+private:
+  void timeoutReadn(char *buffer, int bytes);
+  int d_sock;
+  unsigned char *d_buf;
+  int getLength();
+  int d_len;
+  int d_soacount;
+  string d_domain;
+  int d_type;
+  int d_timeout;
+  u_int32_t d_ip;
+  bool d_inaxfr;
+};
+
diff --git a/pdns/session.cc b/pdns/session.cc
new file mode 100644 (file)
index 0000000..c944b54
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "session.hh"
+#include "ahuexception.hh"
+#include "misc.hh"
+#include <cstring>
+#include <iostream>
+#include <sys/types.h>\r
+#include <fcntl.h>
+#include <sstream>
+
+
+
+void Session::init()
+{
+  d_bufsize=15049;
+
+  d_verbose=false;
+
+  rdbuf=new char[d_bufsize];  
+  rdoffset=0;
+  wroffset=0;
+}
+
+void Session::beVerbose()
+{
+  d_verbose=true;
+}
+
+Session::Session(int s, struct sockaddr_in r)
+{
+  init();
+  remote=r;
+  clisock=s;
+}
+
+int Session::close()
+{
+  int rc=0;
+  
+  if(clisock>=0)
+    rc=Utility::closesocket(clisock);
+
+  clisock=-1;
+  return rc;
+}
+
+Session::~Session()
+{
+
+  /* NOT CLOSING AUTOMATICALLY ANYMORE!
+    if(clisock>=0)
+    ::close(clisock);
+  */  
+
+  delete[] rdbuf;
+}
+
+//! This function makes a deep copy of Session
+Session::Session(const Session &s)
+{
+  d_bufsize=s.d_bufsize;
+
+  init(); // needs d_bufsize, but will reset rdoffset & wroffset
+
+  rdoffset=s.rdoffset;
+  wroffset=s.wroffset;
+  clisock=s.clisock;
+  remote=s.remote;
+
+  memcpy(rdbuf,s.rdbuf,d_bufsize);
+}  
+
+Session::Session(const string &dest, int port, int timeout)
+{
+  struct hostent *h;
+  h=gethostbyname(dest.c_str());
+  if(!h)
+    throw SessionException("Unable to resolve target name");
+  
+  if(timeout)
+    d_timeout=timeout;
+
+  doConnect(*(int*)h->h_addr, port);
+}
+
+Session::Session(u_int32_t ip, int port, int timeout)
+{
+  if(timeout)
+    d_timeout=timeout;
+
+  doConnect(ip, port);
+}
+
+void Session::setTimeout(unsigned int seconds)
+{
+  d_timeout=seconds;
+}
+
+  
+void Session::doConnect(u_int32_t ip, int port)
+{
+  init();
+  clisock=socket(AF_INET,SOCK_STREAM,0);
+  
+  memset(&remote,0,sizeof(remote));
+  remote.sin_family=AF_INET;
+  remote.sin_port=htons(port);
+
+  remote.sin_addr.s_addr=ip;
+
+  Utility::setNonBlocking( clisock );\r
+
+  int err;
+#ifndef WIN32\r
+  if((err=connect(clisock,(struct sockaddr*)&remote,sizeof(remote)))<0 && errno!=EINPROGRESS) {\r
+#else\r
+  if((err=connect(clisock,(struct sockaddr*)&remote,sizeof(remote)))<0 && WSAGetLastError() != WSAEWOULDBLOCK ) {\r
+#endif // WIN32\r
+    throw SessionException("connect: "+stringerror());\r
+\r
+  }\r
+
+  if(!err)
+    goto done;
+
+  fd_set rset,wset;
+  struct timeval tval;
+
+  FD_ZERO(&rset);
+  FD_SET(clisock, &rset);
+  wset=rset;
+  tval.tv_sec=d_timeout;
+  tval.tv_usec=0;
+
+  if(!select(clisock+1,&rset,&wset,0,tval.tv_sec ? &tval : 0))
+    {
+      Utility::closesocket(clisock); // timeout
+      clisock=-1;
+      errno=ETIMEDOUT;
+  
+      throw SessionTimeoutException("Timeout connecting to server");
+    }
+  
+  if(FD_ISSET(clisock, &rset) || FD_ISSET(clisock, &wset))
+    {
+    Utility::socklen_t len=sizeof(err);
+      if(getsockopt(clisock, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
+       throw SessionException("Error connecting: "+stringerror()); // Solaris
+
+      if(err)
+       throw SessionException("Error connecting: "+string(strerror(err)));
+
+    }
+  else
+    throw SessionException("nonblocking connect failed");
+
+ done:\r
+      Utility::setBlocking( clisock );
+}
+
+bool Session::putLine(const string &s)
+{
+  int length=s.length();
+  int written=0;
+  int err;
+
+  while(written<length)
+    {
+      fd_set wset;
+      FD_ZERO(&wset);
+      FD_SET(clisock, &wset);
+      struct timeval tval;
+      tval.tv_sec=d_timeout;
+      tval.tv_usec=0;
+      
+      if(!select(clisock+1,0,&wset,0,tval.tv_sec ? &tval : 0))
+       throw SessionTimeoutException("timeout writing line");
+
+      if(FD_ISSET(clisock, &wset))
+       {
+        Utility::socklen_t len=sizeof(err);
+         if(getsockopt(clisock, SOL_SOCKET,SO_ERROR,(char *) &err,&len)<0)
+           throw SessionException(+strerror(err)); // Solaris..
+         
+         if(err)
+           throw SessionException(strerror(err));
+       }
+      else
+       throw SessionException("nonblocking write failed"+string(strerror(errno)));
+
+      err=send(clisock,s.c_str()+written,length-written,0);
+
+      if(err<0)
+       return false;
+      
+      written+=err;
+    }
+
+  return true;
+}
+
+char *strnchr(char *p, char c, int len)
+{
+  int n;
+  for(n=0;n<len;n++)
+    if(p[n]==c)
+      return p+n;
+  return 0;
+}
+
+int Session::timeoutRead(int s, char *buf, size_t len)
+{
+  fd_set rset;
+  FD_ZERO(&rset);
+  FD_SET(clisock, &rset);
+  struct timeval tval;
+  tval.tv_sec=d_timeout;
+  tval.tv_usec=0;
+  
+  int err;
+  
+  if(!select(clisock+1,&rset,0,0,tval.tv_sec ? &tval : 0))
+    throw SessionTimeoutException("timeout reading");
+  
+  if(FD_ISSET(clisock, &rset))
+    {
+    Utility::socklen_t len=sizeof(err);
+      if(getsockopt(clisock, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
+       throw SessionException(strerror(errno)); // Solaris..
+      
+      if(err)
+       throw SessionException(strerror(err));
+    }
+  else
+    throw SessionException("nonblocking read failed"+string(strerror(errno)));
+  
+  return recv(s,buf,len,0);
+      
+
+}
+
+bool 
+Session::haveLine()
+{
+  return (wroffset!=rdoffset && (strnchr(rdbuf+rdoffset,'\n',wroffset-rdoffset)!=NULL));
+}
+       
+
+bool 
+Session::getLine(string &line)
+{
+  int bytes;
+  char *p;
+
+  int linelength;
+  
+  // read data into a buffer
+  // find first \n, and return that as string, store how far we were
+
+
+  for(;;)
+    {
+      if(wroffset==rdoffset)
+       {
+         wroffset=rdoffset=0;
+       }
+
+      if(wroffset!=rdoffset && (p=strnchr(rdbuf+rdoffset,'\n',wroffset-rdoffset))) // we have a full line in store, return that 
+       {
+         // from rdbuf+rdoffset to p should become the new line
+
+         linelength=p-(rdbuf+rdoffset); 
+         
+         *p=0; // terminate
+         
+         line=rdbuf+rdoffset;
+         line+="\n";
+         
+         rdoffset+=linelength+1;
+
+         return true;
+       }
+      // we need more data before we can return a line
+
+      if(wroffset==d_bufsize) // buffer is full, flush to left
+       {
+         if(!rdoffset) // line too long!
+           {
+             // FIXME: do stuff
+             close();
+             return false;
+           }
+
+         memmove(rdbuf,rdbuf+rdoffset,wroffset-rdoffset);
+         wroffset-=rdoffset;
+         rdoffset=0;
+       }
+      bytes=timeoutRead(clisock,rdbuf+wroffset,d_bufsize-wroffset);
+
+      if(bytes<0)
+         throw SessionException("error on read from socket: "+string(strerror(errno)));
+
+      if(bytes==0)
+       throw SessionException("Remote closed connection");
+
+      wroffset+=bytes;
+    }
+  // we never get here
+}
+  
+int Session::getSocket()
+{
+  return clisock;
+}
+
+string Session::getRemote ()
+{
+  ostringstream o;
+  u_int32_t rint=htonl(remote.sin_addr.s_addr);
+  o<< (rint>>24 & 0xff)<<".";
+  o<< (rint>>16 & 0xff)<<".";
+  o<< (rint>>8  & 0xff)<<".";
+  o<< (rint     & 0xff);
+  o<<":"<<htons(remote.sin_port);
+
+  return o.str();
+}
+
+u_int32_t Session::getRemoteAddr()
+{
+
+  return htonl(remote.sin_addr.s_addr);
+}
+
+string Session::getRemoteIP()
+{
+  ostringstream o;
+  u_int32_t rint=htonl(remote.sin_addr.s_addr);
+  o<< (rint>>24 & 0xff)<<".";
+  o<< (rint>>16 & 0xff)<<".";
+  o<< (rint>>8  & 0xff)<<".";
+  o<< (rint     & 0xff);
+
+  return o.str();
+}
+  
+
+Session *Server::accept()
+{
+  struct sockaddr_in remote;
+  Utility::socklen_t len=sizeof(remote);
+
+  int clisock=-1;
+
+
+  while((clisock=::accept(s,(struct sockaddr *)(&remote),&len))==-1) // repeat until we have a succesful connect
+    {
+      //      L<<Logger::Error<<"accept() returned: "<<strerror(errno)<<endl;
+      if(errno==EMFILE) {
+       throw SessionException("Out of file descriptors - won't recover from that");
+      }
+
+    }
+
+  return new Session(clisock, remote);
+}
+
+
+
+Server::Server(int p, const string &p_localaddress)
+{
+  d_localaddress="0.0.0.0";
+  string localaddress=p_localaddress;
+  port=p;
+
+  struct sockaddr_in local;
+  s=socket(AF_INET,SOCK_STREAM,0);
+
+  if(s<0)
+    {
+      throw Exception(string("socket: ")+strerror(errno));
+    }
+  
+  memset(&local,0,sizeof(local));
+  
+  local.sin_family=AF_INET;
+  
+  struct hostent *h;
+  if(localaddress=="")
+    localaddress=d_localaddress;
+\r
+  if ( localaddress != "0.0.0.0" )
+  {\r
+    h=gethostbyname(localaddress.c_str());
+
+    if(!h)
+      throw Exception(); 
+  
+    local.sin_addr.s_addr=*(int*)h->h_addr;\r
+  }\r
+  else\r
+  {\r
+    local.sin_addr.s_addr = INADDR_ANY;\r
+  }
+
+  local.sin_port=htons(port);
+  
+  int tmp=1;
+  if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
+    throw SessionException(string("Setsockopt failed: ")+strerror(errno));
+
+
+  if(bind(s, (sockaddr*)&local,sizeof(local))<0)
+      throw SessionException("binding to port "+itoa(port)+string(": ")+strerror(errno));
+  
+  if(listen(s,128)<0)
+      throw SessionException("listen: "+stringerror());
+
+}
+
diff --git a/pdns/session.hh b/pdns/session.hh
new file mode 100644 (file)
index 0000000..6006267
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef SESSION_HH
+#define SESSION_HH
+
+#include <string>
+#include <cerrno>
+\r
+#ifndef WIN32\r
+# include <sys/stat.h>\r
+# include <netdb.h>\r
+# include <unistd.h>\r
+# include <sys/time.h>\r
+# include <sys/socket.h>\r
+# include <arpa/inet.h>  \r
+# include <netinet/in.h>\r
+# include <sys/types.h>\r
+# include <strings.h>\r
+\r
+#endif // WIN32\r
+
+#include "ahuexception.hh"
+
+class SessionException: public AhuException
+{
+public:
+  SessionException(const string &reason) : AhuException(reason){}
+};
+
+class SessionTimeoutException: public SessionException
+{
+public:
+  SessionTimeoutException(const string &reason) : SessionException(reason){}
+};
+
+//! The Session class represents a TCP/IP session, which can either be created or run on an existing socket
+class Session
+{
+public:
+  bool getLine(string &); //!< Read a line from the remote
+  bool haveLine(); //!< returns true if a line is available
+  bool putLine(const string &s); //!< Write a line to the remote
+  bool sendFile(int fd); //!< Send a file out
+  int timeoutRead(int s,char *buf, size_t len);
+
+  Session(int s, struct sockaddr_in r); //!< Start a session on an existing socket, and inform this class of the remotes name
+
+  /** Create a session to a remote host and port. This function reads a timeout value from the ArgvMap class 
+      and does a nonblocking connect to support this timeout. It should be noted that nonblocking connects 
+      suffer from bad portability problems, so look here if you see weird problems on new platforms */
+  Session(const string &remote, int port, int timeout=0); 
+  Session(u_int32_t ip, int port, int timeout=0);
+
+  Session(const Session &s); 
+  
+  ~Session();
+  int getSocket(); //!< return the filedescriptor for layering violations
+  string getRemote();
+  u_int32_t getRemoteAddr();
+  string getRemoteIP();
+  void beVerbose();
+  int close(); //!< close and disconnect the connection
+  void setTimeout(unsigned int seconds);
+private:
+  void doConnect(u_int32_t ip, int port);
+  bool d_verbose;
+  char *rdbuf;
+  int d_bufsize;
+  int rdoffset;
+  int wroffset;
+  int clisock;
+  struct sockaddr_in remote;
+  void init();
+  int d_timeout;
+
+};
+
+//! The server class can be used to create listening servers
+class Server
+{
+public:
+  Server(int p, const string &localaddress=""); //!< port on which to listen
+  Session* accept(); //!< Call accept() in an endless loop to accept new connections
+private:
+  int s;
+  int port;
+  int backlog;
+
+  string d_localaddress;
+};
+
+class Exception
+{
+public:
+  Exception(){reason="Unspecified";};
+  Exception(string r){reason=r;};
+  string reason;
+};
+
+#endif /* SESSION_HH */
diff --git a/pdns/showvar.in b/pdns/showvar.in
new file mode 100755 (executable)
index 0000000..814c721
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+# unplug the nameserver: go
+for a in "$@";
+do
+       @bindir@/dynloader @localstatedir@/ahudns.controlsocket show "$a"
+done
diff --git a/pdns/stamp-h.in b/pdns/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/pdns/statbag.cc b/pdns/statbag.cc
new file mode 100644 (file)
index 0000000..1fce017
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+\r
+#include "utility.hh"\r
+#include "statbag.hh"
+#include "ahuexception.hh"
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include "arguments.hh"
+#include "lock.hh"
+
+using namespace std;
+
+StatBag::StatBag()
+{
+  d_doRings=false;
+  pthread_mutex_init(&d_lock,0);
+}
+
+
+
+/** this NEEDS TO HAVE THE LOCK held already! */
+void StatBag::exists(const string &key)
+{
+  if(!d_stats.count(key))
+    {
+      unlock(); // it's the details that count
+      throw AhuException("Trying to deposit into unknown StatBag key '"+key+"'");
+    }
+}
+
+string StatBag::directory()
+{
+  string dir;
+  ostringstream o;
+  lock();
+  for(map<string,int *>::const_iterator i=d_stats.begin();
+      i!=d_stats.end();
+      i++)
+    {
+      o<<i->first<<"="<<*(i->second)<<",";
+    }
+  unlock();
+  dir=o.str();
+  return dir;
+}
+
+
+vector<string>StatBag::getEntries()
+{
+  vector<string> ret;
+  lock();
+  for(map<string,int *>::const_iterator i=d_stats.begin();
+      i!=d_stats.end();
+      i++)
+      ret.push_back(i->first);
+
+  unlock();
+  return ret;
+
+}
+
+string StatBag::getDescrip(const string &item)
+{
+  lock();
+  string tmp=d_keyDescrips[item];
+  unlock();
+  return tmp;
+}
+
+void StatBag::declare(const string &key, const string &descrip)
+{
+  lock();
+  int *i=new int(0);
+  d_stats[key]=i;
+  d_keyDescrips[key]=descrip;
+  unlock();
+}
+
+
+          
+void StatBag::set(const string &key, int value)
+{
+  lock();
+  exists(key);
+  *d_stats[key]=value;
+
+  unlock();
+}
+
+int StatBag::read(const string &key)
+{
+  lock();
+
+  if(!d_stats.count(key))
+    {
+      unlock();
+      return 0;
+    }
+
+  int tmp=*d_stats[key];
+
+  unlock();
+  return tmp;
+
+}
+
+int StatBag::readZero(const string &key)
+{
+  lock();
+
+
+  if(!d_stats.count(key))
+    {
+      unlock();
+      return 0;
+    }
+
+  
+  int tmp=*d_stats[key];
+  d_stats[key]=0;
+
+  unlock();
+
+  return tmp;
+}
+
+
+string StatBag::getValueStr(const string &key)
+{
+  ostringstream o;
+  o<<read(key);
+  return o.str();
+}
+
+string StatBag::getValueStrZero(const string &key)
+{
+  ostringstream o;
+  o<<readZero(key);
+  return o.str();
+}
+
+int *StatBag::getPointer(const string &key)
+{
+  exists(key);
+  return d_stats[key];
+}
+
+StatBag::~StatBag()
+{
+  for(map<string,int *>::const_iterator i=d_stats.begin();
+      i!=d_stats.end();
+      i++)
+    {
+      delete i->second;
+    }
+  
+}
+
+StatRing::StatRing(int size)
+{
+  d_size=size;
+  d_items.resize(d_size);
+  d_lock=0;
+  d_pos=0;
+  d_lock=new pthread_mutex_t;
+  pthread_mutex_init(d_lock, 0);
+}
+
+void StatRing::resize(int newsize)
+{
+  if(d_size==newsize)
+    return;
+  Lock l(d_lock);
+
+  if(newsize>d_size) {
+    d_size=newsize;
+    d_items.resize(d_size);
+    return;
+  }
+
+  // this is the hard part, shrink
+  int startpos=d_pos-newsize;
+  int rpos;
+  vector<string>newring;
+  for(int i=startpos;i<d_pos;++i) {
+    rpos=i>=0 ? i : i+d_size;
+
+    newring.push_back(d_items[rpos%d_size]);
+  }
+  d_items=newring;
+  d_size=newsize;
+  d_pos=d_size-1;
+
+}
+StatRing::~StatRing()
+{
+  // do not clean up d_lock, it is shared
+}
+
+void StatRing::setHelp(const string &str)
+{
+  d_help=str;
+}
+
+string StatRing::getHelp()
+{
+  return d_help;
+}
+
+static bool popisort(const pair<string,int> &a, const pair<string,int> &b)
+{
+  return (a.second > b.second);
+}
+
+vector<pair<string,int> >StatRing::get() const
+{
+  Lock l(d_lock);
+  map<string,int> res;
+  for(vector<string>::const_iterator i=d_items.begin();i!=d_items.end();++i) {
+    if(!i->empty())
+      res[*i]++;
+  }
+  
+  vector<pair<string,int> > tmp;
+  for(map<string,int>::const_iterator i=res.begin();i!=res.end();++i) 
+    tmp.push_back(*i);
+
+  sort(tmp.begin(),tmp.end(),popisort);
+
+  return tmp;
+}
+
+void StatBag::declareRing(const string &name, const string &help, unsigned int size)
+{
+  d_rings[name]=StatRing(size);
+  d_rings[name].setHelp(help);
+}
+
+vector<pair<string,int> > StatBag::getRing(const string &name)
+{
+  return d_rings[name].get();
+}
+
+void StatRing::reset()
+{
+  Lock l(d_lock);
+  for(vector<string>::iterator i=d_items.begin();i!=d_items.end();++i) {
+    if(!i->empty())
+      *i="";
+  }
+}
+
+void StatBag::resetRing(const string &name)
+{
+  d_rings[name].reset();
+}
+
+void StatBag::resizeRing(const string &name, int newsize)
+{
+  d_rings[name].resize(newsize);
+}
+
+
+int StatBag::getRingSize(const string &name)
+{
+  return d_rings[name].getSize();
+}
+
+
+string StatBag::getRingTitle(const string &name)
+{
+  return d_rings[name].getHelp();
+}
+
+vector<string>StatBag::listRings()
+{
+  vector<string> ret;
+  for(map<string,StatRing>::const_iterator i=d_rings.begin();i!=d_rings.end();++i)
+    ret.push_back(i->first);
+  return ret;
+}
+
+
diff --git a/pdns/statbag.hh b/pdns/statbag.hh
new file mode 100644 (file)
index 0000000..856c707
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef STATBAG_HH
+#define STATBAG_HH
+#include <pthread.h>
+#include <map>
+#include <string>
+#include <vector>
+#include "lock.hh"
+using namespace std;
+
+class StatRing
+{
+public:
+  StatRing(int size=10000);
+  ~StatRing();
+  void account(const string &item)
+  {
+    Lock l(d_lock);
+    d_items[d_pos++ % d_size]=item;
+  }
+
+
+  int getSize()
+  {
+    return d_size;
+  }
+  void resize(int newsize);  
+  void reset();
+  void setHelp(const string &str);
+  string getHelp();
+  vector<pair<string,int> >get() const;
+private:
+  int d_size;
+  int d_pos;
+  vector<string>d_items;
+  pthread_mutex_t *d_lock;
+  string d_help;
+};
+
+
+//! use this to gather and query statistics
+class StatBag
+{
+  map<string,int *> d_stats;
+  map<string, string> d_keyDescrips;
+  map<string,StatRing>d_rings;
+  bool d_doRings;
+  pthread_mutex_t d_lock;
+
+public:
+  StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful
+  ~StatBag();
+  void declare(const string &key, const string &descrip=""); //!< Before you can store or access a key, you need to declare it
+
+  void declareRing(const string &name, const string &title, unsigned int size=10000);
+  vector<pair<string,int> >getRing(const string &name);
+  string getRingTitle(const string &name);
+  void ringAccount(const string &name, const string &item)
+  {
+    if(d_doRings)
+      d_rings[name].account(item);
+  }
+  void doRings()
+  {
+    d_doRings=true;
+  }
+
+  vector<string>listRings();
+  void resetRing(const string &name);
+  void resizeRing(const string &name, int newsize);
+  int getRingSize(const string &name);
+
+  string directory(); //!< Returns a list of all data stored
+  vector<string> getEntries(); //!< returns a vector with datums (items)
+  string getDescrip(const string &item); //!< Returns the description of this datum/item
+  void exists(const string &key); //!< call this function to throw an exception in case a key does not exist
+  inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount
+  inline void inc(const string &key); //!< increase this key's value by one
+  void set(const string &key, int value); //!< set this key's value
+  int read(const string &key); //!< read the value behind this key
+  int readZero(const string &key); //!< read the value behind this key, and zero it afterwards
+  int *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments
+  string getValueStr(const string &key); //!< read a value behind a key, and return it as a string
+  string getValueStrZero(const string &key); //!< read a value behind a key, and return it as a string, and zero afterwards
+
+private:
+  void lock(){pthread_mutex_lock(&d_lock);}
+  void unlock(){pthread_mutex_unlock(&d_lock);}
+};
+
+inline void StatBag::deposit(const string &key, int value)
+{
+  lock();
+  exists(key);
+
+  *d_stats[key]+=value;
+
+  unlock();
+}
+
+inline void StatBag::inc(const string &key)
+{
+  deposit(key,1);
+}
+
+
+#endif /* STATBAG_HH */
diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc
new file mode 100644 (file)
index 0000000..731cbe2
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>
+#include <iostream>
+#include <string>
+#include "tcpreceiver.hh"
+\r
+#include <errno.h>
+#include <signal.h>
+
+#include "ueberbackend.hh"
+#include "dnspacket.hh"
+#include "nameserver.hh"
+#include "distributor.hh"
+#include "lock.hh"
+#include "logger.hh"
+#include "arguments.hh"
+#include "packetcache.hh"
+#include "packethandler.hh"
+#include "statbag.hh"
+#include "resolver.hh"
+#include "communicator.hh"
+
+extern PacketCache PC;
+extern StatBag S;
+
+/**
+\file tcpreceiver.cc
+\brief This file implements the tcpreceiver that receives and answers questions over TCP/IP
+*/
+
+pthread_mutex_t TCPNameserver::s_plock;
+Semaphore *TCPNameserver::d_connectionroom_sem;
+PacketHandler *TCPNameserver::s_P; 
+int TCPNameserver::s_timeout;
+
+
+int TCPNameserver::sendDelPacket(DNSPacket *p, int outsock)
+{
+  const char *buf=p->getData();
+  int res=sendData(buf, p->len, outsock);
+  delete p;
+  return res;
+}
+
+
+void TCPNameserver::go()
+{
+  L<<Logger::Error<<"Creating backend connection for TCP"<<endl;
+  s_P=0;
+  try {
+    s_P=new PacketHandler;
+  }
+  catch(AhuException &ae) {
+    L<<Logger::Error<<Logger::NTLog<<"TCP server is unable to launch backends - will try again when questions come in"<<endl;
+  }
+  pthread_create(&d_tid, 0, launcher, static_cast<void *>(this));
+}
+
+void *TCPNameserver::launcher(void *data)
+{
+  static_cast<TCPNameserver *>(data)->thread();
+  return 0;
+}
+
+
+int TCPNameserver::readLength(int fd, struct sockaddr_in *remote)
+{
+  int bytesLeft=2;
+  unsigned char buf[2];
+  
+  Utility::socklen_t remotelen=sizeof(*remote);
+  getpeername(fd, (struct sockaddr *)remote, &remotelen);
+
+  while(bytesLeft) {
+    int ret=waitForData(fd, s_timeout);
+    if(ret<0)
+      throw AhuException("Waiting on data from remote TCP client "+string(inet_ntoa(remote->sin_addr))+": "+stringerror());
+  
+    ret=recv(fd, reinterpret_cast< char * >( buf ) +2-bytesLeft, bytesLeft,0);
+    if(ret<0)
+      throw AhuException("Trying to read data from remote TCP client "+string(inet_ntoa(remote->sin_addr))+": "+stringerror());
+    if(!ret) {
+      DLOG(L<<"Remote TCP client "+string(inet_ntoa(remote->sin_addr))+" closed connection");
+      return -1;
+    }
+    bytesLeft-=ret;
+  }
+  return buf[0]*256+buf[1];
+}
+
+void TCPNameserver::getQuestion(int fd, char *mesg, int pktlen, const struct sockaddr_in &remote)
+{
+  int ret=0, bytesread=0;
+  while(bytesread<pktlen) {
+    if((ret=waitForData(fd,s_timeout))<0 || (ret=recv(fd,mesg+bytesread,pktlen-bytesread,0))<=0)
+      goto err;
+
+    bytesread+=ret;
+  }
+  return;
+
+ err:;
+  if(ret<0) 
+    throw AhuException("Error reading DNS data from TCP client "+string(inet_ntoa(remote.sin_addr))+": "+stringerror());
+  else 
+    throw AhuException("Remote TCP client "+string(inet_ntoa(remote.sin_addr))+" closed connection");
+}
+
+void *TCPNameserver::doConnection(void *data)
+{
+  int fd=(int)data; // gotta love C
+  pthread_detach(pthread_self());
+
+  try {
+    if(!s_P) {
+      L<<Logger::Error<<"TCP server is without backend connections, launching"<<endl;
+      s_P=new PacketHandler;
+    }
+    char mesg[512];
+    
+    DLOG(L<<"TCP Connection accepted on fd "<<fd<<endl);
+    
+    for(;;) {
+      struct sockaddr_in remote;
+      
+      int pktlen=readLength(fd, &remote);
+      if(pktlen<0) // EOF
+       break;
+
+      if(pktlen>511) {
+       L<<Logger::Error<<"Received an overly large question from "<<inet_ntoa(remote.sin_addr)<<", dropping"<<endl;
+       break;
+      }
+      
+      getQuestion(fd,mesg,pktlen,remote);
+      S.inc("tcp-queries");      
+      DNSPacket *packet=new DNSPacket;
+
+      if(packet->parse(mesg, pktlen)<0)
+       break;
+
+      packet->setRemote((struct sockaddr *)&remote,sizeof(remote));
+
+      if(packet->qtype.getCode()==QType::AXFR) {
+       if(doAXFR(packet->qdomain, packet, fd)) 
+         S.inc("tcp-answers");  
+       continue;
+      }
+
+      if(packet->d.rd && arg().mustDo("recursor")) {
+       // now what
+       // this is a pretty rare event all in all, so we can afford to be slow
+       S.inc("recursing-questions");
+       Resolver res;
+       unsigned int len;
+        DLOG(L<<"About to hand query to recursor"<<endl);
+       ServiceTuple st;
+       st.port=53;
+       parseService(arg()["recursor"],st);
+
+       char *buffer=res.sendReceive(st.host,st.port,packet->getRaw(),packet->len,&len);
+        DLOG(L<<"got an answer from recursor: "<<len<<" bytes, "<<(int)buffer<<endl);
+       if(buffer) {
+         sendData(buffer,len,fd);
+         DLOG(L<<"sent out to customer: "<<len<<" bytes"<<endl);
+         delete buffer;
+         S.inc("recursing-answers");
+         S.inc("tcp-answers");  
+       }
+       continue;
+      }
+
+      DNSPacket* cached=new DNSPacket;
+      if(!packet->d.rd && (PC.get(packet, cached))) { // short circuit - does the PacketCache recognize this question?
+       cached->setRemote((struct sockaddr *)(packet->remote), sizeof(struct sockaddr_in));
+       cached->spoofID(packet->d.id);
+       if(sendDelPacket(cached, fd)<0) 
+         goto out;
+
+       S.inc("tcp-answers");
+       continue;
+      }
+      else
+       delete cached;
+      
+      DNSPacket *reply; 
+      {
+       Lock l(&s_plock);
+       reply=s_P->question(packet); // we really need to ask the backend :-)
+      }
+
+      delete packet;
+       
+      if(!reply)  // unable to write an answer?
+       break;
+       
+      S.inc("tcp-answers");
+      sendDelPacket(reply, fd);
+    }
+    
+  out:;
+  }
+  catch(AhuException &ae) {
+    L<<Logger::Error<<"TCP nameserver: "<<ae.reason<<endl;
+  }
+  catch(PacketHandler::DBException &e) {
+    L<<Logger::Error<<"TCP Connection Thread unable to answer a question because of a backend error"<<endl;
+  }
+  catch(exception &e) {
+    L<<Logger::Error<<"TCP Connection Thread died because of STL error: "<<e.what()<<endl;
+  }
+  catch( ... )
+  {
+    L << Logger::Error << "TCP Connection Thread caught unknown exception." << endl;
+  }
+  Utility::closesocket(fd);
+  d_connectionroom_sem->post();
+
+  return 0;
+}
+
+static bool canDoAXFR(DNSPacket *q)
+{
+  if(!arg().mustDo("disable-axfr")) // default is 'everybody can do axfr'
+    return true;
+
+  vector<string>parts;
+  stringtok(parts,arg()["allow-axfr-ips"],", "); // is this IP on the guestlist?
+  for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
+    if(matchNetmask(q->getRemote().c_str(),i->c_str())==1)
+      return true;
+  }
+
+  extern CommunicatorClass Communicator;
+
+  if(Communicator.justNotified(q->qdomain, q->getRemote())) { // we just notified this ip 
+    L<<Logger::Warning<<"Approved AXFR of '"<<q->qdomain<<"' from recently notified slave "<<q->getRemote()<<endl;
+    return true;
+  }
+
+  return false;
+}
+
+/** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
+int TCPNameserver::doAXFR(const string &target, DNSPacket *q, int outsock)
+{
+  DNSPacket *outpacket=0;
+  if(!canDoAXFR(q)) {
+    DLOG(L<<"AXFR denied for "<<q->getRemote()<<endl);
+
+    outpacket=q->replyPacket();
+    outpacket->setRcode(RCode::Refused); 
+    // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
+    sendDelPacket(outpacket,outsock);
+    return 0;
+  }
+
+  outpacket=q->replyPacket();
+
+  DNSResourceRecord soa;  
+  DNSResourceRecord rr;
+
+  SOAData sd;
+  {
+    Lock l(&s_plock);
+    
+    // find domain_id via SOA and list complete domain. No SOA, no AXFR
+    
+    DLOG(L<<"Looking for SOA"<<endl);
+
+    if(!s_P->getBackend()->getSOA(target,sd)) {
+      outpacket->setRcode(9); // 'NOTAUTH'
+      sendDelPacket(outpacket,outsock);
+      return 0;
+    }
+    soa.qname=target;
+    soa.qtype=QType::SOA;
+    soa.content=DNSPacket::serializeSOAData(sd);
+    soa.ttl=sd.default_ttl;
+    soa.domain_id=sd.domain_id;
+    soa.d_place=DNSResourceRecord::ANSWER;
+  }
+  DLOG(L<<"Issuing list command - opening dedicated database connection"<<endl);
+  PacketHandler P;
+  DNSBackend *B=P.getBackend();
+
+  // now list zone
+  if(!(B->list(sd.domain_id))) {
+    L<<Logger::Error<<"Backend signals error condition"<<endl;
+    outpacket->setRcode(2); // 'SERVFAIL'
+    sendDelPacket(outpacket,outsock);
+    return 0;
+  }
+
+  /* write first part of answer */
+
+  DLOG(L<<"Sending out SOA"<<endl);
+  outpacket->addRecord(soa); // AXFR format begins and ends with a SOA record, so we add one
+  sendDelPacket(outpacket, outsock);
+
+  /* now write all other records */
+
+  int count=0;
+  int chunk=100; // FIXME: this should probably be autosizing
+  if(arg().mustDo("strict-rfc-axfrs"))
+    chunk=1;
+
+  outpacket=q->replyPacket();
+  outpacket->setCompress(false);
+
+  while(B->get(rr)) {
+    if(rr.qtype.getCode()==6)
+      continue; // skip SOA - would indicate end of AXFR
+
+    outpacket->addRecord(rr);
+
+    if(!((++count)%chunk)) {
+      count=0;
+    
+      if(sendDelPacket(outpacket, outsock)<0)  // FIXME: this leaks memory!
+       return 0;
+
+      outpacket=q->replyPacket();  
+      outpacket->setCompress(false);
+      // FIXME: Subsequent messages SHOULD NOT have a question section, though the final message MAY.
+    }
+  }
+  if(count) {
+    sendDelPacket(outpacket, outsock);
+  }
+
+  DLOG(L<<"Done writing out records"<<endl);
+  /* and terminate with yet again the SOA record */
+  outpacket=q->replyPacket();
+  outpacket->addRecord(soa);
+  sendDelPacket(outpacket, outsock);
+  DLOG(L<<"last packet - close"<<endl);
+
+  return 1;
+}
+
+TCPNameserver::~TCPNameserver()
+{
+  delete d_connectionroom_sem;
+}
+
+TCPNameserver::TCPNameserver()
+{
+//  sem_init(&d_connectionroom_sem,0,arg().asNum("max-tcp-connections"));
+  d_connectionroom_sem = new Semaphore( arg().asNum( "max-tcp-connections" ));
+
+  s_timeout=10;
+  vector<string>locals;
+  stringtok(locals,arg()["local-address"]," ,");
+
+  vector<string>locals6;
+  stringtok(locals6,arg()["local-ipv6"]," ,");
+
+
+  if(locals.empty() && locals6.empty())
+    throw AhuException("No local address specified");
+
+  d_highfd=0;
+
+#ifndef WIN32
+  signal(SIGPIPE,SIG_IGN);
+#endif // WIN32
+  FD_ZERO(&d_rfds);  
+
+  for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
+    struct sockaddr_in local;
+    int s=socket(AF_INET,SOCK_STREAM,0); 
+
+    if(s<0) 
+      throw AhuException("Unable to acquire TCP socket: "+stringerror());
+    
+    memset(&local,0,sizeof(local));
+    local.sin_family=AF_INET;
+
+    struct hostent *h;
+    
+    if ( *laddr == "0.0.0.0" )
+    {
+      local.sin_addr.s_addr = INADDR_ANY;
+    }
+    else 
+    {
+      h=gethostbyname(laddr->c_str());
+  
+      if(!h)
+        throw AhuException("Unable to resolve local address '"+*laddr+"'");
+
+      local.sin_addr.s_addr=*(int*)h->h_addr;
+    }
+      
+    int tmp=1;
+    if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
+      L<<Logger::Error<<"Setsockopt failed"<<endl;
+      exit(1);  
+    }
+
+    local.sin_port=htons(arg().asNum("local-port"));
+    
+    if(bind(s, (sockaddr*)&local,sizeof(local))<0) {
+      L<<Logger::Error<<"binding to TCP socket: "<<strerror(errno)<<endl;
+      throw AhuException("Unable to bind to TCP socket");
+    }
+    
+    listen(s,128);
+    L<<Logger::Error<<"TCP server bound to "<<*laddr<<":"<<arg()["local-port"]<<endl;
+    d_sockets.push_back(s);
+    FD_SET(s, &d_rfds);
+    d_highfd=max(s,d_highfd);
+  }
+
+  // TODO: Implement ipv6
+#ifndef WIN32
+  for(vector<string>::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) {
+    struct sockaddr_in6 local;
+    int s=socket(AF_INET6,SOCK_STREAM,0); 
+
+    if(s<0) 
+      throw AhuException("Unable to acquire TCPv6 socket: "+stringerror());
+    
+    memset(&local,0,sizeof(local));
+    local.sin6_family=AF_INET6;
+    struct hostent *h;
+    h=gethostbyname2(laddr->c_str(),AF_INET6);
+  
+    if(!h)
+      throw AhuException("Unable to resolve local address '"+*laddr+"'");
+      
+    memcpy(&local.sin6_addr.s6_addr,h->h_addr,16);
+    local.sin6_port=htons(arg().asNum("local-port"));
+
+    int tmp=1;
+    if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
+      L<<Logger::Error<<"Setsockopt failed"<<endl;
+      exit(1);  
+    }
+
+    if(bind(s, (sockaddr*)&local,sizeof(local))<0) {
+      L<<Logger::Error<<"binding to TCP socket: "<<strerror(errno)<<endl;
+      throw AhuException("Unable to bind to TCPv6 socket");
+    }
+    
+    listen(s,128);
+    L<<Logger::Error<<"TCPv6 server bound to "<<*laddr<<":"<<arg()["local-port"]<<endl;
+    d_sockets.push_back(s);
+    FD_SET(s, &d_rfds);
+    d_highfd=max(s,d_highfd);
+  }
+#endif // WIN32
+}
+
+
+//! Start of TCP operations thread
+void TCPNameserver::thread()
+{
+  struct timeval tv;
+  tv.tv_sec=1;
+  tv.tv_usec=0;
+  try {
+    for(;;) {
+      int fd;
+      struct sockaddr_in remote;
+      Utility::socklen_t addrlen=sizeof(remote);
+
+      fd_set rfds=d_rfds; 
+
+      select(d_highfd+1, &rfds, 0, 0,  0); // blocks
+      int sock=-1;
+      for(vector<int>::const_iterator i=d_sockets.begin();i!=d_sockets.end();++i) {
+       if(FD_ISSET(*i, &rfds)) {
+         sock=*i;
+         addrlen=sizeof(remote);
+
+         if((fd=accept(sock, (sockaddr*)&remote, &addrlen))<0) {
+           L<<Logger::Error<<"TCP question accept error: "<<strerror(errno)<<endl;
+           
+           if(errno==EMFILE) {
+             L<<Logger::Error<<Logger::NTLog<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
+             exit(1);
+           }
+         }
+         else {
+           pthread_t tid;
+           d_connectionroom_sem->wait(); // blocks if no connections are available
+
+           int room;
+           d_connectionroom_sem->getValue( &room);
+           if(room<1)
+             L<<Logger::Warning<<Logger::NTLog<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
+
+           if(pthread_create(&tid, 0, &doConnection, (void *)fd)) {
+             L<<Logger::Error<<"Error creating thread: "<<stringerror()<<endl;
+             d_connectionroom_sem->post();
+           }
+         }
+       }
+      }
+    }
+  }
+  catch(AhuException &AE) {
+    L<<Logger::Error<<"TCP Namerserver thread dying because of fatal error: "<<AE.reason<<endl;
+  }
+  catch(...) {
+    L<<Logger::Error<<"TCPNameserver dying because of an unexpected fatal error"<<endl;
+  }
+  exit(1); // take rest of server with us
+}
+
+
diff --git a/pdns/tcpreceiver.hh b/pdns/tcpreceiver.hh
new file mode 100644 (file)
index 0000000..60684bb
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef PDNS_TCPRECEIVER_HH
+#define PDNS_TCPRECEIVER_HH
+
+#include "dns.hh"
+#include "dnsbackend.hh"
+#include "packethandler.hh"
+#include <vector>\r
+\r
+#ifndef WIN32
+# include <sys/select.h>\r
+# include <sys/socket.h>\r
+# include <netinet/in.h>\r
+# include <arpa/inet.h>\r
+# include <sys/stat.h>\r
+# include <unistd.h>\r
+# include <netdb.h>\r
+# include <sys/uio.h>\r
+# include <sys/select.h>\r
+#endif // WIN32
+
+using namespace std;
+
+class TCPNameserver
+{
+public:
+  TCPNameserver();\r
+  ~TCPNameserver();
+  void go();
+private:
+
+  static int sendDelPacket(DNSPacket *p, int outsock);
+  static int readLength(int fd, struct sockaddr_in *remote);
+  static void getQuestion(int fd, char *mesg, int pktlen, const struct sockaddr_in &remote);
+  static int doAXFR(const string &target, DNSPacket *q, int outsock);
+  static void *doConnection(void *data);
+  static void *launcher(void *data);
+  void thread(void);
+  static pthread_mutex_t s_plock;
+  static PacketHandler *s_P;
+  pthread_t d_tid;
+  static Semaphore *d_connectionroom_sem;
+
+  vector<int>d_sockets;
+  int d_highfd;
+  fd_set d_rfds;
+  static int s_timeout;
+};
+
+#endif /* PDNS_TCPRECEIVER_HH */
diff --git a/pdns/ueberbackend.cc b/pdns/ueberbackend.cc
new file mode 100644 (file)
index 0000000..e8e7ef0
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// $Id: ueberbackend.cc,v 1.1 2002/11/27 15:18:33 ahu Exp $ 
+/* (C) Copyright 2002 PowerDNS.COM BV */\r
+#include "utility.hh"
+#include <string>
+#include <map>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <iostream>
+#include <sstream>
+#include <functional>
+
+#include "dns.hh"
+#include "arguments.hh"
+#include "dnsbackend.hh"
+#include "ueberbackend.hh"
+#include "dnspacket.hh"
+#include "logger.hh"
+#include "statbag.hh"
+#include "packetcache.hh"
+
+extern StatBag S;
+
+vector<UeberBackend *>UeberBackend::instances;
+pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER;
+
+sem_t UeberBackend::d_dynserialize;
+string UeberBackend::programname;
+string UeberBackend::s_status;
+
+// initially we are blocked
+bool UeberBackend::d_go=false;
+pthread_mutex_t  UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER;
+
+int UeberBackend::s_s=-1; // ?
+
+//! Loads a module and reports it to all UeberBackend threads
+bool UeberBackend::loadmodule(const string &name)
+{
+  // TODO: Implement dynamic loading?
+#if !defined(WIN32) && !defined(DARWIN)
+  void *dlib=dlopen(name.c_str(), RTLD_NOW);
+  
+  if(dlib == NULL) {
+    L<<Logger::Warning <<"Unable to load module '"<<name<<"': "<<dlerror() << endl; 
+    return false;
+  }
+  
+  return true;
+
+#else
+  L << Logger::Warning << "This version doesn't support dynamic loading (yet)." << endl;
+   return false;
+
+#endif // WIN32
+
+}
+
+void UeberBackend::go(void)
+{
+  pthread_mutex_lock(&d_mut);
+  d_go=true;
+  pthread_cond_broadcast(&d_cond);
+  pthread_mutex_unlock(&d_mut);
+}
+
+bool UeberBackend::getDomainInfo(const string &domain, DomainInfo &di)
+{
+  for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
+    if((*i)->getDomainInfo(domain, di))
+      return true;
+  return false;
+}
+
+void UeberBackend::reload()
+{
+  for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
+  {
+    ( *i )->reload();
+  }
+}
+
+void UeberBackend::rediscover()
+{
+  for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
+  {
+    ( *i )->rediscover();
+  }
+}
+
+
+void UeberBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
+{
+  for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
+  {
+    ( *i )->getUnfreshSlaveInfos( domains );
+  }  
+}
+
+
+
+void UeberBackend::getUpdatedMasters(vector<DomainInfo>* domains)
+{
+  for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
+  {
+    ( *i )->getUpdatedMasters( domains );
+  }
+}
+
+
+bool UeberBackend::getSOA(const string &domain, SOAData &sd)
+{
+  d_question.qtype=QType::SOA;
+  d_question.qname=domain;
+  d_question.zoneId=-1;
+    
+  int cstat=cacheHas(d_question,d_answer);
+  if(cstat==0) {
+    return false;
+  }
+  else if(cstat==1) {
+    // ehm 
+    DNSPacket::fillSOAData(d_answer.content,sd);
+    sd.domain_id=d_answer.domain_id;
+    sd.ttl=d_answer.ttl;
+    cout<<"from cache: sd.ttl: "<<sd.ttl<<endl;
+    return true;
+  }
+    
+
+  for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
+    if((*i)->getSOA(domain, sd)) {
+      DNSResourceRecord rr;
+      rr.qname=domain;
+      rr.qtype=QType::SOA;
+      rr.content=DNSPacket::serializeSOAData(sd);
+      rr.ttl=sd.ttl;
+      cout<<"Set rr.ttl to "<<sd.ttl<<endl;
+      rr.domain_id=sd.domain_id;
+      addOneCache(d_question,rr);
+      return true;
+    }
+
+  addNegCache(d_question); 
+  return false;
+}
+
+bool UeberBackend::superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
+{
+  for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
+    if((*i)->superMasterBackend(ip,domain,nsset,account, db))
+      return true;
+  return false;
+
+}
+
+void UeberBackend::setStatus(const string &st)
+{
+  s_status=st;
+}
+
+UeberBackend::UeberBackend()
+{
+  UeberBackend("default");
+}
+
+UeberBackend::UeberBackend(const string &pname)
+{
+  programname=pname;
+  pthread_mutex_lock(&instances_lock);
+  instances.push_back(this); // report to the static list of ourself
+  pthread_mutex_unlock(&instances_lock);
+
+  tid=pthread_self(); 
+  stale=false;
+
+  backends=BackendMakers().all();
+}
+
+void UeberBackend::die()
+{
+  cleanup();
+  stale=true;
+}
+
+void del(DNSBackend* d)
+{
+  delete d;
+}
+
+void UeberBackend::cleanup()
+{
+  pthread_mutex_lock(&instances_lock);
+
+  remove(instances.begin(),instances.end(),this);
+  instances.resize(instances.size()-1);
+
+  pthread_mutex_unlock(&instances_lock);
+
+  for_each(backends.begin(),backends.end(),del);
+}
+
+int UeberBackend::cacheHas(const Question &q, DNSResourceRecord &rr)
+{
+  extern PacketCache PC;
+  static int *qcachehit=S.getPointer("query-cache-hit");
+  static int *qcachemiss=S.getPointer("query-cache-miss");
+
+  static int negqueryttl=arg().asNum("negquery-cache-ttl");
+  static int queryttl=arg().asNum("query-cache-ttl");
+  if(!negqueryttl && !queryttl) {
+    (*qcachemiss)++;
+    return -1;
+  }
+
+  string content;
+  //  L<<Logger::Warning<<"looking up: "<<q.qname+"|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
+  bool ret=PC.getKey(q.qname+"|Q|"+q.qtype.getName()+"|"+itoa(q.zoneId), content);   // think about lowercasing here
+
+  if(!ret) {
+    (*qcachemiss)++;
+    return -1;
+  }
+
+  (*qcachehit)++;
+  if(content.empty())
+    return 0;
+  rr.unSerialize(content);
+  return 1;
+}
+
+void UeberBackend::addNegCache(const Question &q)
+{
+  extern PacketCache PC;
+  static int negqueryttl=arg().asNum("negquery-cache-ttl");
+  if(!negqueryttl)
+    return;
+  //  L<<Logger::Warning<<"negative inserting: "<<q.qname+"|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
+  PC.insert(q.qname+"|Q|"+q.qtype.getName()+"|"+itoa(q.zoneId),"",negqueryttl);
+}
+
+void UeberBackend::addOneCache(const Question &q, const DNSResourceRecord &rr)
+{
+  extern PacketCache PC;
+  static int queryttl=arg().asNum("query-cache-ttl");
+  if(!queryttl)
+    return;
+
+  PC.insert(q.qname+"|Q|"+q.qtype.getName()+"|"+itoa(q.zoneId),rr.serialize(),queryttl);
+}
+
+
+UeberBackend::~UeberBackend()
+{
+  DLOG(L<<Logger::Error<<"UeberBackend destructor called, removing ourselves from instances, and deleting our backends"<<endl);
+  cleanup();
+}
+
+// this handle is more magic than most
+void UeberBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int zoneId)
+{
+  if(stale) {
+    L<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
+    throw AhuException("We are stale, please recycle");
+  }
+
+  DLOG(L<<"UeberBackend received question for "<<qtype.getName()<<" of "<<qname<<endl);
+  if(!d_go) {
+    pthread_mutex_lock(&d_mut);
+    while (d_go==false) {
+      L<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
+      pthread_cond_wait(&d_cond, &d_mut);
+      L<<Logger::Error<<"Broadcast received, unblocked"<<endl;
+    }
+    pthread_mutex_unlock(&d_mut);
+  }
+
+  d_handle.i=0;
+  d_handle.qtype=qtype;
+  d_handle.qname=qname;
+  d_handle.pkt_p=pkt_p;
+  d_ancount=0;
+
+  if(!backends.size()) {
+    L<<Logger::Error<<Logger::NTLog<<"No database backends available - unable to answer questions."<<endl;
+    stale=true; // please recycle us! 
+    throw AhuException("We are stale, please recycle");
+  }
+  else {
+    d_question.qtype=qtype;
+    d_question.qname=qname;
+    d_question.zoneId=zoneId;
+    int cstat=cacheHas(d_question,d_answer);
+    if(cstat<0) { // nothing
+      d_negcached=d_cached=false;
+      (d_handle.d_hinterBackend=backends[d_handle.i++])->lookup(qtype, qname,pkt_p,zoneId);
+    } 
+    else if(cstat==0) {
+      d_negcached=true;
+      d_cached=false;
+    }
+    else {
+      d_negcached=false;
+      d_cached=true;
+    }
+  }
+
+  d_handle.parent=this;
+
+}
+
+bool UeberBackend::get(DNSResourceRecord &rr)
+{
+  if(d_negcached) {
+    return false; 
+  }
+
+  if(d_cached) {
+    rr=d_answer;
+    d_negcached=true; // ugly, confusing 
+    return true;
+  }
+
+  if(!d_handle.get(rr)) {
+    if(!d_ancount && !d_handle.qname.empty()) // don't cache axfr
+      addNegCache(d_question);
+
+    if(d_ancount==1) {
+      addOneCache(d_question,lastrr);
+    }
+
+    return false;
+  }
+
+  if(!d_ancount++) {
+    lastrr=rr;
+  }
+  return true;
+}
+
+bool UeberBackend::list(int domain_id)
+{
+  d_cached=d_negcached=false;
+  d_ancount=0;
+  if(stale) {
+    L<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
+    throw AhuException("We are stale, please recycle");
+  }
+
+  DLOG(L<<"UeberBackend received list request for domain id "<<domain_id<<endl);
+
+  pthread_mutex_lock(&d_mut);
+  while (d_go==false) {
+    L<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
+    pthread_cond_wait(&d_cond, &d_mut);
+    L<<Logger::Error<<"Broadcast received, unblocked"<<endl;
+  }
+
+  pthread_mutex_unlock(&d_mut);
+
+  d_handle.i=0;
+  d_handle.pkt_p=0;
+  d_handle.qname="";
+  d_negcached=false;
+
+  if(!backends.size()) {
+    return 0; // we failed
+  }
+  else {
+    while(!(d_handle.d_hinterBackend=backends[d_handle.i++])->list(domain_id) && d_handle.i<backends.size())
+      ;
+  }
+  d_handle.parent=this;
+
+  return true;
+}
+
+int UeberBackend::handle::instances=0;
+
+UeberBackend::handle::handle()
+{
+  //  L<<Logger::Warning<<"Handle instances: "<<instances<<endl;
+  instances++;
+}
+
+UeberBackend::handle::~handle()
+{
+  instances--;
+}
+
+
+
+
+
+bool UeberBackend::handle::get(DNSResourceRecord &r)
+{
+  DLOG(L << "Ueber get() was called for a "<<qtype.getName()<<" record" << endl);
+  bool isMore=false;
+  while(d_hinterBackend && !(isMore=d_hinterBackend->get(r))) { // this backend out of answers
+    if(i<parent->backends.size()) {
+      DLOG(L<<"Backend #"<<i<<" of "<<parent->backends.size()
+          <<" out of answers, taking next"<<endl);
+      
+      d_hinterBackend=parent->backends[i++];
+      d_hinterBackend->lookup(qtype,qname,pkt_p);
+    }
+    else 
+      break;
+
+    DLOG(L<<"Now asking backend #"<<i<<endl);
+  }
+
+  if(!isMore && i==parent->backends.size()) {
+    DLOG(L<<"UeberBackend reached end of backends"<<endl);
+    return false;
+  }
+
+  DLOG(L<<"Found an answering backend - will not try another one"<<endl);
+  i=parent->backends.size(); // don't go on to the next backend
+  return true;
+}
diff --git a/pdns/ueberbackend.hh b/pdns/ueberbackend.hh
new file mode 100644 (file)
index 0000000..79d8128
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef UEBERBACKEND_HH
+#define UEBERBACKEND_HH
+
+#include <vector>
+#include <map>
+#include <string>
+#include <algorithm>
+#include <pthread.h>
+#include <semaphore.h>\r
+\r
+#ifndef WIN32\r
+#include <sys/un.h>\r
+#include <dlfcn.h>\r
+#include <unistd.h>\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#endif // WIN32\r
+
+#include "dnspacket.hh"
+#include "dnsbackend.hh"
+
+using namespace std;
+
+class BackendReporter;
+
+/** This is a very magic backend that allows us to load modules dynamically,
+    and query them in order. This is persistent over all UeberBackend instantiations
+    across multiple threads. Very magic */
+
+class UeberBackend : public DNSBackend
+{
+public:
+  UeberBackend();
+  UeberBackend(const string &);
+  ~UeberBackend();
+  typedef DNSBackend *BackendMaker(); //!< typedef for functions returning pointers to new backends
+
+  bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db);
+
+  /** contains BackendReporter objects, which contain maker functions and information about
+      weather a module has already been reported to existing instances of the UeberBackend
+  */
+  static vector<BackendReporter>backendmakers;
+
+  /** Tracks all created UeberBackend instances for us. We use this vector to notify
+      existing threads of new modules 
+  */
+  static vector<UeberBackend *>instances;
+  static pthread_mutex_t instances_lock;
+
+  static bool loadmodule(const string &name);
+
+  /** Thread function that listens on our unix domain socket for commands, for example
+      instructions to load new modules */
+  static void *DynListener(void *);
+  static void go(void);
+
+  
+  /** This contains all registered backends. The DynListener modifies this list for us when
+      new modules are loaded */
+  vector<DNSBackend*>backends; 
+
+  void die();
+  void cleanup();
+
+  //! the very magic handle for UeberBackend questions
+  class handle
+  {
+  public:
+    bool get(DNSResourceRecord &r);
+    handle();
+    ~handle();
+
+    //! The UeberBackend class where this handle belongs to
+    UeberBackend *parent;
+    //! The current real backend, which is answering questions
+    DNSBackend *d_hinterBackend;
+
+    //! Index of the current backend within the backends vector
+    unsigned int i;
+
+    //! DNSPacket who asked this question
+    DNSPacket *pkt_p;
+    string qname;
+    QType qtype;
+  private:
+
+    static int instances;
+  };
+
+  void lookup(const QType &, const string &qdomain, DNSPacket *pkt_p=0,  int zoneId=-1);
+
+  bool getSOA(const string &domain, SOAData &sd);
+  bool list(int domain_id);
+  bool get(DNSResourceRecord &r);
+
+  static DNSBackend *maker(const map<string,string> &);
+  static void closeDynListener();
+  static void UeberBackend::setStatus(const string &st);
+  void getUnfreshSlaveInfos(vector<DomainInfo>* domains);
+  void getUpdatedMasters(vector<DomainInfo>* domains);
+  bool getDomainInfo(const string &domain, DomainInfo &di);
+  void rediscover();
+  void reload();
+private:
+  DNSResourceRecord lastrr;
+  pthread_t tid;
+  handle d_handle;
+  bool d_negcached;
+  bool d_cached;
+  struct Question
+  {
+    QType qtype;
+    string qname;
+    int zoneId;
+  }d_question;
+  DNSResourceRecord d_answer;
+
+  int cacheHas(const Question &q, DNSResourceRecord &rr);
+  void addNegCache(const Question &q);
+  void addOneCache(const Question &q, const DNSResourceRecord &rr);
+  
+  static pthread_mutex_t d_mut;
+  static pthread_cond_t d_cond;
+  static sem_t d_dynserialize;
+  static bool d_go;
+  static int s_s;
+  static string s_status; 
+  int d_ancount;
+  static string programname;
+  bool stale;
+};
+
+
+/** Class used to report new backends. It stores a maker function, and a flag that indicates that 
+    this module has been reported */
+class BackendReporter
+{
+public:
+  BackendReporter(UeberBackend::BackendMaker *p)
+  {
+    maker=p;
+    reported=false;
+  };
+  map<string,string>d_parameters;
+  UeberBackend::BackendMaker *maker; //!< function to make this backend
+  bool reported; //!< if this backend has been reported to running UeberBackend threads 
+private:
+};
+
+#endif
diff --git a/pdns/unix_utility.cc b/pdns/unix_utility.cc
new file mode 100644 (file)
index 0000000..7f2ccae
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// Utility class win32 implementation.
+
+#include "utility.hh"
+#include <cstring>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h> 
+#include "ahuexception.hh"
+#include "logger.hh"
+#include "misc.hh"
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+
+using namespace std;
+
+// Closes a socket.
+int Utility::closesocket( Utility::sock_t socket )
+{
+  return ::close( socket );
+}
+
+bool Utility::setNonBlocking(sock_t sock)
+{
+  int flags=fcntl(sock,F_GETFL,0);    
+  if(flags<0 || fcntl(sock, F_SETFL,flags|O_NONBLOCK) <0)
+    return false;
+  return true;
+}
+
+bool Utility::setBlocking(sock_t sock)
+{
+  int flags=fcntl(sock,F_GETFL,0);    
+  if(flags<0 || fcntl(sock, F_SETFL,flags&(~O_NONBLOCK)) <0)
+    return false;
+  return true;
+}
+
+const char *Utility::inet_ntop(int af, const char *src, char *dst, size_t size)
+{
+  return const_cast<char *>(::inet_ntop(af,src,dst,size));
+}
+
+unsigned int Utility::sleep(unsigned int sec)
+{
+  return ::sleep(sec);
+}
+
+void Utility::usleep(unsigned long usec)
+{
+  ::usleep(usec);
+}
+
+
+// Drops the program's privileges.
+void Utility::dropPrivs( int uid, int gid )
+{
+  if(gid) {
+    if(setgid(gid)<0) {
+      theL()<<Logger::Error<<"Unable to set effective group id to "<<gid<<": "<<stringerror()<<endl;
+      exit(1);
+    }
+    else
+      theL()<<Logger::Error<<"Set effective group id to "<<uid<<endl;
+
+  }
+
+  if(uid) {
+    if(setuid(uid)<0) {
+      theL()<<Logger::Error<<"Unable to set effective user id to "<<uid<<":  "<<stringerror()<<endl;
+      exit(1);
+    }
+    else
+      theL()<<Logger::Error<<"Set effective user id to "<<uid<<endl;
+  }
+}
+
+
+// Returns the current process id.
+Utility::pid_t Utility::getpid( void )
+{
+  return ::getpid();
+}
+
+
+// Returns the current time.
+int Utility::gettimeofday( struct timeval *tv, void *tz )
+{
+  return ::gettimeofday(tv,0);
+}
+
+
+// Converts an address from dot and numbers format to binary data.
+int Utility::inet_aton( const char *cp, struct in_addr *inp )
+{
+  return ::inet_aton(cp,inp);
+
+}
+
+
+// Converts an address from presentation format to network format.
+int Utility::inet_pton( int af, const char *src, void *dst )
+{
+  return ::inet_pton(af, src, dst);
+}
+
+
+// Retrieves a gid using a groupname.
+int Utility::makeGidNumeric(const string &group)
+{
+  int newgid;
+  if(!(newgid=atoi(group.c_str()))) {
+    struct group *gr=getgrnam(group.c_str());
+    if(!gr) {
+      theL()<<Logger::Error<<"Unable to look up gid of group '"<<group<<"': "<<strerror(errno)<<endl;
+      exit(1);
+    }
+    newgid=gr->gr_gid;
+  }
+  return newgid;
+}
+
+
+// Retrieves an uid using a username.
+int Utility::makeUidNumeric(const string &username)
+{
+  int newuid;
+  if(!(newuid=atoi(username.c_str()))) {
+    struct passwd *pw=getpwnam(username.c_str());
+    if(!pw) {
+      theL()<<Logger::Error<<"Unable to look up uid of user '"<<username<<"': "<<strerror(errno)<<endl;
+      exit(1);
+    }
+    newuid=pw->pw_uid;
+  }
+  return newuid;
+}
+
+
+// Returns a random number.
+long int Utility::random( void )
+{
+  return rand();
+}
+
+// Sets the random seed.
+void Utility::srandom( unsigned int seed )
+{
+  ::srandom(seed);
+}
+
+// Compares two string, ignoring the case.
+int Utility::strcasecmp( const char *s1, const char *s2 )
+{
+  return ::strcasecmp( s1, s2 );
+}
+
+
+// Writes a vector.
+int Utility::writev(int socket, const struct iovec *vector, size_t count )
+{
+  return ::writev(socket,vector,count);
+}
+
+#ifdef DARWIN
+
+// Darwin 6.0 Compatible implementation, uses pthreads so it portable across more platforms.
+
+#define SEM_VALUE_MAX 32767
+#define SEM_MAGIC     ((u_int32_t) 0x09fa4012)
+
+Semaphore::Semaphore(unsigned int value)
+{
+  if (value > SEM_VALUE_MAX) {
+    throw AhuException("Cannot create semaphore: value too large");
+  }
+
+  // Initialize
+  
+  if (pthread_mutex_init(&m_lock, NULL) != 0) {
+    throw AhuException("Cannot create semaphore: cannot allocate mutex");
+  }
+
+  if (pthread_cond_init(&m_gtzero, NULL) != 0) {
+    pthread_mutex_destroy(&m_lock);
+    throw AhuException("Cannot create semaphore: cannot allocate condition");
+  }
+
+  m_count = (u_int32_t) value;
+  m_nwaiters = 0;
+  m_magic = SEM_MAGIC;
+}
+
+int Semaphore::post()
+{
+  pthread_mutex_lock(&m_lock);
+
+  m_count++;
+  if (m_nwaiters > 0) {
+    pthread_cond_signal(&m_gtzero);
+  }
+
+  pthread_mutex_unlock(&m_lock);
+
+  return 0;
+}
+
+int Semaphore::wait()
+{
+  pthread_mutex_lock(&m_lock);
+  
+  while (m_count == 0) {
+    m_nwaiters++;
+    pthread_cond_wait(&m_gtzero, &m_lock);
+    m_nwaiters--;
+  }
+  
+  m_count--;
+
+  pthread_mutex_unlock(&m_lock);
+
+  return 0;
+}
+
+int Semaphore::tryWait()
+{
+  int retval = 0;
+
+  pthread_mutex_lock(&m_lock);
+
+  if (m_count > 0) {
+    m_count--;
+  } else {
+    errno = EAGAIN;
+    retval = -1;
+  }
+
+  pthread_mutex_unlock(&m_lock);
+  return retval;
+}
+
+int Semaphore::getValue(Semaphore::sem_value_t *sval)
+{
+  pthread_mutex_lock(&m_lock);
+  *sval = m_count;
+  pthread_mutex_unlock(&m_lock);
+
+  return 0;
+}
+
+Semaphore::~Semaphore()
+{
+  // Make sure there are no waiters.
+  
+  pthread_mutex_lock(&m_lock);
+  if (m_nwaiters > 0) {
+    pthread_mutex_unlock(&m_lock);
+    //errno = EBUSY;
+    //return -1;
+  }
+  pthread_mutex_unlock(&m_lock);
+
+  // Destroy it.
+
+  pthread_mutex_destroy(&m_lock);
+  pthread_cond_destroy(&m_gtzero);
+  m_magic = 0;
+
+  //return 0;
+}
+
+#else /* not DARWIN from here on */
+
+
+Semaphore::Semaphore(unsigned int value)
+{
+  m_pSemaphore=new sem_t;
+  if (sem_init(m_pSemaphore, 0, value) == -1) {
+    theL() << Logger::Error << "Cannot create semaphore: " << stringerror() << endl;
+    exit(1);
+  }
+}
+
+int Semaphore::post()
+{
+  return sem_post(m_pSemaphore);
+}
+
+int Semaphore::wait()
+{
+  return sem_wait(m_pSemaphore);
+}
+int Semaphore::tryWait()
+{
+  return sem_trywait(m_pSemaphore);
+}
+
+int Semaphore::getValue(Semaphore::sem_value_t *sval)
+{
+  return sem_getvalue(m_pSemaphore, sval);
+}
+
+Semaphore::~Semaphore()
+{
+}
+
+#endif
diff --git a/pdns/utility.hh b/pdns/utility.hh
new file mode 100644 (file)
index 0000000..9addf23
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+// Utility class specification.
+
+#ifndef UTILITY_HH
+#define UTILITY_HH
+
+#ifndef WIN32
+# include <arpa/inet.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <sys/time.h>
+# include <sys/uio.h>
+# include <signal.h>
+# include <pthread.h>
+# include <semaphore.h>
+# include <signal.h>
+# include <errno.h>
+#else
+// Disable debug info truncation warning.
+# pragma warning ( disable: 4786 )
+# pragma warning ( disable: 4503 )
+# pragma warning ( disable: 4101 )
+
+# define WINDOWS_LEAN_AND_MEAN
+# include <windows.h>
+# include <signal.h>
+# include <map>
+
+// For scope fix.
+# define for if ( false ) {} else for
+
+# define ETIMEDOUT    WSAETIMEDOUT
+# define EINPROGRESS  WSAEWOULDBLOCK
+
+# define AF_INET6 -1
+
+# define VERSION "2.0rc1-WIN32"
+
+# define snprintf _snprintf
+
+// Custom bittypes.
+typedef unsigned char int8_t;
+typedef unsigned int  int16_t;
+typedef unsigned long int32_t;
+typedef unsigned char u_int8_t;
+typedef unsigned int  u_int16_t;
+typedef unsigned long u_int32_t;
+
+#endif // WIN32
+
+#include <semaphore.h>
+#include <string>
+
+using namespace std;
+
+
+//! A semaphore class.
+class Semaphore
+{
+private:
+  sem_t *m_pSemaphore;
+#ifdef WIN32
+  typedef int sem_value_t;
+
+  //! The semaphore.
+
+
+
+  //! Semaphore counter.
+  long m_counter;
+
+#else
+  typedef int sem_value_t;
+
+  u_int32_t       m_magic;
+  pthread_mutex_t m_lock;
+  pthread_cond_t  m_gtzero;
+  sem_value_t     m_count;
+  u_int32_t       m_nwaiters;
+#endif
+
+protected:
+public:
+  //! Default constructor.
+  Semaphore( unsigned int value = 0 );
+
+  //! Destructor.
+  ~Semaphore( void );
+  
+  //! Posts to a semaphore.
+  int post( void );
+
+  //! Waits for a semaphore.
+  int wait( void );
+
+  //! Tries to wait for a semaphore.
+  int tryWait( void );
+  
+  //! Retrieves the semaphore value.
+  int getValue( Semaphore::sem_value_t *sval );
+  
+};
+
+
+//! This is a utility class used for platform independant abstraction.
+class Utility
+{
+#ifdef WIN32
+private:
+  static int inet_pton4( const char *src, void *dst );
+  static int inet_pton6( const char *src, void *dst );
+
+  static const char *inet_ntop4( const char *src, char *dst, size_t size );
+  static const char *inet_ntop6( const char *src, char *dst, size_t size );
+
+#endif // WIN32
+
+public:
+#ifdef WIN32
+
+  //! iovec structure for windows.
+  typedef struct 
+  {
+    void  *iov_base;  //!< Base address.
+    size_t iov_len;   //!< Number of bytes.
+  } iovec;
+
+  // A few type defines.
+  typedef DWORD     pid_t;
+  typedef SOCKET    sock_t;
+  typedef int       socklen_t;
+  
+#else
+  typedef ::iovec iovec;
+  typedef ::pid_t     pid_t;
+  typedef int       sock_t;
+  typedef ::socklen_t        socklen_t;
+  
+#endif // WIN32
+
+  //! Closes a socket.
+  static int closesocket( sock_t socket );
+
+  //! Returns the process id of the current process.
+  static pid_t getpid( void );
+
+  //! Gets the current time.
+  static int gettimeofday( struct timeval *tv, void *tz = NULL );
+
+  //! Converts an address from dot and numbers format to binary data.
+  static int inet_aton( const char *cp, struct in_addr *inp );
+
+  //! Converts an address from presentation format to network format.
+  static int inet_pton( int af, const char *src, void *dst );
+
+  //! The inet_ntop() function converts an address from network format (usually a struct in_addr or some other binary form, in network byte order) to presentation format.
+  static const char *inet_ntop( int af, const char *src, char *dst, size_t size );
+
+  //! Retrieves a gid using a groupname.
+  static int makeGidNumeric( const string & group );
+  
+  //! Retrieves an uid using an username.
+  static int makeUidNumeric( const string & username );
+
+  //! Writes a vector.
+  static int writev( Utility::sock_t socket, const iovec *vector, size_t count );
+  //! Returns a random number.
+  static long int random( void );
+
+  //! Sets the random seed.
+  static void srandom( unsigned int seed );
+
+  //! Compares two strings and ignores case.
+  static int strcasecmp( const char *s1, const char *s2 );
+
+  //! Drops the program's privileges.
+  static void dropPrivs( int uid, int gid );
+  
+  //! Sets the socket into blocking mode.
+  static bool setBlocking( Utility::sock_t socket );
+
+  //! Sets the socket into non-blocking mode.
+  static bool setNonBlocking( Utility::sock_t socket );
+  
+  //! Sleeps for a number of seconds.
+  static unsigned int sleep( unsigned int seconds );
+  
+  //! Sleeps for a number of microseconds.
+  static void usleep( unsigned long usec );
+  
+};
+
+
+#endif // UTILITY_HH
diff --git a/pdns/webserver.cc b/pdns/webserver.cc
new file mode 100644 (file)
index 0000000..8e44666
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "utility.hh"\r
+#include "webserver.hh"
+#include "session.hh"
+#include "misc.hh"
+#include <vector>
+#include "logger.hh"
+#include <stdio.h>
+#include "dns.hh"
+
+
+map<string,WebServer::HandlerFunction *>WebServer::d_functions;
+void *WebServer::d_that;
+string WebServer::d_password;
+
+char WebServer::B64Decode1(char cInChar)
+{
+  // The incoming character will be A-Z, a-z, 0-9, +, /, or =.
+  // The idea is to quickly determine which grouping the
+  // letter belongs to and return the associated value
+  // without having to search the global encoding string
+  // (the value we're looking for would be the resulting
+  // index into that string).
+  //
+  // To do that, we'll play some tricks...
+  unsigned char iIndex = '\0';
+  switch ( cInChar ) {
+  case '+':
+    iIndex = 62;
+    break;
+
+  case '/':
+    iIndex = 63;
+    break;
+
+  case '=':
+    iIndex = 0;
+    break;
+
+  default:
+    // Must be 'A'-'Z', 'a'-'z', '0'-'9', or an error...
+    //
+    // Numerically, small letters are "greater" in value than
+    // capital letters and numerals (ASCII value), and capital
+    // letters are "greater" than numerals (again, ASCII value),
+    // so we check for numerals first, then capital letters,
+    // and finally small letters.
+    iIndex = '9' - cInChar;
+    if ( iIndex > 0x3F ) {
+      // Not from '0' to '9'...
+      iIndex = 'Z' - cInChar;
+      if ( iIndex > 0x3F ) {
+       // Not from 'A' to 'Z'...
+       iIndex = 'z' - cInChar;
+       if ( iIndex > 0x3F ) {
+         // Invalid character...cannot
+         // decode!
+         iIndex = 0x80; // set the high bit
+       } // if
+       else {
+         // From 'a' to 'z'
+         iIndex = (('z' - iIndex) - 'a') + 26;
+       } // else
+      } // if
+      else {
+       // From 'A' to 'Z'
+       iIndex = ('Z' - iIndex) - 'A';
+      } // else
+    } // if
+    else {
+      // Adjust the index...
+      iIndex = (('9' - iIndex) - '0') + 52;
+    } // else
+    break;
+
+  } // switch
+
+  return iIndex;
+}
+
+int WebServer::B64Decode(const std::string& strInput, std::string& strOutput)
+{
+  // Set up a decoding buffer
+  long cBuf = 0;
+  char* pBuf = (char*)&cBuf;
+
+  // Decoding management...
+  short iBitGroup = 0, iInNum = 0;
+
+  // While there are characters to process...
+  //
+  // We'll decode characters in blocks of 4, as
+  // there are 4 groups of 6 bits in 3 bytes. The
+  // incoming Base64 character is first decoded, and
+  // then it is inserted into the decode buffer
+  // (with any relevant shifting, as required).
+  // Later, after all 3 bytes have been reconsituted,
+  // we assign them to the output string, ultimately
+  // to be returned as the original message.
+  int iInSize = strInput.size();
+  unsigned char cChar = '\0';
+  while ( iInNum < iInSize ) {
+    // Fill the decode buffer with 4 groups of 6 bits
+    cBuf = 0; // clear
+    for ( iBitGroup = 0; iBitGroup < 4; ++iBitGroup ) {
+      if ( iInNum < iInSize ) {
+       // Decode a character
+       cChar = B64Decode1(strInput.at(iInNum++));
+      } // if
+      else {
+       // Decode a padded zero
+       cChar = '\0';
+      } // else
+
+      // Check for valid decode
+      if ( cChar > 0x7F )
+       return -1;
+
+      // Adjust the bits
+      switch ( iBitGroup ) {
+      case 0:
+       // The first group is copied into
+       // the least significant 6 bits of
+       // the decode buffer...these 6 bits
+       // will eventually shift over to be
+       // the most significant bits of the
+       // third byte.
+       cBuf = cBuf | cChar;
+       break;
+
+      default:
+       // For groupings 1-3, simply shift
+       // the bits in the decode buffer over
+       // by 6 and insert the 6 from the
+       // current decode character.
+       cBuf = (cBuf << 6) | cChar;
+       break;
+
+      } // switch
+    } // for
+
+    // Interpret the resulting 3 bytes...note there
+    // may have been padding, so those padded bytes
+    // are actually ignored.
+    strOutput += pBuf[2];
+    strOutput += pBuf[1];
+    strOutput += pBuf[0];
+  } // while
+
+  return 1;
+}
+
+
+
+
+void WebServer::registerHandler(const string&s, HandlerFunction *ptr)
+{
+  d_functions[s]=ptr;
+}
+
+void WebServer::setCaller(void *that)
+{
+  d_that=that;
+}
+
+void *WebServer::serveConnection(void *p)
+{
+  Session *client=static_cast<Session *>(p);
+  try {
+    string line;
+    client->getLine(line);
+    stripLine(line);
+    //    L<<"page: "<<line<<endl;
+
+    vector<string> parts;
+    stringtok(parts,line);
+    
+    string uri;
+    if(parts.size()>1)
+      uri=parts[1];
+
+    vector<string>variables;
+
+    parts.clear();
+    stringtok(parts,uri,"?");
+
+    //    L<<"baseUrl: '"<<parts[0]<<"'"<<endl;
+    
+    vector<string>urlParts;
+    stringtok(urlParts,parts[0],"/");
+    string baseUrl;
+    if(urlParts.empty())
+      baseUrl="";
+    else
+      baseUrl=urlParts[0];
+
+    //    L<<"baseUrl real: '"<<baseUrl<<"'"<<endl;
+
+    if(parts.size()>1) {
+      stringtok(variables,parts[1],"&");
+    }
+
+    map<string,string>varmap;
+
+    for(vector<string>::const_iterator i=variables.begin();
+       i!=variables.end();++i) {
+
+      parts.clear();
+      stringtok(parts,*i,"=");
+      if(parts.size()>1)
+       varmap[parts[0]]=parts[1];
+      else
+       varmap[parts[0]]="";
+
+      L<<"'"<<parts[0]<<"' = '"<<varmap[parts[0]]<<"'"<<endl;
+    }
+
+    bool authOK=0;
+
+    // read & ignore other lines
+    do {
+      client->getLine(line);
+      stripLine(line);
+
+      if(!line.find("Authorization: Basic ")) {
+       string cookie=line.substr(21);
+       string plain;
+
+       B64Decode(cookie,plain);
+       vector<string>cparts;
+       stringtok(cparts,plain,":");
+
+       if(cparts.size()==2 && !strcmp(cparts[1].c_str(),d_password.c_str())) { // this gets rid of terminating zeros
+         authOK=1;
+       }
+      }
+    }while(!line.empty());
+
+
+    if(!d_password.empty() && !authOK) {
+      client->putLine("HTTP/1.1 401 OK\n");
+      client->putLine("WWW-Authenticate: Basic realm=\"PowerDNS\"\n");
+      
+      client->putLine("Connection: close\n");
+      client->putLine("Content-type: text/html\n\n");
+      client->putLine("Please enter a valid password!\n");
+      client->close();
+      delete client;
+      return 0;
+    }
+
+    HandlerFunction *fptr;
+    if((fptr=d_functions[baseUrl])) {
+      
+      bool custom;
+      string ret=(*fptr)(varmap, d_that, &custom);
+
+      if(!custom) {
+       client->putLine("HTTP/1.1 200 OK\n");
+       client->putLine("Connection: close\n");
+       client->putLine("Content-type: text/html\n\n");
+      }
+      client->putLine(ret);
+    }
+    else {
+      client->putLine("HTTP/1.1 404 Not found\n");
+      client->putLine("Connection: close\n");
+      client->putLine("Content-type: text/html\n\n");
+      // FIXME: CSS problem?
+      client->putLine("<html><body><h1>Did not find file '"+baseUrl+"'</body></html>\n");
+    }
+        
+    client->close();
+    delete client;
+    client=0;
+    return 0;
+
+  }
+  catch(SessionTimeoutException &e) {
+    L<<Logger::Error<<"Timeout in webserver"<<endl;
+  }
+  catch(SessionException &e) {
+    L<<Logger::Error<<"Fatal error in webserver: "<<e.reason<<endl;
+  }
+  catch(Exception &e) {
+    L<<Logger::Error<<"Exception in webserver: "<<e.reason<<endl;
+  }
+  catch(exception &e) {
+    L<<Logger::Error<<"STL Exception in webserver: "<<e.what()<<endl;
+  }
+  catch(...) {
+    L<<Logger::Error<<"Unknown exception in webserver"<<endl;
+  }
+  if(client) {
+    client->close();
+    delete client;
+    client=0;
+  }
+  return 0;
+}
+
+WebServer::WebServer(const string &listenaddress, int port, const string &password)
+{
+  d_listenaddress=listenaddress;
+  d_port=port;
+  d_password=password;
+}
+
+void WebServer::go()
+{
+  try {
+    Server *s=new Server(d_port, d_listenaddress);
+    
+    Session *client;
+    pthread_t tid;
+    
+    L<<Logger::Error<<"Launched webserver on "<<d_listenaddress<<":"<<d_port<<endl;
+
+    while((client=s->accept())) {
+      pthread_create(&tid, 0 , &serveConnection, (void *)client);
+    }
+  }
+  catch(SessionTimeoutException &e) {
+    L<<Logger::Error<<"Timeout in webserver"<<endl;
+  }
+  catch(SessionException &e) {
+    L<<Logger::Error<<"Fatal error in webserver: "<<e.reason<<endl;
+  }
+  catch(Exception &e) {
+    L<<Logger::Error<<"Fatal error in main webserver thread: "<<e.reason<<endl;
+  }
+  catch(exception &e) {
+    L<<Logger::Error<<"STL Exception in main webserver thread: "<<e.what()<<endl;
+  }
+  catch(...) {
+    L<<Logger::Error<<"Unknown exception in main webserver thread"<<endl;
+  }
+  exit(1);
+
+}
diff --git a/pdns/webserver.hh b/pdns/webserver.hh
new file mode 100644 (file)
index 0000000..387d88f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef WEBSERVER_HH
+#define WEBSERVER_HH
+#include <map>
+#include <string>
+
+
+using namespace std;
+
+class WebServer
+{
+public:
+  WebServer(const string &listenaddress, int port, const string &password="");
+  void go();
+  static void* serveConnection(void *);
+  void setCaller(void *that);
+  typedef string HandlerFunction(const map<string,string>&varmap, void *that, bool *custom);
+  void registerHandler(const string &, HandlerFunction *ptr);
+private:
+  static char B64Decode1(char cInChar);
+  static int B64Decode(const std::string& strInput, std::string& strOutput);
+  string d_listenaddress;
+  int d_port;
+  static map<string,HandlerFunction *>d_functions;
+  static void *d_that;
+  static string d_password;
+};
+#endif /* WEBSERVER_HH */
diff --git a/pdns/ws.cc b/pdns/ws.cc
new file mode 100644 (file)
index 0000000..8696cfe
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/#include "utility.hh"\r
+#include "ws.hh"
+#include "webserver.hh"
+#include "logger.hh"
+#include "statbag.hh"
+#include "misc.hh"
+#include "arguments.hh"
+#include "dns.hh"
+
+extern StatBag S;
+
+StatWebServer::StatWebServer()
+{
+  d_start=time(0);
+       d_min10=d_min5=d_min1=0;
+}
+
+void StatWebServer::go()
+{
+  S.doRings();
+  pthread_create(&d_tid, 0, threadHelper, this);
+  pthread_create(&d_tid, 0, statThreadHelper, this);
+}
+
+
+
+void StatWebServer::statThread()
+{
+  try {
+    for(;;) {
+      d_queries.submit(S.read("udp-queries"));
+      d_cachehits.submit(S.read("packetcache-hit"));
+      d_cachemisses.submit(S.read("packetcache-miss"));
+      d_qcachehits.submit(S.read("query-cache-hit"));
+      d_qcachemisses.submit(S.read("query-cache-miss"));
+      Utility::sleep(1);
+    }
+  }
+  catch(...) {
+    L<<Logger::Error<<"Webserver statThread caught an exception, dying"<<endl;
+    exit(1);
+  }
+}
+
+void *StatWebServer::statThreadHelper(void *p)
+{
+  StatWebServer *sws=static_cast<StatWebServer *>(p);
+  sws->statThread();
+  return 0; // never reached
+}
+
+
+void *StatWebServer::threadHelper(void *p)
+{
+  StatWebServer *sws=static_cast<StatWebServer *>(p);
+  sws->launch();
+  return 0; // never reached
+}
+
+void printtable(ostringstream &ret, const string &ringname, const string &title, int limit=10)
+{
+  int tot=0;
+  int entries=0;
+  vector<pair <string,int> >ring=S.getRing(ringname);
+
+  for(vector<pair<string,int> >::const_iterator i=ring.begin(); i!=ring.end();++i) {  
+    tot+=i->second;
+    entries++;
+  }
+
+
+  ret<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff>"
+    "<a href=?ring="<<ringname<<"><font color=#ffffff>Top-"<<limit<<" of ";
+  ret<<entries<<": "<<title<<"</a></td>"<<endl;
+
+  ret<<"<tr><td colspan=3><table bgcolor=#ff0000 width=100%><tr><td align=left>"
+    "<a href=?resetring="<<ringname<<"><font color=#ffffff>Reset</a></td>";
+  ret<<"<td align=right>Resize: ";
+  
+  int sizes[]={10,100,500,1000,10000,500000,0};
+  for(int i=0;sizes[i];++i) {
+    if(S.getRingSize(ringname)!=sizes[i])
+      ret<<"<a href=?resizering="<<ringname<<"&size="<<sizes[i]<<">"<<sizes[i]<<"</a> ";
+    else
+      ret<<"("<<sizes[i]<<") ";
+  }
+  ret<<"</td></table>"<<endl;
+
+
+  int printed=0;
+  for(vector<pair<string,int> >::const_iterator i=ring.begin();limit && i!=ring.end();++i,--limit) {
+    ret<<"<tr><td>"<<i->first<<"</td><td>"<<i->second<<"</td><td align=right>"<<setprecision(2)<<i->second*100.0/tot<<"%</td>"<<endl;
+    printed+=i->second;
+  }
+  ret<<"<tr><td colspan=3></td></tr>"<<endl;
+  if(printed!=tot)
+    ret<<"<tr><td><b>Rest:</b></td><td><b>"<<tot-printed<<"</b></td><td align=right><b>"<<setprecision(2)<<(tot-printed)*100.0/tot<<"%</b></td>"<<endl;
+
+  ret<<"<tr><td><b>Total:</b></td><td><b>"<<tot<<"</td><td align=right><b>100%</b></td>";
+  ret<<"</table><p>"<<endl;
+}
+
+void StatWebServer::printvars(ostringstream &ret)
+{
+  ret<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff><font color=#ffffff>Variables</td>"<<endl;
+  
+
+  vector<string>entries=S.getEntries();
+  for(vector<string>::const_iterator i=entries.begin();i!=entries.end();++i) {
+    ret<<"<tr><td>"<<*i<<"</td><td>"<<S.read(*i)<<"</td><td>"<<S.getDescrip(*i)<<"</td>"<<endl;
+  }
+}
+
+void StatWebServer::printargs(ostringstream &ret)
+{
+  ret<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff><font color=#ffffff>Arguments</td>"<<endl;
+
+  vector<string>entries=arg().list();
+  for(vector<string>::const_iterator i=entries.begin();i!=entries.end();++i) {
+    ret<<"<tr><td>"<<*i<<"</td><td>"<<arg()[*i]<<"</td><td>"<<arg().getHelp(*i)<<"</td>"<<endl;
+  }
+}
+
+
+string StatWebServer::indexfunction(const map<string,string> &varmap, void *ptr, bool *custom)
+{
+
+  StatWebServer *sws=static_cast<StatWebServer *>(ptr);
+  map<string,string>rvarmap=varmap;
+  if(!rvarmap["resetring"].empty()){
+    *custom=true;
+    S.resetRing(rvarmap["resetring"]);
+    return "HTTP/1.1 301 Moved Permanently\nLocation: /\nConnection: close\n\n";
+  }
+  if(!rvarmap["resizering"].empty()){
+    *custom=true;
+    S.resizeRing(rvarmap["resizering"], atoi(rvarmap["size"].c_str()));
+    return "HTTP/1.1 301 Moved Permanently\nLocation: /\nConnection: close\n\n";
+  }
+
+  ostringstream ret;
+
+  ret<<"<html><head><title>PowerDNS Operational Monitor</title></head><body bgcolor=#ffffff>"<<endl;
+
+
+  if(rvarmap["ring"].empty())
+    ret<<"<h2>PDNS "VERSION" Main Page</h2>"<<endl;
+  else
+    ret<<"<h2>Details page</h2><a href=/>Back to main page</a><p>"<<endl;
+
+  time_t passed=time(0)-s_starttime;
+
+  ret<<"Uptime: ";
+  ret<<humanDuration(passed)<<endl;
+
+
+  ret<<"Queries/second, 1, 5, 10 minute averages:  "<<setprecision(3)<<
+    sws->d_queries.get1()<<", "<<
+    sws->d_queries.get5()<<", "<<
+    sws->d_queries.get10()<<". Max queries/second: "<<sws->d_queries.getMax()<<
+    "<br>"<<endl;
+  
+  if(sws->d_cachemisses.get10()+sws->d_cachehits.get10()>0)
+    ret<<"Cache hitrate, 1, 5, 10 minute averages: "<<setprecision(2)<<
+      (sws->d_cachehits.get1()*100.0)/((sws->d_cachehits.get1())+(sws->d_cachemisses.get1()))<<"%, "<<
+      (sws->d_cachehits.get5()*100.0)/((sws->d_cachehits.get5())+(sws->d_cachemisses.get5()))<<"%, "<<
+      (sws->d_cachehits.get10()*100.0)/((sws->d_cachehits.get10())+(sws->d_cachemisses.get10()))<<
+      "%<br>"<<endl;
+
+  if(sws->d_qcachemisses.get10()+sws->d_qcachehits.get10()>0)
+    ret<<"Backend query cache hitrate, 1, 5, 10 minute averages: "<<setprecision(2)<<
+      (sws->d_qcachehits.get1()*100.0)/((sws->d_qcachehits.get1())+(sws->d_qcachemisses.get1()))<<"%, "<<
+      (sws->d_qcachehits.get5()*100.0)/((sws->d_qcachehits.get5())+(sws->d_qcachemisses.get5()))<<"%, "<<
+      (sws->d_qcachehits.get10()*100.0)/((sws->d_qcachehits.get10())+(sws->d_qcachemisses.get10()))<<
+      "%<br>"<<endl;
+
+  ret<<"Backend query load, 1, 5, 10 minute averages: "<<setprecision(3)<<
+    sws->d_qcachemisses.get1()<<", "<<
+    sws->d_qcachemisses.get5()<<", "<<
+    sws->d_qcachemisses.get10()<<". Max queries/second: "<<sws->d_qcachemisses.getMax()<<
+    "<br>"<<endl;
+
+  ret<<"Total queries: "<<S.read("udp-queries")<<". Question/answer latency: "<<S.read("latency")/1000.0<<"ms<p>"<<endl;
+  if(rvarmap["ring"].empty()) {
+    vector<string>entries=S.listRings();
+    for(vector<string>::const_iterator i=entries.begin();i!=entries.end();++i)
+      printtable(ret,*i,S.getRingTitle(*i));
+
+    sws->printvars(ret);
+    if(arg().mustDo("webserver-print-arguments"))
+      sws->printargs(ret);
+  }
+  else
+    printtable(ret,rvarmap["ring"],S.getRingTitle(rvarmap["ring"]),100);
+
+  ret<<"</body></html>"<<endl;
+
+  return ret.str();
+}
+
+void StatWebServer::launch()
+{
+  try {
+    WebServer ws(arg()["webserver-address"], arg().asNum("webserver-port"),arg()["webserver-password"]);
+    ws.setCaller(this);
+    ws.registerHandler("",&indexfunction);
+    ws.go();
+  }
+  catch(...) {
+    L<<Logger::Error<<"StatWebserver thread caught an exception, dying"<<endl;
+    exit(1);
+  }
+}
diff --git a/pdns/ws.hh b/pdns/ws.hh
new file mode 100644 (file)
index 0000000..9f2971e
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002  PowerDNS.COM BV
+
+    This program 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef WS_HH
+#define WS_HH
+#include <string>
+#include <map>
+#include <time.h>
+#include <pthread.h>
+#include <sstream>
+#include <iomanip>\r
+\r
+#ifndef WIN32\r
+# include <unistd.h>\r
+#endif // WIN32\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif // HAVE_CONFIG_H\r
+
+#include "misc.hh"
+using namespace std;
+
+class Ewma
+{
+public:
+  Ewma() : d_last(0), d_10(0), d_5(0), d_1(0), d_max(0){dt.set();}
+  void submit(int val) 
+  {
+    int rate=val-d_last;
+    double difft=dt.udiff()/1000000.0;
+    dt.set();
+    
+    d_10=((600.0-difft)*d_10+(difft*rate))/600.0;
+    d_5=((300.0-difft)*d_5+(difft*rate))/300.0;
+    d_1=((60.0-difft)*d_1+(difft*rate))/60.0;
+    d_max=max(d_1,d_max);
+      
+    d_last=val;
+  }
+  double get10()
+  {
+    return d_10;
+  }
+  double get5()
+  {
+    return d_5;
+  }
+  double get1()
+  {
+    return d_1;
+  }
+  double getMax()
+  {
+    return d_max;
+  }
+private:
+  DTime dt;
+  int d_last;
+  double d_10, d_5, d_1, d_max;
+};
+
+
+class StatWebServer
+{
+public:
+  StatWebServer();
+  void go();
+private:
+  static void *threadHelper(void *);
+  static void *statThreadHelper(void *p);
+  static string indexfunction(const map<string,string> &varmap, void *ptr, bool *custom);
+  void printvars(ostringstream &ret);
+  void printargs(ostringstream &ret);
+  void launch();
+  void statThread();
+  pthread_t d_tid;
+
+  time_t d_start;
+  double d_min10, d_min5, d_min1;
+  Ewma d_queries, d_cachehits, d_cachemisses;
+  Ewma d_qcachehits, d_qcachemisses;
+};
+
+#endif
diff --git a/pdns/ylwrap b/pdns/ylwrap
new file mode 100755 (executable)
index 0000000..5ea68e4
--- /dev/null
@@ -0,0 +1,143 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+# Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program 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, 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# 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.
+
+# Usage:
+#     ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+# * INPUT is the input file
+# * OUTPUT is file PROG generates
+# * DESIRED is file we actually want
+# * PROGRAM is program to run
+# * ARGS are passed to PROG
+# Any number of OUTPUT,DESIRED pairs may be used.
+
+# The input.
+input="$1"
+shift
+case "$input" in
+ [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+ *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+# The directory holding the input.
+input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+# Quote $INPUT_DIR so we can use it in a regexp.
+# FIXME: really we should care about more than `.' and `\'.
+input_rx=`echo "$input_dir" | sed -e 's,\\\\,\\\\\\\\,g' -e 's,\\.,\\\\.,g'`
+
+echo "got $input_rx"
+
+pairlist=
+while test "$#" -ne 0; do
+   if test "$1" = "--"; then
+      shift
+      break
+   fi
+   pairlist="$pairlist $1"
+   shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+$prog ${1+"$@"} "$input"
+status=$?
+
+if test $status -eq 0; then
+   set X $pairlist
+   shift
+   first=yes
+   # Since DOS filename conventions don't allow two dots,
+   # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+   # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+   y_tab_nodot="no"
+   if test -f y_tab.c || test -f y_tab.h; then
+      y_tab_nodot="yes"
+   fi
+
+   while test "$#" -ne 0; do
+      from="$1"
+      # Handle y_tab.c and y_tab.h output by DOS
+      if test $y_tab_nodot = "yes"; then
+        if test $from = "y.tab.c"; then
+           from="y_tab.c"
+        else
+           if test $from = "y.tab.h"; then
+              from="y_tab.h"
+           fi
+        fi
+      fi
+      if test -f "$from"; then
+         # If $2 is an absolute path name, then just use that,
+         # otherwise prepend `../'.
+         case "$2" in
+          [\\/]* | ?:[\\/]*) target="$2";;
+          *) target="../$2";;
+        esac
+
+        # Edit out `#line' or `#' directives.  We don't want the
+        # resulting debug information to point at an absolute srcdir;
+        # it is better for it to just mention the .y file with no
+        # path.
+        sed -e "/^#/ s,$input_rx,," "$from" > "$target" || status=$?
+      else
+        # A missing file is only an error for the first file.  This
+        # is a blatant hack to let us support using "yacc -d".  If -d
+        # is not specified, we don't want an error when the header
+        # file is "missing".
+        if test $first = yes; then
+           status=1
+        fi
+      fi
+      shift
+      shift
+      first=no
+   done
+else
+   status=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $status