diff --git a/ABOUT-NLS b/ABOUT-NLS deleted file mode 100644 index 5fde45a..0000000 --- a/ABOUT-NLS +++ /dev/null @@ -1,324 +0,0 @@ -Notes on the Free Translation Project -************************************* - - Free software is going international! The Free Translation Project -is a way to get maintainers of free software, translators, and users all -together, so that will gradually become able to speak many languages. -A few packages already provide translations for their messages. - - If you found this `ABOUT-NLS' file inside a distribution, you may -assume that the distributed package does use GNU `gettext' internally, -itself available at your nearest GNU archive site. But you do _not_ -need to install GNU `gettext' prior to configuring, installing or using -this package with messages translated. - - Installers will find here some useful hints. These notes also -explain how users should proceed for getting the programs to use the -available translations. They tell how people wanting to contribute and -work at translations should contact the appropriate team. - - When reporting bugs in the `intl/' directory or bugs which may be -related to internationalization, you should tell about the version of -`gettext' which is used. The information can be found in the -`intl/VERSION' file, in internationalized packages. - -Quick configuration advice -========================== - - If you want to exploit the full power of internationalization, you -should configure it using - - ./configure --with-included-gettext - -to force usage of internationalizing routines provided within this -package, despite the existence of internationalizing capabilities in the -operating system where this package is being installed. So far, only -the `gettext' implementation in the GNU C library version 2 provides as -many features (such as locale alias, message inheritance, automatic -charset conversion or plural form handling) as the implementation here. -It is also not possible to offer this additional functionality on top -of a `catgets' implementation. Future versions of GNU `gettext' will -very likely convey even more functionality. So it might be a good idea -to change to GNU `gettext' as soon as possible. - - So you need _not_ provide this option if you are using GNU libc 2 or -you have installed a recent copy of the GNU gettext package with the -included `libintl'. - -INSTALL Matters -=============== - - Some packages are "localizable" when properly installed; the -programs they contain can be made to speak your own native language. -Most such packages use GNU `gettext'. Other packages have their own -ways to internationalization, predating GNU `gettext'. - - By default, this package will be installed to allow translation of -messages. It will automatically detect whether the system already -provides the GNU `gettext' functions. If not, the GNU `gettext' own -library will be used. This library is wholly contained within this -package, usually in the `intl/' subdirectory, so prior installation of -the GNU `gettext' package is _not_ required. Installers may use -special options at configuration time for changing the default -behaviour. The commands: - - ./configure --with-included-gettext - ./configure --disable-nls - -will respectively bypass any pre-existing `gettext' to use the -internationalizing routines provided within this package, or else, -_totally_ disable translation of messages. - - When you already have GNU `gettext' installed on your system and run -configure without an option for your new package, `configure' will -probably detect the previously built and installed `libintl.a' file and -will decide to use this. This might be not what is desirable. You -should use the more recent version of the GNU `gettext' library. I.e. -if the file `intl/VERSION' shows that the library which comes with this -package is more recent, you should use - - ./configure --with-included-gettext - -to prevent auto-detection. - - The configuration process will not test for the `catgets' function -and therefore it will not be used. The reason is that even an -emulation of `gettext' on top of `catgets' could not provide all the -extensions of the GNU `gettext' library. - - Internationalized packages have usually many `po/LL.po' files, where -LL gives an ISO 639 two-letter code identifying the language. Unless -translations have been forbidden at `configure' time by using the -`--disable-nls' switch, all available translations are installed -together with the package. However, the environment variable `LINGUAS' -may be set, prior to configuration, to limit the installed set. -`LINGUAS' should then contain a space separated list of two-letter -codes, stating which languages are allowed. - -Using This Package -================== - - As a user, if your language has been installed for this package, you -only have to set the `LANG' environment variable to the appropriate -`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, -and `CC' is an ISO 3166 two-letter country code. For example, let's -suppose that you speak German and live in Germany. At the shell -prompt, merely execute `setenv LANG de_DE' (in `csh'), -`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). -This can be done from your `.login' or `.profile' file, once and for -all. - - You might think that the country code specification is redundant. -But in fact, some languages have dialects in different countries. For -example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The -country code serves to distinguish the dialects. - - Not all programs have translations for all languages. By default, an -English message is shown in place of a nonexistent translation. If you -understand other languages, you can set up a priority list of languages. -This is done through a different environment variable, called -`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' -for the purpose of message handling, but you still need to have `LANG' -set to the primary language; this is required by other parts of the -system libraries. For example, some Swedish users who would rather -read translations in German than English for when Swedish is not -available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. - - In the `LANGUAGE' environment variable, but not in the `LANG' -environment variable, `LL_CC' combinations can be abbreviated as `LL' -to denote the language's main dialect. For example, `de' is equivalent -to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' -(Portuguese as spoken in Portugal) in this context. - -Translating Teams -================= - - For the Free Translation Project to be a success, we need interested -people who like their own language and write it well, and who are also -able to synergize with other translators speaking the same language. -Each translation team has its own mailing list. The up-to-date list of -teams can be found at the Free Translation Project's homepage, -`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" -area. - - If you'd like to volunteer to _work_ at translating messages, you -should become a member of the translating team for your own language. -The subscribing address is _not_ the same as the list itself, it has -`-request' appended. For example, speakers of Swedish can send a -message to `sv-request@li.org', having this message body: - - subscribe - - Keep in mind that team members are expected to participate -_actively_ in translations, or at solving translational difficulties, -rather than merely lurking around. If your team does not exist yet and -you want to start one, or if you are unsure about what to do or how to -get started, please write to `translation@iro.umontreal.ca' to reach the -coordinator for all translator teams. - - The English team is special. It works at improving and uniformizing -the terminology in use. Proven linguistic skill are praised more than -programming skill, here. - -Available Packages -================== - - Languages are not equally supported in all packages. The following -matrix shows the current state of internationalization, as of September -2001. The matrix shows, in regard of each package, for which languages -PO files have been submitted to translation coordination, with a -translation percentage of at least 50%. - - Ready PO files bg cs da de el en eo es et fi fr gl he hr id it ja - +----------------------------------------------------+ - a2ps | [] [] [] | - bash | [] [] [] [] | - bfd | | - binutils | [] | - bison | [] [] [] [] [] | - clisp | [] [] [] [] | - cpio | [] [] [] [] [] | - diffutils | [] [] [] [] [] [] [] | - enscript | [] [] | - error | [] [] | - fetchmail | | - fileutils | [] [] [] [] [] [] [] [] | - findutils | [] [] [] [] [] [] [] [] | - flex | [] [] [] | - freetype | | - gas | | - gawk | [] [] | - gcal | | - gcc | | - gettext | [] [] [] [] [] [] [] [] [] [] | - gnupg | [] [] [] [] [] [] [] | - gprof | | - grep | [] [] [] [] [] [] [] [] | - hello | [] [] [] [] [] [] [] [] [] [] [] | - id-utils | [] [] [] | - indent | [] [] [] [] [] | - jpilot | [] | - kbd | | - ld | [] | - libc | [] [] [] [] [] [] [] [] | - lilypond | [] | - lynx | [] [] [] [] | - m4 | [] [] [] [] [] [] [] [] | - make | [] [] [] [] [] [] | - mysecretdiary | [] | - nano | [] [] [] | - opcodes | | - parted | [] [] [] | - ptx | [] [] [] [] [] [] [] | - python | | - recode | [] [] [] [] [] [] [] [] [] | - sed | [] [] [] [] [] [] [] [] [] [] [] [] | - sh-utils | [] [] [] [] [] [] [] [] [] [] | - sharutils | [] [] [] [] [] [] [] [] | - sketch | | - soundtracker | [] [] [] | - sp | | - tar | [] [] [] [] [] [] [] [] | - texinfo | [] [] [] [] [] [] | - textutils | [] [] [] [] [] [] [] [] | - util-linux | [] [] | - wdiff | [] [] [] | - wget | [] [] [] [] [] [] [] [] [] [] | - +----------------------------------------------------+ - bg cs da de el en eo es et fi fr gl he hr id it ja - 0 14 24 32 11 1 8 23 13 1 33 22 4 0 7 9 18 - - ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh - +----------------------------------------------------+ - a2ps | [] [] [] | 6 - bash | | 4 - bfd | | 0 - binutils | | 1 - bison | [] | 6 - clisp | [] | 5 - cpio | [] [] [] [] [] | 10 - diffutils | [] [] [] [] | 11 - enscript | [] [] [] | 5 - error | [] [] | 4 - fetchmail | | 0 - fileutils | [] [] [] [] [] [] [] [] [] | 17 - findutils | [] [] [] [] [] [] [] [] | 16 - flex | [] [] [] | 6 - freetype | | 0 - gas | | 0 - gawk | [] | 3 - gcal | | 0 - gcc | | 0 - gettext | [] [] [] [] [] [] [] [] | 18 - gnupg | [] [] [] | 10 - gprof | | 0 - grep | [] [] [] [] | 12 - hello | [] [] [] [] [] [] [] [] [] [] [] | 22 - id-utils | [] [] [] | 6 - indent | [] [] [] [] [] [] [] | 12 - jpilot | | 1 - kbd | [] | 1 - ld | | 1 - libc | [] [] [] [] [] [] [] [] | 16 - lilypond | [] [] | 3 - lynx | [] [] [] [] | 8 - m4 | [] [] [] [] | 12 - make | [] [] [] [] [] [] | 12 - mysecretdiary | | 1 - nano | [] | 4 - opcodes | [] | 1 - parted | [] [] | 5 - ptx | [] [] [] [] [] [] [] [] | 15 - python | | 0 - recode | [] [] [] [] | 13 - sed | [] [] [] [] [] [] [] | 19 - sh-utils | [] [] [] [] [] [] [] [] [] [] [] | 21 - sharutils | [] [] [] | 11 - sketch | | 0 - soundtracker | | 3 - sp | | 0 - tar | [] [] [] [] [] [] [] | 15 - texinfo | [] | 7 - textutils | [] [] [] [] [] [] [] [] | 16 - util-linux | [] [] | 4 - wdiff | [] [] [] [] | 7 - wget | [] [] [] [] [] [] [] | 17 - +----------------------------------------------------+ - 33 teams ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh - 53 domains 9 1 6 20 0 6 17 1 13 25 10 11 23 21 2 2 387 - - Some counters in the preceding matrix are higher than the number of -visible blocks let us expect. This is because a few extra PO files are -used for implementing regional variants of languages, or language -dialects. - - For a PO file in the matrix above to be effective, the package to -which it applies should also have been internationalized and -distributed as such by its maintainer. There might be an observable -lag between the mere existence a PO file and its wide availability in a -distribution. - - If September 2001 seems to be old, you may fetch a more recent copy -of this `ABOUT-NLS' file on most GNU archive sites. The most -up-to-date matrix with full percentage details can be found at -`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. - -Using `gettext' in new packages -=============================== - - If you are writing a freely available program and want to -internationalize it you are welcome to use GNU `gettext' in your -package. Of course you have to respect the GNU Library General Public -License which covers the use of the GNU `gettext' library. This means -in particular that even non-free programs can use `libintl' as a shared -library, whereas only free software can use `libintl' as a static -library or use modified versions of `libintl'. - - Once the sources are changed appropriately and the setup can handle -to use of `gettext' the only thing missing are the translations. The -Free Translation Project is also available for packages which are not -developed inside the GNU project. Therefore the information given above -applies also for every other Free Software Project. Contact -`translation@iro.umontreal.ca' to make the `.pot' files available to -the translation teams. - diff --git a/AUTHORS b/AUTHORS index 4721984..af11393 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,25 @@ Main tinc authors: -Guus Sliepen -Ivo Timmermans +- Guus Sliepen +- Ivo Timmermans (inactive) + +Significant contributions from: +- Michael Tokarev +- Florian Forster +- Grzegorz Dymarek +- Max Rijevski +- Scott Lamb +- Julien Muchembled +- Timothy Redaelli +- Brandon Black +- Loïc Grenié These files are from other sources: * lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from the syslog 1.3 sources. +* src/bsd/tunemu.c and tunemu.h are by Friedrich Schöller + + Also some of the macro files in the directory m4, and their accompanying files in lib, were taken from GNU fileutils. diff --git a/COPYING b/COPYING index a43ea21..1384f46 100644 --- a/COPYING +++ b/COPYING @@ -1,8 +1,17 @@ +Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and others. +See the AUTHORS file for a complete list. + +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. + + GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -15,7 +24,7 @@ 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 +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,7 +64,7 @@ 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. - + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @@ -110,7 +119,7 @@ above, provided that you also meet all of these conditions: 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.) - + 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 @@ -168,7 +177,7 @@ 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. - + 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 @@ -225,7 +234,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 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 @@ -278,62 +287,3 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - Appendix: 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. - - - Copyright (C) 19yy - - 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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. - - , 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/COPYING.README b/COPYING.README index 144207e..2eb9c1f 100644 --- a/COPYING.README +++ b/COPYING.README @@ -1,4 +1,19 @@ -This program is released under the GPL with the additional exemption -that compiling, linking, and/or using OpenSSL is allowed. You may -provide binary packages linked to the OpenSSL libraries, provided that -all other requirements of the GPL are met. +The following applies to tinc: + +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. You may provide binary +packages linked to the OpenSSL libraries, provided that all other requirements +of the GPL are met. + +The following applies to the LZO library: + + Hereby I grant a special exception to the tinc VPN project + (http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library + (http://www.openssl.org). + + Markus F.X.J. Oberhumer + +When tinc is compiled with the --enable-tunemu option, the resulting binary +falls under the GPL version 3 or later. + + diff --git a/ChangeLog b/ChangeLog index 7622c02..041bf3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4614 +1,2224 @@ -2002-04-09 13:51 Guus Sliepen - - * configure.in: This is the release of 1.0pre7. - -2002-04-09 13:44 Guus Sliepen - - * NEWS, README: Remarks about 1.0pre7 release. - -2002-04-09 13:43 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2002-04-09 13:43 Guus Sliepen - - * doc/: PROTOCOL, tinc.conf.5, tinc.texi: masklength is better - known as prefixlength - -2002-04-09 13:42 Guus Sliepen - - * src/: conf.c, subnet.c, subnet.h: masklength is better known as - prefixlength. - -2002-04-08 15:27 Guus Sliepen - - * Makefile.am: Automake forgets about depcomp, remind it. - -2002-04-05 11:11 Guus Sliepen - - * src/netutl.c: Fix maskcheck() and maskcmp(). - -2002-04-01 23:28 Guus Sliepen - - * src/net_setup.c: check_rsa() is broken, I don't know why, just - remove it for now. - -2002-04-01 23:28 Guus Sliepen - - * src/net.c: Don't check_network_activity() if select() is - interrupted by a signal. - -2002-03-27 20:43 Guus Sliepen - - * m4/zlib.m4: Make configure --help output look nicer. - -2002-03-27 17:26 Guus Sliepen - - * NEWS, README: Update with information about the pre6 release. - -2002-03-27 17:00 Guus Sliepen - - * po/nl.po: Update dutch translation. - -2002-03-27 17:00 Guus Sliepen - - * src/openbsd/device.c: Fix format strings. - -2002-03-27 16:47 Guus Sliepen - - * src/Makefile.am: Remove symlink to device.c when doing a make - dist. - -2002-03-27 16:35 Guus Sliepen - - * doc/Makefile.maint: Recent automake uses $(AMTAR) instead of - $(TAR) - -2002-03-27 16:26 Guus Sliepen - - * src/: edge.c, protocol.c, protocol_auth.c, protocol_edge.c: - Remove cruft. - -2002-03-27 16:26 Guus Sliepen - - * doc/: tinc.conf.5, tinc.texi: Small updates. - -2002-03-27 16:01 Guus Sliepen - - * src/: net.h, net_packet.c: Limit the amount of packets in a queue - to 8. - -2002-03-27 16:01 Guus Sliepen - - * lib/: list.c, list.h: Extend list_t with the number of elements - in the list. - -2002-03-27 15:02 Guus Sliepen - - * src/: net.c, net_socket.c: Merge do_prune() with build_fdset(). - Probably fixes the invalid filedescriptor error. - -2002-03-26 14:19 Guus Sliepen - - * doc/tinc.texi: Small correction. - -2002-03-26 13:00 Guus Sliepen - - * src/process.c: Fix execute_script(). - -2002-03-25 16:51 Guus Sliepen - - * src/net_packet.c: Send REQ_KEY only once until ANS_KEY has - arrived. - -2002-03-25 16:12 Guus Sliepen - - * doc/tinc.texi: Tell a little bit more about security. - -2002-03-25 16:01 Guus Sliepen - - * doc/: tinc.conf.5, tinc.texi, tincd.8: Updated documentation. - -2002-03-25 14:54 Guus Sliepen - - * src/net_setup.c: Set myself->status.reachable. - -2002-03-24 18:14 Guus Sliepen - - * src/conf.c: Configuration variables were still handled case - sensitively. - -2002-03-24 18:08 Guus Sliepen - - * src/openbsd/device.c: OpenBSD tun device uses address family - number instead of Ethernet type. - -2002-03-24 17:50 Guus Sliepen - - * src/openbsd/device.c: Respect type field. - -2002-03-24 17:40 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2002-03-24 17:36 Guus Sliepen - - * src/linux/device.c: Set $INTERFACE correctly when using ethertap - while compiled with tun/tap support. - -2002-03-24 17:28 Guus Sliepen - - * src/: graph.c, net.c: Execute hosts/name-up when a node becomes - reachable, and hosts/name-down when it becomes unreachable. - -2002-03-24 17:22 Guus Sliepen - - * src/process.c: Don't try to execute scripts unless they exist. - -2002-03-23 21:21 Guus Sliepen - - * src/: protocol_auth.c, protocol_misc.c: Reset retry timeout when - receiving the first PONG, not right after receiving the ACK. - -2002-03-23 21:13 Guus Sliepen - - * src/net.c: Don't run graph algorithms if no edge is deleted in - terminate_connection(). - -2002-03-23 21:12 Guus Sliepen - - * src/protocol.c: free() request strings when deleting past - requests from the tree. - -2002-03-23 21:01 Guus Sliepen - - * src/protocol_auth.c: send_ack() was broken. - -2002-03-22 14:31 Guus Sliepen - - * src/: connection.c, edge.c, node.c, protocol.c, protocol_auth.c, - protocol_edge.c, protocol_key.c, protocol_subnet.c: Fix compiler - warnings, strictly use long int and %lx for options. - -2002-03-22 13:41 Guus Sliepen - - * src/protocol_edge.c: Fix add_edge_h(). - -2002-03-22 12:43 Guus Sliepen - - * acconfig.h, configure.in, src/edge.c, src/edge.h, src/net.c, - src/net.h, src/net_setup.c, src/protocol.c, src/protocol.h, - src/protocol_auth.c, src/protocol_edge.c: - - Added support for jumbograms. - - Remove tcpaddress from edges, it is not used at all. - - Last bits of code to prevent looping requests. - -2002-03-22 00:11 Guus Sliepen - - * src/: protocol.c, protocol.h, protocol_edge.c, protocol_key.c, - protocol_subnet.c: Put a break on requests that run around in - circles. - -2002-03-19 23:48 Guus Sliepen - - * src/: graph.c, node.h: Updated SSSP algorithm to automatically - detect indirect links (if a node uses different addresses for - connections to other nodes). - -2002-03-19 01:08 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2002-03-19 01:08 Guus Sliepen - - * src/: netutl.c, route.c: Don't use s6_addr[16|32] anymore. - -2002-03-19 01:07 Guus Sliepen - - * src/process.c: Cleanup. - -2002-03-18 23:47 Guus Sliepen - - * src/: net.c, net.h, net_packet.c, net_setup.c, net_socket.c: - Remember sockaddrs of listening sockets, use appropriate one when - sending UDP packets. - -2002-03-18 15:39 Guus Sliepen - - * src/netutl.c: Fix #define s6_addr32. - -2002-03-18 15:19 Guus Sliepen - - * src/netutl.c: #define s6_addr32, needed for FreeBSD. - -2002-03-17 17:08 Guus Sliepen - - * src/netutl.c: Only unmap IPv6 addresses. - -2002-03-17 16:59 Guus Sliepen - - * src/: net_packet.c, net_socket.c, netutl.c, netutl.h: Unmap - v4mapped sockaddrs. - -2002-03-15 16:50 Guus Sliepen - - * src/route.c: Typo. - -2002-03-15 16:40 Guus Sliepen - - * src/route.c: Different way of detecting neighbor solicitation - requests. - -2002-03-15 16:08 Guus Sliepen - - * src/route.c: Oops, don't forget to actually put the checksum in - the response packet. - -2002-03-15 15:41 Guus Sliepen - - * src/route.c: Neighbor solicitation requests now work (I think). - -2002-03-12 17:30 Guus Sliepen - - * src/graph.c: Revert changes to Kruskal's algo. - -2002-03-12 15:25 Guus Sliepen - - * src/route.c: Put #ifdef NEIGHBORSOL around corresponding code. - -2002-03-12 15:20 Guus Sliepen - - * src/subnet.c: Remove silly cache thingy. - -2002-03-12 15:19 Guus Sliepen - - * src/net_packet.c: Packet sequence number/authentication warnings - only if debug_lvl >= 5. - -2002-03-12 14:42 Guus Sliepen - - * src/graph.c: Simplified implementation of Kruskal's minimum - spanning tree algorithm. - -2002-03-11 14:56 Guus Sliepen - - * src/route.c: New strategy: forward icmp6 neighbor solicitations - to intended target. - -2002-03-11 14:14 Guus Sliepen - - * src/route.c: Try to reply to neighbor solicitation requests. - -2002-03-11 12:45 Guus Sliepen - - * src/net.c: prune_connections() before build_fdset(). - -2002-03-11 12:23 Guus Sliepen - - * src/: net.c, process.c, subnet.c, tincd.c: Cleanups, spelling - fixes, allow symbol names for signals (-k option), don't remove - pidfile if other tincd is still running. - -2002-03-10 17:09 Guus Sliepen - - * src/net_setup.c: Don't retry to make outgoing connections when - exitting. - -2002-03-10 16:40 Guus Sliepen - - * Makefile.am, autogen.sh: Small fixes to improve portability. - -2002-03-10 15:07 Guus Sliepen - - * autogen.sh: Autodetect $MAKE/gmake/make. - -2002-03-10 15:05 Guus Sliepen - - * configure.in: po/POTFILES and po/Makefile should not be generated - by configure. - -2002-03-10 15:04 Guus Sliepen - - * src/route.c: Fix forwarding of IPv6 packets. - -2002-03-01 16:14 Guus Sliepen - - * po/nl.po, src/net_packet.c, src/net_setup.c, src/net_socket.c: - Check if BindToDevice and PriorityInheritance are supported. - -2002-03-01 15:33 Guus Sliepen - - * src/route.c: Woops. - -2002-03-01 15:25 Guus Sliepen - - * doc/tinc.conf.5, doc/tinc.texi, po/nl.po, src/net.c, src/route.c: - Document and clean up MAC address expiry. - -2002-03-01 15:09 Guus Sliepen - - * src/: event.c, meta.c, net.c, net.h, net_packet.c, net_setup.c, - net_socket.c, protocol_misc.c, route.c, route.h, subnet.h: - - Global time_t now, so that we don't have to call time() too often. - - MAC addresses expire after a time configurable by MACExpire - (default 600 seconds) - -2002-03-01 14:38 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2002-03-01 14:38 Guus Sliepen - - * doc/: tinc.conf.5, tinc.texi: Updated documentation. - -2002-03-01 14:18 Guus Sliepen - - * src/: net.c, net.h, net_setup.c, net_socket.c: Create/bind TCP - and UDP listening sockets in pairs. - -2002-03-01 13:26 Guus Sliepen - - * src/: net.h, net_packet.c, route.c, route.h: If - "PriorityInheritance = yes" is specified in tinc.conf, the value of - the TOS field of the tunneled packets will be passed on to the UDP - packets tinc sends out. - -2002-03-01 13:25 Guus Sliepen - - * src/net_setup.c: Fix listening sockets. - -2002-03-01 12:18 Guus Sliepen - - * src/net_socket.c: Make BindToInterface work. - -2002-02-27 23:37 Guus Sliepen - - * src/: protocol.c, protocol_key.c: Fix send_request() bug. - -2002-02-27 00:26 Guus Sliepen - - * src/: net.c, net.h, net_packet.c, net_setup.c, net_socket.c, - protocol.h: Allow multiple listening sockets. - -2002-02-26 23:47 Guus Sliepen - - * src/: net.h, netutl.c: Tweaking IPv6 support. - -2002-02-20 23:37 Guus Sliepen - - * src/: net.h, net_packet.c, net_socket.c, netutl.c: - - Change SA_LEN to SALEN, former one is already defined on some - platforms. - - Use SALEN everywhere appropriate. - -2002-02-20 23:15 Guus Sliepen - - * src/: net.h, net_packet.c, net_setup.c, netutl.c: - - Use gai_strerror() where appropriate - - Clear hints before using them with getaddrinfo() - - Use sa_len on platforms that support them - -2002-02-20 20:31 Guus Sliepen - - * src/net_packet.c: Preserve inpkt->len, needed for broadcasts. - -2002-02-20 20:25 Guus Sliepen - - * src/: connection.h, net_setup.c, net_socket.c, protocol_auth.c, - protocol_key.c: Protocol now also exchanges - cipher/digest/maclength/compression for the meta connection. - -2002-02-20 18:16 Guus Sliepen - - * src/subnet.c: Cache results of lookup_subnet_...(). - -2002-02-20 18:15 Guus Sliepen - - * src/netutl.c: Fix maskcmp() and maskcpy(). - -2002-02-20 17:04 Guus Sliepen - - * src/route.c: Forward packets in router mode. - -2002-02-20 17:04 Guus Sliepen - - * src/net_setup.c: Use AF_UNSPEC for listening sockets if - AddressFamily = any. - -2002-02-20 17:04 Guus Sliepen - - * src/net.c: Fix segfault when receiving HUP signal. - -2002-02-18 17:25 Guus Sliepen - - * src/net_packet.c: file net_packet.c was initially added on branch - CABAL. - -2002-02-18 17:25 Guus Sliepen - - * src/net_setup.c: file net_setup.c was initially added on branch - CABAL. - -2002-02-18 17:25 Guus Sliepen - - * src/net_socket.c: file net_socket.c was initially added on branch - CABAL. - -2002-02-18 17:25 Guus Sliepen - - * doc/tinc.conf.5, doc/tinc.texi, po/POTFILES.in, po/nl.po, - src/Makefile.am, src/conf.c, src/conf.h, src/connection.c, - src/connection.h, src/edge.c, src/edge.h, src/graph.c, src/meta.c, - src/net.c, src/net.h, src/net_packet.c, src/net_setup.c, - src/net_socket.c, src/netutl.c, src/netutl.h, src/node.c, - src/node.h, src/process.c, src/protocol_auth.c, - src/protocol_edge.c, src/route.c, src/subnet.c, src/subnet.h, - src/freebsd/device.c, src/linux/device.c, src/netbsd/device.c, - src/openbsd/device.c, src/solaris/device.c: - - Non-blocking connect()s. - - Socket handling revamped to use sockaddr_t. - - tinc can now tunnel over IPv6. - - Handle all addresses and subnets in network byte order. - Only convert them when they need to be printed. - - IPv6 subnets bigger than /128 now work. - - Use %s and strerror(errno) instead of %m. - -2002-02-12 15:42 Guus Sliepen - - * acconfig.h, configure.in: Add check for NetBSD. - -2002-02-12 15:40 Guus Sliepen - - * src/netbsd/device.c: Added device.c for NetBSD, actually a copy - of the OpenBSD one. - -2002-02-12 15:40 Guus Sliepen - - * src/netbsd/device.c: file device.c was initially added on branch - CABAL. - -2002-02-12 15:36 Guus Sliepen - - * src/: meta.c, net.c: Get rid of sys/signal.h. - -2002-02-12 15:29 Guus Sliepen - - * src/process.c: Don't use sa_sigaction (which NetBSD doesn't like) - at all if we don't use siginfo. - -2002-02-11 16:59 Guus Sliepen - - * THANKS, configure.in, doc/tinc.conf.5, doc/tinc.texi, m4/zlib.m4, - po/nl.po, src/net.c, src/node.c, src/node.h, src/protocol.h, - src/protocol_key.c: Added support for packet compression, thanks to - Mark Glines. Add "Compression = " to the host config files, - where level can be 0 (off), or any integer between 1 (fast) and 9 - (best). - -2002-02-11 16:59 Guus Sliepen - - * m4/zlib.m4: file zlib.m4 was initially added on branch CABAL. - -2002-02-11 15:20 Guus Sliepen - - * src/solaris/device.c: Small fix. - -2002-02-11 15:20 Guus Sliepen - - * src/net.c: - - If no PrivateKeyFile is specified, /etc/tinc/netname/rsa_key.priv - is assumed. - - Check RSA key before using it. - -2002-02-11 13:33 Guus Sliepen - - * src/: freebsd/device.c, linux/device.c, openbsd/device.c, - solaris/device.c: Sensible defaults for $INTERFACE. - -2002-02-11 11:16 Guus Sliepen - - * src/: netutl.c, netutl.h: Last bits of the merger. - -2002-02-11 11:05 Guus Sliepen - - * src/: event.c, event.h, protocol_auth.c, protocol_edge.c, - protocol_key.c, protocol_misc.c, protocol_subnet.c: Forgot to merge - new files from pre5. - -2002-02-10 22:57 Guus Sliepen - - * AUTHORS, Makefile.am, NEWS, README, THANKS, TODO, acconfig.h, - configure.in, doc/CONNECTIVITY, doc/NETWORKING, doc/PROTOCOL, - doc/SECURITY2, doc/tinc.conf.5, doc/tinc.texi, doc/tincd.8, - doc/sample-config/tinc-down, doc/sample-config/tinc-up, - doc/sample-config/tinc.conf, lib/avl_tree.c, lib/dropin.c, - lib/dropin.h, m4/openssl.m4, po/POTFILES.in, po/nl.po, - redhat/Makefile.am, src/Makefile.am, src/conf.c, src/conf.h, - src/connection.c, src/connection.h, src/device.h, src/edge.c, - src/edge.h, src/graph.c, src/graph.h, src/meta.c, src/meta.h, - src/net.c, src/net.h, src/node.c, src/node.h, src/process.c, - src/process.h, src/protocol.c, src/protocol.h, src/route.c, - src/route.h, src/subnet.c, src/subnet.h, src/tincd.c, - src/freebsd/device.c, src/linux/device.c, src/openbsd/device.c, - src/solaris/device.c: Merging of the entire pre5 branch. - -2002-02-10 16:44 Ivo Timmermans - - * doc/tinc.texi: Added @dircategory - -2002-02-10 01:39 Guus Sliepen - - * doc/tinc.texi: Better placement of @cindex directives. - -2002-02-09 23:54 Guus Sliepen - - * configure.in: Remove src/device.c before making a symbolic link. - -2002-02-09 22:44 Guus Sliepen - - * THANKS: Credits go to Jerome Etienne for his security analysis. - -2002-02-09 22:42 Guus Sliepen - - * configure.in: 1.0pre5, without a dash. - -2002-02-09 22:35 Guus Sliepen - - * src/Makefile.am: Add os/device.c to the release. - -2002-02-09 22:11 Guus Sliepen - - * doc/: tinc.conf.5, tincd.8: Spelling checker. - -2002-02-09 22:00 Guus Sliepen - - * configure.in: Make po/POTFILES and po/Makefile since not all - versions of autoconf do this automatically. - -2002-02-09 21:33 Guus Sliepen - - * po/nl.po: Update translation. - -2002-02-09 21:30 Guus Sliepen - - * Makefile.am: There are no makefiles in redhat/. - -2002-02-09 21:27 Guus Sliepen - - * README: We're up to version 1.0pre5 now. - -2002-02-09 21:18 Guus Sliepen - - * configure.in, redhat/Makefile.am: Don't make makefiles in debian/ - and redhat/. - -2002-02-09 21:07 Guus Sliepen - - * NEWS, README, TODO: Update to pre5. - -2002-02-09 21:00 Guus Sliepen - - * doc/: CONNECTIVITY, NETWORKING, PROTOCOL, SECURITY2, tincd.8: - 2002. - -2002-02-09 20:59 Guus Sliepen - - * src/: conf.c, conf.h, connection.c, connection.h, device.h, - edge.c, edge.h, graph.c, graph.h, meta.c, meta.h, net.c, net.h, - netutl.c, netutl.h, node.c, node.h, process.c, process.h, - protocol_auth.c, protocol_edge.c, protocol_key.c, protocol_misc.c, - protocol_subnet.c, route.c, route.h, subnet.c, tincd.c, - freebsd/device.c, linux/device.c, openbsd/device.c, - solaris/device.c: We're living in 2002 now. - -2002-02-09 19:34 Guus Sliepen - - * doc/tinc.texi: Update info manual. - -2002-02-09 17:26 Guus Sliepen - - * src/net.c: Fix flushing of event queue. - -2002-02-09 17:24 Guus Sliepen - - * doc/tinc.conf.5, po/nl.po, src/conf.c, src/conf.h, src/event.h, - src/net.c, src/process.c, src/subnet.c: Cleanups. - -2002-02-09 17:07 Guus Sliepen - - * src/: Makefile.am, connection.h, net.c, net.h, protocol_auth.c, - route.c: Added struct outgoing_t, which is a ticket containing the - name of a node to connect to and the time we should wait before - retrying. The outgoing_t is kept either in the event queue or by the - corresponding connection_t. - -2002-02-09 15:32 Guus Sliepen - - * src/net.c: Don't quit because of tap read errors. - -2002-02-09 12:06 Guus Sliepen - - * src/: net.c, protocol_key.c: Allow packet encryption to be turned - of with Cipher = none. - -2002-02-08 13:02 Guus Sliepen - - * src/event.h: file event.h was initially added on branch pre5. - -2002-02-08 13:02 Guus Sliepen - - * src/event.c: file event.c was initially added on branch pre5. - -2002-02-08 13:02 Guus Sliepen - - * src/: event.c, event.h: Added functions to manage an event queue. - -2002-02-08 12:22 Guus Sliepen - - * src/protocol_node.c: ADD/DEL_NODE messages are not used anymore. - -2002-02-08 12:12 Guus Sliepen - - * src/: net.c, process.c: - - Purge unreachable nodes if there are no outgoing connections or - SIGWINCH is received. - - Actually use sigsegv_square(). - -2002-02-08 10:32 Guus Sliepen - - * src/protocol_subnet.c: Really fix del_subnet_h(). - -2002-02-07 22:37 Guus Sliepen - - * src/protocol_subnet.c: Fix handling of DEL_SUBNET messages. - -2002-02-07 22:36 Guus Sliepen - - * src/: graph.c, net.c: Fix IndirectData and TCPOnly options. - -2002-02-07 16:42 Guus Sliepen - - * doc/sample-config/: tinc-down, tinc-up, tinc.conf: Updated sample - configuration files. - -2002-02-07 15:55 Guus Sliepen - - * src/route.c: Get rid of last %hhx. - -2002-02-07 15:53 Guus Sliepen - - * src/: netutl.c, subnet.c: FreeBSD compile fixes. - -2002-02-07 15:43 Guus Sliepen - - * src/: protocol_subnet.c, route.c, subnet.c: Make tinc's IPv6 - support working. - -2002-02-07 14:21 Guus Sliepen - - * src/: netutl.c, subnet.c: OpenBSD (and probably other non-GNU - operating systems) doesn't support %hhu. - -2002-02-07 13:42 Guus Sliepen - - * src/: graph.c, netutl.c, route.c, openbsd/device.c: OpenBSD - compile fixes. - -2002-02-07 13:09 Guus Sliepen - - * src/conf.c: get_config_address() returns a pointer to a newly - created ipv4_t. - -2002-02-07 13:07 Guus Sliepen - - * src/: conf.c, conf.h, edge.c, net.c, netutl.c, netutl.h, - protocol.h, protocol_auth.c, protocol_edge.c, subnet.c, subnet.h: - Send addresses and subnets as human readable strings. - -2002-02-07 13:05 Guus Sliepen - - * doc/: PROTOCOL, SECURITY2, tinc.conf.5, tinc.texi, tincd.8: - Updated documentation. - -2002-02-07 10:48 Guus Sliepen - - * src/protocol_key.c: Really stop proxying keys. - -2002-02-07 00:51 Guus Sliepen - - * src/solaris/device.c: Fix for Solaris. - -2002-02-06 21:55 Guus Sliepen - - * po/nl.po: Update dutch translation. - -2002-02-06 21:55 Guus Sliepen - - * src/: protocol_auth.c, protocol_edge.c, protocol_subnet.c: - Display new debug messages only when debug level is set accordingly. - -2002-02-06 21:18 Guus Sliepen - - * src/: graph.c, net.c, node.h, protocol_key.c: - - Fix sequence number handling when many nodes are involved - - Use minimum spanning tree when broadcasting KEY_CHANGED - - Disable key proxying for now. - -2002-02-06 20:17 Guus Sliepen - - * acconfig.h, m4/openssl.m4, src/tincd.c: Check for - OpenSSL/SSLeay_add_all_algorithms(). - -2002-02-06 18:07 Guus Sliepen - - * po/: POTFILES.in, nl.po: More translations. - -2002-02-06 17:51 Guus Sliepen - - * src/node.c: Cleanup. - -2002-02-06 17:50 Guus Sliepen - - * lib/avl_tree.c: Clear pointers and count/depth after unlinking a - node. - -2002-02-06 16:58 Guus Sliepen - - * src/net.h: Maximum size of an ethernet frame is 1514 bytes, not - 1500. - -2002-02-06 16:46 Guus Sliepen - - * po/: POTFILES.in, nl.po: Add more translations. - -2002-02-06 16:44 Guus Sliepen - - * src/net.c: Use full keylength when calculating MAC, and allow - large UDP packets to be received. - -2002-02-06 15:38 Guus Sliepen - - * src/protocol_key.c: Fix ans_key_h(). - -2002-02-06 15:27 Guus Sliepen - - * src/protocol_key.c: Copy key to node_t before forwarding it. - -2002-02-06 15:09 Guus Sliepen - - * src/: graph.c, node.c: Quick hack to fix node_udp_compare(). - -2002-02-06 14:57 Guus Sliepen - - * src/net.c: Don't send packets to nodes that are not reachable. - -2002-02-06 14:43 Guus Sliepen - - * src/: graph.c, node.c: Don't forget to manage the node_udp_tree. - -2002-02-06 14:14 Guus Sliepen - - * src/graph.c: FreeBSD compile fix. - -2002-02-06 14:07 Guus Sliepen - - * src/net.c: Don't complain about missing Port variable, use - default (655) instead. - -2002-02-06 14:05 Guus Sliepen - - * doc/tinc.conf.5: Update configuration manual. - -2002-02-06 14:04 Guus Sliepen - - * src/freebsd/device.c: Declare correct variable name. - -2002-02-06 13:35 Guus Sliepen - - * po/nl.po, src/graph.c, src/subnet.c: Added one message to be - translated. - -2002-02-06 13:25 Guus Sliepen - - * po/nl.po, src/graph.c, src/node.h, src/protocol_key.c: Cleanups. - -2002-02-05 16:17 Guus Sliepen - - * src/: Makefile.am, connection.c, connection.h, edge.c, edge.h, - graph.c, graph.h, net.c, node.c, node.h, protocol.c, protocol.h, - protocol_auth.c, protocol_edge.c, protocol_key.c, - protocol_subnet.c: - - Move information about cipher and digest from ACK to SEND_KEY - - Move information about addresses and portnumbers from ADD_NODE to - ADD_EDGE - - Stop exchanging information about nodes at all, it can be derived - from the ADD_EDGE and ADD_SUBNET messages. - - Don't purge anything. Only authorative nodes are allowed to delete - edges and subnets. This means we remember information about nodes - that may not be reachable anymore, but reduces amount of - ADD/DEL_SUBNET/EDGE messages. - - Lots of bugfixes. - -2002-02-03 23:18 Guus Sliepen - - * src/tincd.c: Woops! - -2002-02-03 23:14 Guus Sliepen - - * src/: net.h, node.h, process.c, protocol.c, protocol.h, - protocol_key.c, tincd.c: Cleanups. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_subnet.c: file protocol_subnet.c was initially added - on branch pre5. - -2002-02-03 22:29 Guus Sliepen - - * src/: Makefile.am, protocol.c, protocol.h, protocol_auth.c, - protocol_edge.c, protocol_key.c, protocol_misc.c, protocol_node.c, - protocol_subnet.c: Split up protocol.c. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_misc.c: file protocol_misc.c was initially added on - branch pre5. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_node.c: file protocol_node.c was initially added on - branch pre5. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_edge.c: file protocol_edge.c was initially added on - branch pre5. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_key.c: file protocol_key.c was initially added on - branch pre5. - -2002-02-03 22:29 Guus Sliepen - - * src/protocol_auth.c: file protocol_auth.c was initially added on - branch pre5. - -2002-02-01 17:00 Guus Sliepen - - * src/: net.c, protocol.c: Fixes for some buglets. - -2002-01-29 12:50 Guus Sliepen - - * src/: net.c, protocol.c: Some fixes to make cipher/digest - selection actually work. - -2002-01-29 00:26 Guus Sliepen - - * src/: net.c, net.h, node.c, node.h, protocol.c, tincd.c: - - Removed salt in favour of sequence numbers. - - Packet encryption is now fully configurable: - - option "Cipher" takes name of a cipher as argument (default - "blowfish") - - option "Digest" takes name of a digest as argument (default - "sha1") - - option "MACLength" takes length of message authentication code as - argument (default 4), set to 0 to turn it off completely. - -2002-01-24 18:03 Guus Sliepen - - * src/net.c: Don't retry if all outgoing connections work. - -2002-01-22 22:52 Guus Sliepen - - * src/net.c: More #ifdefs around use of sequence numbers. - -2002-01-22 22:46 Guus Sliepen - - * src/linux/device.c: Don't use iovecs with Linux ethertap device. - -2002-01-14 01:29 Guus Sliepen - - * TODO: Updated TODO list. - -2002-01-14 00:57 Guus Sliepen - - * src/: net.c, net.h, node.h, protocol.c: Experimental changes to - fix the security weaknesses found by Jerome Etienne. Compile with - MORESECURE defined to add replay protection and packet - authentication. - -2001-12-23 15:06 Guus Sliepen - - * src/protocol.c: Exchange options during authentication (enables - IndirectData and TCPOnly) - -2001-12-23 15:06 Guus Sliepen - - * src/conf.c: Fix boolean "no". - -2001-12-20 14:53 Guus Sliepen - - * src/protocol.c: Resynchronise completely after receiving bad - DEL_EDGE. - -2001-12-18 22:12 Guus Sliepen - - * doc/: tinc.conf.5, tincd.8: - - Revamped man pages to make them more maintainable. - - Reflect new and changed options. - -2001-12-18 22:10 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2001-12-18 15:33 Guus Sliepen - - * src/linux/device.c: Make mymac extern. - -2001-12-18 15:32 Guus Sliepen - - * src/freebsd/device.c: FreeBSD compile fixes. - -2001-12-18 00:11 Guus Sliepen - - * src/: graph.c, net.c, node.h, protocol.c: Updated semantics for - the meta protocol and fixed a few small bugs. - -2001-12-16 14:51 Guus Sliepen - - * configure.in, src/conf.c, src/conf.h, src/net.c: Added - configurable statistics logging for the Cube project. - -2001-11-16 23:41 Ivo Timmermans - - * src/net.c: Conversion to struct addrinfo is almost complete for - this file. - -2001-11-16 23:40 Ivo Timmermans - - * src/tincd.c: Don't include netutl.h. - -2001-11-16 23:31 Ivo Timmermans - - * src/conf.c: Fixed silly typo: "np" instead of "no" - -2001-11-16 23:31 Ivo Timmermans - - * src/conf.c: get_config_subnet needs to be fixed. - -2001-11-16 18:40 Ivo Timmermans - - * src/route.c: route_ipv4 and route_ipv6 replaced by route_ip. - -2001-11-16 18:39 Ivo Timmermans - - * src/protocol.c: Don't include netutl.h. - -2001-11-16 18:39 Ivo Timmermans - - * src/node.c: lookup_node_udp changed. - -2001-11-16 18:38 Ivo Timmermans - - * src/net.c: First part of rewriting things to use struct addrinfo. - -2001-11-16 18:36 Ivo Timmermans - - * lib/: dropin.c, dropin.h: Added dropin replacements for get*info - and helper functions. - -2001-11-16 17:16 Ivo Timmermans - - * acconfig.h: Added HAVE_STRUCT_ADDRINFO - -2001-11-16 16:56 Ivo Timmermans - - * src/node.h: - (re)added port to struct node_t - -2001-11-16 13:21 Ivo Timmermans - - * src/: netutl.c, netutl.h: Obsoleted. - -2001-11-16 13:20 Ivo Timmermans - - * src/: connection.c, edge.c, net.c: Don't include netutl.h. - -2001-11-16 13:17 Ivo Timmermans - - * src/conf.c: Don't include netutl.h. - -2001-11-16 13:16 Ivo Timmermans - - * src/Makefile.am: Don't compile/link netutl.c. - -2001-11-16 13:14 Ivo Timmermans - - * src/conf.h: get_config_{ip,port} removed. - -2001-11-16 13:12 Ivo Timmermans - - * src/: node.h, edge.h: Changed to use struct addrinfo where - needed. - -2001-11-16 13:10 Ivo Timmermans - - * src/subnet.h: Obsoleted all IP types in favor of struct - addrinfo - -2001-11-16 13:08 Ivo Timmermans - - * src/net.h: Removed definitions of ipv4_t, ipv6_t, port_t - -2001-11-16 13:02 Ivo Timmermans - - * src/connection.c: Changed lookup_connection to use struct - addrinfo - -2001-11-16 13:01 Ivo Timmermans - - * src/connection.h: Changed prototype for lookup_connection to use - struct addrinfo - -2001-11-16 01:23 Ivo Timmermans - - * src/connection.h: Use struct addrinfo in connection_t to hold all - host data such as IP address and port - -2001-11-16 01:13 Ivo Timmermans - - * src/conf.c: Deprecated get_config_ip and get_config_port - -2001-11-16 00:49 Ivo Timmermans - - * configure.in: Check for struct addrinfo - -2001-11-16 00:28 Ivo Timmermans - - * AUTHORS: Credit OpenSSH - -2001-11-16 00:26 Ivo Timmermans - - * configure.in: Check for getnameinfo, gai_strerror, freeaddrinfo - -2001-11-16 00:05 Ivo Timmermans - - * configure.in: Check for getaddrinfo - -2001-11-05 20:09 Guus Sliepen - - * lib/dropin.c, lib/utils.c, src/net.c: More fixes for Solaris. - -2001-11-05 20:06 Guus Sliepen - - * lib/dropin.c, lib/dropin.h, lib/utils.c, src/solaris/device.c: - Various fixes needed for Solaris. - -2001-11-05 00:48 Guus Sliepen - - * src/protocol.c: Correctly check if subnet owner exists. - -2001-11-05 00:29 Guus Sliepen - - * src/protocol.c: Be liberal in what you accept: allow unknown - edges to be deleted. - -2001-11-03 23:53 Guus Sliepen - - * src/: net.c, process.c: [no log message] - -2001-11-03 22:22 Guus Sliepen - - * src/protocol.c: Several bugfixes. - -2001-11-03 22:21 Guus Sliepen - - * src/net.c: Use PEM functions as suggested by OpenSSL docs. - -2001-10-31 21:37 Guus Sliepen - - * src/: netutl.c, process.c, protocol.c: Some very small fixes - -2001-10-31 21:22 Guus Sliepen - - * src/net.c: Avoid connecting to another node twice, and check name - of outgoing connections. - -2001-10-31 21:07 Guus Sliepen - - * src/conf.c: Show cfg->variable instead of cfg->value when - complaining about wrong type. - -2001-10-31 21:02 Guus Sliepen - - * src/protocol.c: Don't forget to read public RSA key when making - an outgoing connection. - -2001-10-31 13:50 Guus Sliepen - - * src/: device.h, graph.c, graph.h, net.c, node.c, process.c, - protocol.c, linux/device.c: - - Small fixes to graph algorithms - - More control over tap device, ability to set interface name to - something other than the netname. - - Export NETNAME, DEVICE and INTERFACE environment variables to - scripts. - -2001-10-30 17:34 Guus Sliepen - - * src/: connection.c, connection.h, net.c, protocol.c: More updates - to protocol handlers and reimplemented terminate_connection(). - -2001-10-30 13:59 Guus Sliepen - - * src/: Makefile.am, edge.c, graph.c, net.c, node.c, protocol.c, - subnet.c: Various fixes, tinc is now somewhat capable of actually - working again. - -2001-10-29 14:14 Guus Sliepen - - * src/graph.h: file graph.h was initially added on branch CABAL. - -2001-10-29 14:14 Guus Sliepen - - * src/: graph.c, graph.h: Working version of Kruskal's algorithm. - The running time is very bad though. - -2001-10-28 23:42 Guus Sliepen - - * src/: connection.c, connection.h, edge.c, edge.h, graph.c, - node.c, node.h, protocol.c, subnet.c, subnet.h: - - More changes needed for Kruskal's algorithm - - Implemented a breadth-first search algorithm as a cheap - substitution for a single-source shortest path algorithm. - -2001-10-28 11:16 Guus Sliepen - - * src/graph.c: file graph.c was initially added on branch CABAL. - -2001-10-28 11:16 Guus Sliepen - - * src/: Makefile.am, connection.h, edge.c, edge.h, graph.c, net.c, - node.h, process.c, protocol.c: - - More s/vertex/edge/g - - Implementation of Kruskal's minimum spanning tree algorithm. - -2001-10-28 09:41 Guus Sliepen - - * src/edge.c: file edge.c was initially added on branch CABAL. - -2001-10-28 09:41 Guus Sliepen - - * src/: Makefile.am, conf.h, connection.c, connection.h, edge.c, - edge.h, net.c, protocol.c, protocol.h, tincd.c, vertex.c, vertex.h: - What was I thinking? s/vertex/edge/g. - -2001-10-28 09:41 Guus Sliepen - - * src/edge.h: file edge.h was initially added on branch CABAL. - -2001-10-27 17:19 Guus Sliepen - - * src/: conf.c, connection.c, net.c, process.c, tincd.c: Various - small fixes to make tinc runnable again. - -2001-10-27 15:13 Guus Sliepen - - * src/: device.h, net.c, net.h, node.c, process.c, route.c, - subnet.c, subnet.h, vertex.c, linux/device.c: Make sure everything - links. - -2001-10-27 14:13 Guus Sliepen - - * src/: conf.c, conf.h, connection.c, connection.h, device.h, - meta.c, net.c, net.h, netutl.c, netutl.h, node.c, node.h, - process.c, protocol.c, protocol.h, route.c, route.h, subnet.c, - subnet.h, tincd.c, vertex.c, vertex.h, linux/device.c: Big bad - commit: - - Transition to new node/vertex/connection structures - - Use new configuration handling everywhere - - Linux tun/tap device handling cleanup - - Start of IPv6 support in route.c - - It compiles, but it won't link. - -2001-10-13 15:53 Guus Sliepen - - * acconfig.h, configure.in, src/Makefile.am: Support new files - (node/vertex/device.[ch]) and OpenBSD. - -2001-10-12 17:52 Guus Sliepen - - * src/openbsd/device.c: Forgot the tun specific stuff. - -2001-10-12 17:49 Guus Sliepen - - * src/openbsd/device.c: file device.c was initially added on branch - CABAL. - -2001-10-12 17:49 Guus Sliepen - - * src/openbsd/device.c: Added OpenBSD tun device handling. Untested - though. - -2001-10-12 17:38 Guus Sliepen - - * src/solaris/device.c: Forgot to remove some old #ifdef stuff. - -2001-10-12 17:33 Guus Sliepen - - * src/solaris/device.c: file device.c was initially added on branch - CABAL. - -2001-10-12 17:33 Guus Sliepen - - * src/solaris/device.c: Solaris tun device handling cleaned up a - bit and added. - -2001-10-12 17:22 Guus Sliepen - - * src/freebsd/device.c: Added FreeBSD tap device handling. - -2001-10-12 17:22 Guus Sliepen - - * src/freebsd/device.c: file device.c was initially added on branch - CABAL. - -2001-10-12 17:16 Guus Sliepen - - * src/linux/device.c: file device.c was initially added on branch - CABAL. - -2001-10-12 17:16 Guus Sliepen - - * src/: device.h, linux/device.c: - - Split tap device stuff out of net.[ch] - - Each OS gets it's own device.c to get rid of evil #ifdefs. - - Cleaned up Linux ethertap and tun/tap handling. - -2001-10-12 17:16 Guus Sliepen - - * src/device.h: file device.h was initially added on branch CABAL. - -2001-10-10 22:35 Guus Sliepen - - * src/: connection.c, connection.h, node.h, vertex.h: More updates - to new node/vertex/connection combo. - -2001-10-10 22:34 Guus Sliepen - - * src/: conf.c, conf.h: Revamp configuration handling: - - Store everything in AVL trees (fast lookup) - - No need for hazahaza anymore - - Parse values when needed - - This simplifies a lot of config variable lookups. - -2001-10-10 11:42 Guus Sliepen - - * src/: connection.c, connection.h: Removed everything from - connection.c that has already been moved to node.c and vertex.c. - -2001-10-10 10:49 Guus Sliepen - - * src/node.c: file node.c was initially added on branch CABAL. - -2001-10-10 10:49 Guus Sliepen - - * src/vertex.c: file vertex.c was initially added on branch CABAL. - -2001-10-10 10:49 Guus Sliepen - - * src/: connection.h, node.c, node.h, vertex.c, vertex.h: Further - implementation of doc/CONNECTIVITY. connection.[ch] is now split - into a node, vertex and connection part. - -2001-10-09 21:41 Wessel Dankers - - * autogen.sh: make is not always GNU make. - -2001-10-09 21:37 Guus Sliepen - - * src/: node.h, vertex.h: Small corrections. - -2001-10-09 21:30 Guus Sliepen - - * src/: node.h, vertex.h: Started implementing doc/CONNECTIVITY. - -2001-10-09 21:30 Guus Sliepen - - * src/node.h: file node.h was initially added on branch CABAL. - -2001-10-09 21:30 Guus Sliepen - - * src/vertex.h: file vertex.h was initially added on branch CABAL. - -2001-10-08 17:47 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2001-10-08 17:37 Guus Sliepen - - * src/protocol.c: Fix bug when dropping an old connection in favour - of a new one from the same host. - -2001-10-08 15:37 Guus Sliepen - - * src/net.c: - - Use ping timeout mechanism to close connections that don't - authenticate in time. - - Fix potential segmentation fault in check_dead_connections(). - -2001-10-08 13:59 Guus Sliepen - - * src/net.c: Fix bug where tinc would crash because of a portscan - or a connection from a tinc daemon with a different version. - -2001-10-08 13:47 Guus Sliepen - - * src/: connection.c, connection.h, net.c, protocol.c: - - Renamed lastbutonehop to prevhop. - - Added connection_t *via to connection_t, this keeps record of - where to send UDP packets to. - -2001-09-25 15:39 Guus Sliepen - - * src/net.c: Fill in next- and lastbutonehop for myself. - -2001-09-25 15:35 Guus Sliepen - - * src/net.c: Try next connectto instead of the same over and over. - -2001-09-24 16:16 Guus Sliepen - - * src/connection.c: Show next- and lastbutonehop when dumping - connectionlist to syslog. - -2001-09-24 16:11 Guus Sliepen - - * src/: connection.h, net.c, protocol.c, protocol.h: Not only keep - track of nexthop, but also of lastbutonehop. If destination cl wants - indirectdata, send it to the lastbutonehop instead, unless it too - has requested so, and so on. - -2001-09-24 15:31 Guus Sliepen - - * src/net.c: - - Try old TUN/TAP ioctl() request if the one from if_tun.h fails. - - Be more verbose about the kind of tap device used. - -2001-09-05 20:38 Ivo Timmermans - - * src/process.c: Killing tincd with SIGINT causes it to toggle - between the current debug level and level 5. Useful to debug a - running tincd. - -2001-09-01 14:46 Guus Sliepen - - * src/: conf.c, conf.h: config_t* is a const parameter in - get_config_val(). - -2001-09-01 14:36 Guus Sliepen - - * src/: process.c, process.h, tincd.c: Optional signal number for - -k option. - -2001-09-01 14:36 Guus Sliepen - - * src/net.c: Revised reconnection mechanism, always try out all - ConnectTo lines. - -2001-09-01 14:02 Guus Sliepen - - * src/protocol.c: Remove IndirectData support for now, new - implementation will be added later. - -2001-08-28 22:52 Guus Sliepen - - * src/subnet.c: Fix signed comparison bug in lookup_subnet_ipv4(). - -2001-08-17 20:14 Guus Sliepen - - * src/: net.c, protocol.c: Don't send DEL_HOSTs when !status.meta - -2001-07-24 22:14 Guus Sliepen - - * src/net.c: Explicitly log which type of tunnel device is used. - -2001-07-24 22:13 Guus Sliepen - - * src/conf.h: The val variable in a config_t is never used as a - long. - -2001-07-24 22:04 Guus Sliepen - - * src/tincd.c: Write public key to rsa_key.pub instead of - rsa_key.priv (if not host configuration file is found). - -2001-07-24 22:03 Guus Sliepen - - * src/: conf.c, process.c: Don't use %m in fprintf(). - -2001-07-24 10:51 Guus Sliepen - - * doc/CONNECTIVITY: More on edges. - -2001-07-24 00:06 Guus Sliepen - - * doc/CONNECTIVITY: Discuss how sending ADD_EDGEs would be better - than sending ADD_HOSTs. - -2001-07-22 19:41 Guus Sliepen - - * doc/CONNECTIVITY: Written down a possible solution. - -2001-07-22 17:25 Guus Sliepen - - * doc/CONNECTIVITY: Correctie. - -2001-07-22 16:58 Guus Sliepen - - * doc/CONNECTIVITY: Small update. - -2001-07-22 16:46 Guus Sliepen - - * doc/CONNECTIVITY: Described problem in more detail. - -2001-07-22 16:04 Guus Sliepen - - * doc/CONNECTIVITY: file CONNECTIVITY was initially added on branch - CABAL. - -2001-07-22 16:04 Guus Sliepen - - * doc/CONNECTIVITY: Started writing a document about how daemons - connect to each other. - -2001-07-21 22:21 Guus Sliepen - - * src/: net.c, route.c: Woohoo! tinc now compiles, runs and - actually *works* on Solaris! Tested on a SparcStation 20MP running - Solaris 7. (Thanks, jiggel!) - -2001-07-21 17:46 Guus Sliepen - - * src/net.c: Always close all sockets in terminate_connection(). - -2001-07-21 17:34 Guus Sliepen - - * src/: connection.c, net.c, net.h, protocol.c: Updated - terminate_connection() so you can choose if DEL_HOSTs should be sent - or not. - -2001-07-20 22:25 Guus Sliepen - - * src/: connection.c, connection.h, net.c, protocol.c, route.c: - Added purge_tree for connection_t's which are no longer in the - connection, active or id trees, but which may still be referenced. - This tree is flushed when it is safe, this replaces - purge_connection_tree(). - - Also lots of bugfixes related to the new trees. - -2001-07-20 15:54 Guus Sliepen - - * src/: meta.c, net.c, protocol.c, route.c, tincd.c: Remove all - unnecessary status.meta and status.active checks. - -2001-07-19 14:29 Guus Sliepen - - * src/: net.c, protocol.c: Correctly use the active_tree. - -2001-07-15 20:07 Guus Sliepen - - * src/: connection.c, connection.h, net.c, protocol.c: Split - connection list into two lists: - - one list to handle all incoming/outgoing TCP connections - - another list to handle all UDP connections - - This will prevent race conditions. - -2001-07-15 16:21 Guus Sliepen - - * m4/tuntap.m4, src/net.c: Correct inclusion of standard if_tun.h - header file. - -2001-07-04 10:43 Guus Sliepen - - * src/tincd.c: Don't load table of verbose OpenSSL errormessages. - -2001-07-04 10:41 Guus Sliepen - - * m4/openssl.m4, src/meta.c, src/net.c, src/protocol.c, - src/tincd.c: - - Always use instead of just - - Check if RAND_pseudo_bytes() exists, otherwise just use - RAND_bytes() - -2001-07-01 23:42 Guus Sliepen - - * src/protocol.c: Check for all potential duplicate entries in the - id tree. - -2001-07-01 11:21 Guus Sliepen - - * src/route.c: Fix compiler warning. - -2001-07-01 11:21 Guus Sliepen - - * po/nl.po, src/protocol.c: Fix printf format bug. - -2001-07-01 11:06 Guus Sliepen - - * TODO: More items marked as done. - -2001-06-29 17:38 Guus Sliepen - - * po/nl.po: Dutch translation updated. - -2001-06-29 17:33 Guus Sliepen - - * Makefile.am, redhat/tinc, redhat/tinc.spec: Update of RedHat - build scripts. - -2001-06-29 17:32 Guus Sliepen - - * po/: es.po, nl.po, old/es.po: It appears that autogen.sh doesn't - like es.po if it isn't mentioned in the makefile/configure scripts. - -2001-06-29 17:32 Guus Sliepen - - * po/old/es.po: file es.po was initially added on branch CABAL. - -2001-06-29 16:15 Guus Sliepen - - * m4/openssl.m4: Check for dlopen in standard libraries first - (needed for DEC OSF). - -2001-06-29 15:09 Guus Sliepen - - * src/: connection.c, subnet.c: Fix gcc 3.0 warnings. - -2001-06-29 15:09 Guus Sliepen - - * src/protocol.c: Log error if two hosts connect with same IP/port - tuple. - -2001-06-29 13:09 Guus Sliepen - - * Makefile.am: Also remove po/Makefile.in.in, which is generated by - autogen.sh. - -2001-06-29 13:03 Guus Sliepen - - * po/es.po: es.po revived. - -2001-06-29 12:30 Guus Sliepen - - * src/net.c: Execute tinc-down BEFORE tap device is closed. This is - a. more symmetric (tinc-up is started after tap device is opened) - and b. is needed for tun/tap device, where the interface does not - exist anymore after the device file is closed. - -2001-06-29 12:27 Guus Sliepen - - * configure.in: Don't build Spanish translation. - -2001-06-29 12:27 Guus Sliepen - - * ABOUT-NLS, Makefile.am: ABOUT-NLS is created by autogen.sh. - -2001-06-29 12:23 Guus Sliepen - - * po/es.po: Spanish translation removed. Nobody maintains it, and - it is severely outdated. - -2001-06-27 00:00 Ivo Timmermans - - * m4/tuntap.m4: Small fix to make it compile again - -2001-06-21 20:28 Guus Sliepen - - * m4/tuntap.m4: Reinstated search for if_tun.h in kernel source - tree, because apparently /usr/include/linux does not always have the - same contents as the include files from the currently running - kernel. - -2001-06-21 18:37 Guus Sliepen - - * src/net.c: Remove #warnings I used for debugging stuff. - -2001-06-21 18:37 Guus Sliepen - - * m4/openssl.m4: Check for and add -ldl. - -2001-06-21 18:16 Guus Sliepen - - * src/: net.c, route.c: - - Solaris compile fixes - - Set mymac to broadcast MAC so that ifconfig hw ether <...> is - really not needed anymore. - - Forwarding of indirect packets when in switch mode (because the - kernel will not do it for us then). - -2001-06-20 23:32 Ivo Timmermans - - * Makefile.am: Don't include the debian/ dir in a release - -2001-06-09 12:00 Guus Sliepen - - * src/protocol.c: Woops - big bug in send_key_changed fixed. - -2001-06-08 20:02 Guus Sliepen - - * src/: net.c, net.h, protocol.c: Only reset seconds_till_retry - when we activate the outgoing connection. - -2001-06-07 09:51 Guus Sliepen - - * m4/openssl.m4: Changed drastically because it didn't work - correctly: - - Don't cache the --with-openssl-* option arguments - - Only search for openssl/*.h, the openssl include files include - other files only from an openssl/ directory too - - Set CPPFLAGS before AC_CHECK_HEADERS - -2001-06-07 09:48 Guus Sliepen - - * configure.in: Save configure cache more often. - -2001-06-06 21:12 Guus Sliepen - - * src/route.c: Fixes to make switching work between hosts that have - no meta-connection. - -2001-06-06 21:11 Guus Sliepen - - * src/subnet.c: Log and warn about duplicate subnet_add()'s for the - same subnet. - -2001-06-05 21:45 Guus Sliepen - - * src/net.c: Add missing? counting of total_socket_in. - -2001-06-05 21:39 Guus Sliepen - - * src/: conf.c, conf.h, net.c: You can now put an option "Mode" in - tinc.conf, and choose from: - - - Mode = router (default, work like tinc has always worked) - - Mode = switch (work like a switch) - - Mode = hub (work like a hub, broadcasting everything) - -2001-06-05 20:07 Guus Sliepen - - * src/subnet.c: Fix bug where lookup_subnet_ipv4() could go into an - infinite loop. - -2001-06-05 18:31 Guus Sliepen - - * src/route.c: - - This oneliner removes the need for ifconfig tap? hw ether - fe:fd:0:0:0:0 - -2001-06-05 18:15 Guus Sliepen - - * po/nl.po: Updated dutch translation. - -2001-06-05 18:13 Guus Sliepen - - * Makefile.am, configure.in: Changed some stuff to allow correct - generation of po/Makefile after a make cvs-clean. - -2001-06-05 18:09 Guus Sliepen - - * src/: connection.c, net.c, net.h, protocol.c, route.c, subnet.c, - tincd.c: - - tinc can now act as a switch or a hub too (as opposed to a router - only) - - cleaner initialisation of "UNKNOWN" and "MYSELF" names - -2001-06-04 13:14 Guus Sliepen - - * src/route.c: Added proxy-arp support. No more ifconfig -arp - needed. Works like a charm under FreeBSD now :). - -2001-06-01 10:02 Guus Sliepen - - * src/subnet.c: Fix subnet_lookup() for overlapping subnets. Needs - rethinking. - -2001-05-28 10:56 Guus Sliepen - - * src/: net.c, tincd.c: Make sure Solaris is happy too. - -2001-05-28 10:21 Guus Sliepen - - * src/: net.c, route.c: Small fixes to allow correct compilation - under FreeBSD (tested with 4.3) - -2001-05-26 11:35 Ivo Timmermans - - * Makefile.am: Don't distribute autogen.sh in a release - -2001-05-26 11:35 Ivo Timmermans - - * configure.in: Changed version number to 1.0-cvs - -2001-05-26 11:34 Ivo Timmermans - - * Makefile.am: New make target: `make release' - -2001-05-25 20:57 Guus Sliepen - - * doc/: SECURITY, sample-config/tinc-down, sample-config/tinc-up, - sample-config/hosts/alpha, sample-config/hosts/alpha.key, - sample-config/hosts/beta, sample-config/hosts/beta.key: Fix sample - configuration to show keys in PEM format and correct tapdevice. - -2001-05-25 15:24 Guus Sliepen - - * TODO: Documents are merged. Now we only need to check the ports - and the TCPonly and IndirectData options. - -2001-05-25 14:45 Guus Sliepen - - * doc/tinc.texi: Merged PROTOCOL, NETWORK and SECURITY2 with the - texinfo manual. - -2001-05-25 13:54 Guus Sliepen - - * src/: connection.h, meta.c, net.c, net.h, protocol.c, route.c: - TCPonly now works (in a relatively clean way too). - -2001-05-25 12:08 Guus Sliepen - - * src/net.c: With recent kernels the tun device file is located in - /dev/net. - -2001-05-25 12:06 Guus Sliepen - - * doc/: tinc.conf.5, tinc.texi, tincd.8: Small corrections to the - manuals. - -2001-05-25 10:36 Guus Sliepen - - * src/: meta.c, net.c, protocol.c: Small fixes: - - - Fix compiler warnings (one was a real (but harmless) bug) - - Don't send PING packets if there is UDP traffic - - Correctly terminate strings containing salt for PING/PONG packets - -2001-05-24 23:52 Guus Sliepen - - * src/protocol.c: Only send key_changed if it was previously - requested. - -2001-05-24 23:32 Guus Sliepen - - * TODO: All features for 1.0 are implemented now, we just have to - check the FreeBSD and Solaris ports and merge some docs. - -2001-05-24 23:30 Guus Sliepen - - * src/protocol.h: Since this is incompatible with some earlier - versions, PROT_CURRENT is increased. - -2001-05-24 23:29 Guus Sliepen - - * src/protocol.c: Add randomness to PING/PONG packets to prevent - crypto attacks on quiet tunnels. - -2001-05-24 22:40 Guus Sliepen - - * doc/tinc.conf.5: Changed URL from kernelnotes.org to - linuxdoc.org. - -2001-05-24 22:24 Guus Sliepen - - * doc/tinc.texi: More revisions to the documentation: - - - Removed cruft - - Reordered some sections to make it more logical for the beginner - - Added small examples and hints about configuration files - -2001-05-19 17:50 Guus Sliepen - - * doc/tinc.texi: - - Make sure correct information is supplied for both old kernels - (with ethertap) and for new kernels (with TUN/TAP driver). - - Revised example configuration and made it conform to latest (CVS) - version of tinc. - -2001-05-07 21:08 Guus Sliepen - - * ABOUT-NLS, src/net.c, src/net.h, src/netutl.c, src/protocol.c: - - s/ip_t/ipv4_t/g - - Add "salt" to the beginning of UDP packets. Replaces length field - which is not useful anyway. - -2001-05-04 20:45 Guus Sliepen - - * TODO, src/net.c: Correctly cycle through ConnectTo variables. - -2001-03-13 22:33 Guus Sliepen - - * src/protocol.c: Check indirectdata option before forwarding - certain requests. - -2001-03-13 22:32 Guus Sliepen - - * src/net.c: Ignore alarm signals if we do not need to respond to - them. - -2001-03-13 10:55 Guus Sliepen - - * src/process.c: Fixed bug in setup_signals() that would make tinc - die when unexpected signals were caught. - -2001-03-13 00:58 Guus Sliepen - - * src/meta.c: Fixed a race condition triggered by receive_meta() - and the new authentication scheme. - -2001-03-04 15:00 Guus Sliepen - - * doc/NETWORKING: file NETWORKING was initially added on branch - CABAL. - -2001-03-04 15:00 Guus Sliepen - - * doc/NETWORKING: Added a description of what is going on in net.c - and route.c, and how packets flow through tinc. - -2001-03-04 14:59 Guus Sliepen - - * po/: POTFILES.in, es.po, nl.po: Updated translation. - -2001-03-04 14:59 Guus Sliepen - - * src/: Makefile.am, connection.c, connection.h, net.c, net.h, - protocol.c, route.c, route.h: - - route.c is now used to determine destination - - flags are removed, since they were not used at all. Use options - instead. - - indirectdata works now, tcponly almost... - - made functions that don't return useful information void - -2001-03-02 12:25 Guus Sliepen - - * src/protocol.c: Added explaination of our key exchange using RSA - encryption. - -2001-03-01 22:32 Guus Sliepen - - * src/: net.c, process.c, process.h, tincd.c: Various small fixes. - -2001-02-27 17:50 Guus Sliepen - - * lib/avl_tree.c: Removed compiler warning. - -2001-02-27 17:37 Guus Sliepen - - * src/: conf.h, net.c, net.h, protocol.c, tincd.c: Removed lots of - compiler warnings. - -2001-02-27 17:17 Guus Sliepen - - * src/net.c: - - Fixed Interface option (untested) - - Removed error handling for non-critical socket options - - Added TCP_NODELAY and IPTOS_LOWDELAY options for meta sockets. - -2001-02-27 17:15 Ivo Timmermans - - * TODO: Authentication done - -2001-02-27 16:33 Guus Sliepen - - * src/net.c: Don't forget to reconnect if outgoing connection fails - during authentication. - -2001-02-26 12:37 Guus Sliepen - - * src/protocol.c: - - Make sure METAKEY is smaller than the modulus of the RSA key - - Get symmetric key from the least significant bytes of the RSA - message - -2001-02-25 21:17 Guus Sliepen - - * po/: POTFILES.in, es.po, nl.po: Added process.c to the translated - files. - -2001-02-25 20:09 Guus Sliepen - - * src/: net.c, protocol.c, protocol.h: Implemented new - authentication scheme from doc/SECURITY2. - -2001-02-25 17:34 Guus Sliepen - - * src/: net.c, protocol.c: Encrypt network packets in CBC mode - instead of CFB mode. (This breaks compatibility with all previous - versions!) - -2001-02-25 17:04 Guus Sliepen - - * src/net.c: Copy packets before putting them in the queue. - -2001-02-25 16:34 Guus Sliepen - - * lib/list.c: Free node->data and node, not node->data twice. - -2001-02-25 15:51 Guus Sliepen - - * po/es.po, po/nl.po, src/tincd.c: Add missing \n. - -2001-02-25 12:09 Guus Sliepen - - * src/: meta.c, protocol.c: Corrected check for errors after read() - calls. - -2001-02-20 22:53 Wessel Dankers - - * lib/avl_tree.c: Important bugfix in avl_insert_before() and - avl_insert_after() - -2001-02-18 03:13 Ivo Timmermans - - * m4/tuntap.m4: tinc_TUNTAP now substitutes the values outside the - AC_CACHE_CHECK block. configure should now correctly set - HAVE_TUNTAP. - -2001-02-13 10:54 Guus Sliepen - - * doc/SECURITY2: Added description of the proposed new - authentication scheme. - -2001-02-13 10:54 Guus Sliepen - - * doc/SECURITY2: file SECURITY2 was initially added on branch - CABAL. - -2001-02-11 12:55 Ivo Timmermans - - * doc/es/.cvsignore, lib/.cvsignore, redhat/.cvsignore: file - .cvsignore was initially added on branch CABAL. - -2001-02-11 12:55 Ivo Timmermans - - * .cvsignore, doc/.cvsignore, doc/es/.cvsignore, lib/.cvsignore, - redhat/.cvsignore, src/.cvsignore: More files to ignore in CVS - -2001-02-11 12:50 Guus Sliepen - - * Makefile.am, autogen.sh, lib/Makefile.am, src/Makefile.am: - - Updated CVS_CREATED to remove intl/ directory and some other - autogenerated files. - - Checked if all INCLUDES/LIBS/etc directives inherit the global - variables. - -2001-02-11 12:46 Guus Sliepen - - * src/.cvsignore: Ignore file for src/ - -2001-02-11 12:44 Guus Sliepen - - * .cvsignore, doc/.cvsignore, m4/.cvsignore, po/.cvsignore: Added - .cvsignore files to get rid of warnings and prevent autogenerated - files from being added accidentaly. - -2001-02-11 12:44 Guus Sliepen - - * .cvsignore, doc/.cvsignore, m4/.cvsignore, po/.cvsignore, - src/.cvsignore: file .cvsignore was initially added on branch - CABAL. - -2001-02-06 11:42 Guus Sliepen - - * src/protocol.c: Removed another local definition of the variable - "errno" - -2001-02-06 11:13 Guus Sliepen - - * po/: es.po, nl.po: Updated dutch translation. - -2001-02-06 11:13 Guus Sliepen - - * lib/: avl_tree.c, avl_tree.h: Fix memory leak in avl_insert() if - item was already inserted. - -2001-02-06 11:12 Guus Sliepen - - * lib/dropin.c, src/protocol.c: FreeBSD compile fixes (thanks to - XeF4) - -2001-01-18 14:01 Ivo Timmermans - - * doc/: Makefile.am, Makefile.maint: Distribute the sample config - as a .tar.gz - -2001-01-18 14:00 Ivo Timmermans - - * doc/tinc.texi: Fixed some errors - -2001-01-17 02:48 Ivo Timmermans - - * po/: es.po, nl.po: Get the PO files up to date with the current - source - -2001-01-17 02:40 Ivo Timmermans - - * doc/tinc.texi: Merged documentation with various updates I had - lying around - -2001-01-17 02:34 Ivo Timmermans - - * NEWS: Second draft of the release notes - -2001-01-17 02:31 Ivo Timmermans - - * configure.in: Change version to 1.0pre4 - -2001-01-17 02:30 Ivo Timmermans - - * src/conf.c: Fix error reporting of read_config - -2001-01-13 17:36 Guus Sliepen - - * src/: conf.c, conf.h, net.c, tincd.c: - - Allow ASN1 style keys to be in the config files. - Note: tinc ignores private key in the main config file, tinc.conf, - because it should really be in a separate file. - - When generating new keys, check if name is known and by default - append the public key to the host configuration file (otherwise - rsa_key.pub). - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/hosts/alpha: file alpha was initially added on - branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/hosts/alpha.key: file alpha.key was initially - added on branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/hosts/beta: file beta was initially added on - branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/hosts/beta.key: file beta.key was initially - added on branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/tinc-down: file tinc-down was initially added - on branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/tinc.conf: file tinc.conf was initially added - on branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/rsa_key.priv: file rsa_key.priv was initially - added on branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/sample-config/tinc-up: file tinc-up was initially added on - branch CABAL. - -2001-01-13 15:38 Guus Sliepen - - * doc/: tinc.conf.sample, sample-config/rsa_key.priv, - sample-config/tinc-down, sample-config/tinc-up, - sample-config/tinc.conf, sample-config/hosts/alpha, - sample-config/hosts/alpha.key, sample-config/hosts/beta, - sample-config/hosts/beta.key: Added sample configuration directory. - -2001-01-11 12:19 Guus Sliepen - - * src/net.c: - - Only send out DEL_HOSTs for hosts with a meta connection - -2001-01-08 22:32 Guus Sliepen - - * src/subnet.h: - - Cleaned up subnet_t - -2001-01-08 22:32 Guus Sliepen - - * lib/avl_tree.c: - - Sign was wrong in search_closest_smaller/greater - -2001-01-08 21:35 Guus Sliepen - - * src/protocol.c: - - Squashed another nasty bug. - -2001-01-07 21:19 Guus Sliepen - - * src/: connection.h, net.c, net.h, protocol.c, protocol.h: - - Added indirectdata and tcponly functionality. - -2001-01-07 21:19 Guus Sliepen - - * src/subnet.c: - - Fixed IPv6 subnet lookup routine. - -2001-01-07 18:08 Guus Sliepen - - * README, THANKS, TODO, doc/tinc.texi, lib/avl_tree.c, - lib/avl_tree.h, lib/dropin.c, lib/dropin.h, lib/list.c, lib/list.h, - lib/utils.c, lib/utils.h, po/es.po, po/nl.po, src/conf.c, - src/conf.h, src/connection.c, src/connection.h, src/meta.c, - src/meta.h, src/net.c, src/net.h, src/netutl.c, src/netutl.h, - src/process.c, src/process.h, src/protocol.c, src/protocol.h, - src/route.c, src/route.h, src/subnet.c, src/subnet.h, src/tincd.c: - - It's 2001, all copyright notices are updated. - -2001-01-07 18:08 Guus Sliepen - - * doc/: PROTOCOL, SECURITY: - - Description of protocol and authentication updated. - -2001-01-07 16:27 Guus Sliepen - - * src/route.h: file route.h was initially added on branch CABAL. - -2001-01-07 16:27 Guus Sliepen - - * src/route.h: - - Added header file for route.c. The routing routines in it are not - used yet, but have a look at the source for the ideas behind it. - -2001-01-07 16:25 Guus Sliepen - - * src/: connection.c, connection.h, net.c, net.h, netutl.c, - process.c, process.h, protocol.c, route.c: - - Reinstated a queue for outgoing packets. - -2001-01-07 16:24 Guus Sliepen - - * lib/: list.c, list.h: - - Changed list routines to give it the same look'n'feel as the rbl - and avl tree library. - -2001-01-06 21:43 Guus Sliepen - - * doc/tinc.conf.5: - - Typo. - -2001-01-06 21:02 Guus Sliepen - - * doc/tinc.texi: - - Updated texinfo manual. - -2001-01-06 19:44 Guus Sliepen - - * doc/: tinc.conf.5, tincd.8: - - Updated manual pages. - -2001-01-06 19:21 Guus Sliepen - - * lib/: avl_tree.c, avl_tree.h: - - Changed license of AVL tree library to GPL. - -2001-01-06 19:03 Guus Sliepen - - * src/: conf.c, protocol.c, tincd.c: - - Check and follow symlinks in is_safe_path - - By default write keys to tinc config directory - - Small fix in protocol.c - -2001-01-06 17:51 Guus Sliepen - - * po/: es.po, nl.po: - - Updated dutch translation. - -2001-01-06 00:53 Guus Sliepen - - * src/: conf.c, conf.h, connection.c, connection.h, meta.c, net.c, - process.c, protocol.c, route.c, subnet.c, subnet.h, tincd.c: - - Let user choose whether keys are in the config files or separate - - Use AVL trees instead of RBL trees - - Fixed a lot of annoying subtle bugs! Thanks to gdb... - -2001-01-06 00:51 Guus Sliepen - - * lib/: utils.c, utils.h: - - Doubled size of trace buffer for easier debugging. - -2001-01-06 00:50 Guus Sliepen - - * lib/avl_tree.h: file avl_tree.h was initially added on branch - CABAL. - -2001-01-06 00:50 Guus Sliepen - - * lib/avl_tree.c: file avl_tree.c was initially added on branch - CABAL. - -2001-01-06 00:50 Guus Sliepen - - * lib/: Makefile.am, avl_tree.c, avl_tree.h: - - AVL tree routines: faster than RBL, and also more stable. - -2000-12-22 22:34 Guus Sliepen - - * acconfig.h, configure.in, m4/gnuscanf.m4, src/conf.c, src/conf.h, - src/net.c, src/net.h, src/protocol.c: - - Don't even think about using sscanf with %as anymore - - Allow keys to be inside the config files or in a seperate file - - Small fixes - -2000-12-22 18:15 Ivo Timmermans - - * src/Makefile.am: Added lint target, requires lclint. - -2000-12-22 18:10 Ivo Timmermans - - * po/POTFILES.in: Forget router.c - -2000-12-22 17:59 Ivo Timmermans - - * Makefile.am: Include autogen.sh (needed for the Debian package). - -2000-12-06 14:33 Ivo Timmermans - - * src/: conf.c, conf.h: Re-introduced MyVirtualIP and VpnMask, as - dummy options. - -2000-12-05 09:59 Ivo Timmermans - - * src/: net.c, protocol.c: Tiny bits of code beautifying - -2000-12-05 09:56 Ivo Timmermans - - * src/conf.c: Oops. I did some VERY wrong things with readline(). - Fixed now. - -2000-12-05 09:54 Ivo Timmermans - - * doc/tinc.texi: Massive long awaited documentation update. It's - not finished yet, most notably the example configuration is still - old. - -2000-12-03 13:23 Ivo Timmermans - - * src/tincd.c: Option -d accepts an argument to set the debug level - immediately. - -2000-12-03 13:22 Ivo Timmermans - - * src/conf.c: Sort configuration directives - -2000-12-03 13:21 Ivo Timmermans - - * TODO: Added documentation merger - -2000-12-01 14:46 Ivo Timmermans - - * Makefile.am: Include COPYING.README in the distribution. - -2000-12-01 14:45 Ivo Timmermans - - * COPYING.README: Stated that distributing executables linked with - OpenSSL is permitted provided that all other requirements of the GPL - are complied with. - -2000-12-01 14:45 Ivo Timmermans - - * COPYING.README: file COPYING.README was initially added on branch - CABAL. - -2000-12-01 13:38 Ivo Timmermans - - * src/conf.c: Use buffer instead of line in read_config_file(), - line may be assigned NULL, so buffer always holds the pointer to the - allocated space. - -2000-12-01 13:36 Ivo Timmermans - - * src/conf.c: readline() accepts two extra parameters, buf and - buflen, to avoid mallocing and freeing for every line that is read. - -2000-12-01 00:44 Ivo Timmermans - - * TODO: Tagged `Storing private key in separate file' as done. - -2000-12-01 00:39 Ivo Timmermans - - * doc/tinc.texi: All full stops have two spaces after them. (Silly - commit, I know.) - -2000-12-01 00:18 Ivo Timmermans - - * src/: net.c, net.h, protocol.c: New function - read_rsa_public_key(); In net.c/setup_myself deleted old code to - read the public key (which is now implicitly read in together with - the private key). - -2000-11-30 23:48 Ivo Timmermans - - * src/net.c: Avoid printing duplicate messages from read_rsa_keys - -2000-11-30 23:33 Ivo Timmermans - - * src/net.c: Better error checking when reading the RSA private - key. - -2000-11-30 23:32 Ivo Timmermans - - * src/conf.c: In readline(): initialise the line to zero length; In - read_config_file(): Test for EOF, and print the variable name that - caused an error. - -2000-11-30 22:11 Ivo Timmermans - - * src/conf.c: The file is safe if it doesn't exist. - -2000-11-30 21:08 Ivo Timmermans - - * src/net.c: Read the PEM file pointed to by the configuration - directive PrivateKey. This means thatt he meaning of this variable - has changed, it no longer should contain the private key directly. - - WARNING: This code is untested. - -2000-11-30 01:24 Ivo Timmermans - - * src/conf.c: Implemented is_safe_path, and extended - ask_and_safe_open. - - is_safe_path needs more work before it is useable. - -2000-11-29 16:22 Ivo Timmermans - - * po/nl.po: Updated Dutch translation - -2000-11-29 15:30 Ivo Timmermans - - * src/conf.c: Also free the pointer returned by readline(). - -2000-11-29 15:27 Ivo Timmermans - - * src/conf.c: Use readline() in read_config_file() instead of - fgets. - -2000-11-29 15:24 Ivo Timmermans - - * src/: conf.c, conf.h, tincd.c: Implemented a readline() function - that will read an entire line into a dynamically allocated buffer; - - Ask for a file name in ask_and_safe_open(). - -2000-11-29 15:23 Ivo Timmermans - - * lib/: xalloc.h, xmalloc.c: xstrdup now takes a const pointer as - an argument. - -2000-11-29 02:37 Ivo Timmermans - - * m4/gnuscanf.m4: file gnuscanf.m4 was initially added on branch - CABAL. - -2000-11-29 02:37 Ivo Timmermans - - * acconfig.h, configure.in, system.h, m4/gnuscanf.m4: Added a check - for a scanf that knows about %as. - -2000-11-29 01:33 Ivo Timmermans - - * configure.in, lib/dropin.c, lib/dropin.h: Check for - get_current_dir_name. There is a replacement function in dropin.c. - -2000-11-29 00:23 Ivo Timmermans - - * lib/dropin.c: file dropin.c was initially added on branch CABAL. - -2000-11-29 00:23 Ivo Timmermans - - * lib/: Makefile.am, daemon.c, daemon.h, dropin.c, dropin.h: - dropin.c/h contain a set of drop-in replacements for non-standard C - library functions (read: GNU extensions). - -2000-11-29 00:23 Ivo Timmermans - - * lib/dropin.h: file dropin.h was initially added on branch CABAL. - -2000-11-29 00:12 Ivo Timmermans - - * m4/openssl.m4, src/conf.c, src/tincd.c: Save RSA public and - private keys to a separate file, instead of wanting to copy them - into a configuration file. - -2000-11-28 09:59 Ivo Timmermans - - * src/process.c: Use sigaction to set signal handlers, the previous - commit (1.1.2.16) already contained a large portion of what should - have gone in this one. - -2000-11-27 21:52 Ivo Timmermans - - * TODO: Sort items to either 1.0 or future release goals. - -2000-11-26 23:46 Ivo Timmermans - - * configure.in, system.h: Check for the function strsignal, and - define it to "" if it is not available. - -2000-11-26 23:42 Ivo Timmermans - - * src/process.c: Give an error message if daemon() failed. - -2000-11-26 23:32 Ivo Timmermans - - * po/es.po: Updated Spanish translation, provided by Enrique - Zanardi. - -2000-11-25 14:33 Guus Sliepen - - * acconfig.h, autogen.sh, configure.in, src/net.c, src/process.c, - src/protocol.c: - - Use only one socket for all UDP traffic (for compatibility) - - Write pidfile again after detaching - - Check OS (for handling FreeBSD/Solaris tun/tap stuff) - -2000-11-25 00:30 Guus Sliepen - - * lib/: daemon.c, daemon.h: - - Added daemon() replacement. - -2000-11-25 00:30 Guus Sliepen - - * lib/daemon.c: file daemon.c was initially added on branch CABAL. - -2000-11-25 00:30 Guus Sliepen - - * lib/daemon.h: file daemon.h was initially added on branch CABAL. - -2000-11-25 00:14 Guus Sliepen - - * THANKS: - - Added Armijn to the list - -2000-11-25 00:12 Guus Sliepen - - * configure.in, lib/Makefile.am, lib/rbl.c, lib/rbl.h, - src/connection.c, src/net.c, src/process.c, src/process.h, - src/subnet.c, src/tincd.c: Another big & bad commit: - - Added some extra search functions to rbl routines - - Fix subnet_lookup() - - Reorder some syslog messages to make more sense - - daemon() is back - - Don't let scripts execute in parallel (gives race conditions, and - anyway something MIGHT just be configured which is necessary for - further execution of tinc itself) - - Accidently merged check_child() with execute_script(). - - Small fixes - -2000-11-24 15:13 Ivo Timmermans - - * doc/tinc.texi: Explain how to tell configure where OpenSSL lives. - -2000-11-24 15:13 Ivo Timmermans - - * lib/pidfile.c: Set errno to 0 before trying to kill the other - process. - -2000-11-24 15:12 Ivo Timmermans - - * m4/openssl.m4: Alter CFLAGS, somehow INCLUDES doesn't propagate - properly. Still doesn't work exactly like it should, but getting - there. - -2000-11-24 15:00 Ivo Timmermans - - * cvsusers: file cvsusers was initially added on branch CABAL. - -2000-11-24 15:00 Ivo Timmermans - - * Makefile.am, cvsusers: Use cvs2cl instead of rcs2log to generate - the ChangeLog. - -2000-11-24 14:33 Ivo Timmermans - - * Makefile.am: Do not attempt to retreive ChangeLog information - only from the CABAL tag, it doesn't work anyway. - -2000-11-24 14:32 Ivo Timmermans - - * configure.in: Do not check for the daemon() system call - -2000-11-24 13:44 Ivo Timmermans - - * src/process.c: Do not use the C library's daemon() call. - -2000-11-23 10:30 Guus Sliepen - - * autogen.sh, configure.in: - - Don't link with -ldl anymore - - Let's not use bash' built-in pwd function anymore... it does not - follow symlinks. - -2000-11-23 00:09 Guus Sliepen - - * lib/list.c: - - #include instead of - -2000-11-22 23:18 Guus Sliepen - - * lib/list.c, src/connection.c, src/connection.h, src/process.c, - src/process.h: - - Fixed all (except 2) compiler warnings gcc -Wall gave. - -2000-11-22 23:05 Guus Sliepen - - * configure.in, lib/list.c, src/process.c, src/protocol.c: - - More porting to FreeBSD and Solaris. - -2000-11-22 21:25 Guus Sliepen - - * src/protocol.c: - - Work with the correct key buffer in ans_key_h - -2000-11-22 20:55 Guus Sliepen - - * src/: protocol.c, protocol.h: - - No more %as. - -2000-11-22 20:14 Guus Sliepen - - * lib/rbl.c, src/process.c, src/tincd.c: - - Write pidfile AFTER detaching... - - Minor cleanups - -2000-11-22 19:54 Guus Sliepen - - * lib/rbl.c, src/connection.c, src/netutl.c, src/protocol.c: - - Cleaned up and checked for some more NULL pointers in rbl.c - - Two connection lists: one for incoming connections, sorted on - ip/port, one for connections whose identity we know, sorted on id - ofcourse... - -2000-11-22 18:49 Ivo Timmermans - - * src/process.c: Declare fd. - -2000-11-22 18:48 Ivo Timmermans - - * src/process.c: Add more checks to ensure that filedescriptors are - right in _execute_script(). - -2000-11-22 17:19 Ivo Timmermans - - * src/: Makefile.am, tincd.c: Honor the --localstatedir option to - configure, instead of hardcoded /var. - -2000-11-21 10:13 Guus Sliepen - - * lib/: rbl.c, xalloc.h, xmalloc.c: - - Check for NULL tree->delete callback - - Add xstrdup() function - -2000-11-21 00:29 Guus Sliepen - - * src/: net.c, process.c: - - More fixes. - -2000-11-20 23:13 Guus Sliepen - - * lib/list.c, src/connection.c, src/connection.h, src/net.c, - src/process.c, src/process.h, src/subnet.c, src/tincd.c: - - Various small fixes. - -2000-11-20 20:56 Ivo Timmermans - - * configure.in: Get rid of all libtool references at once. libtool - was only used by libblowfish, which was superseded by openssl. - -2000-11-20 20:41 Guus Sliepen - - * src/: connection.c, net.c, subnet.c, subnet.h: - - Proper initialization of rbltree structures. - -2000-11-20 20:12 Guus Sliepen - - * src/connection.h: file connection.h was initially added on branch - CABAL. - -2000-11-20 20:12 Guus Sliepen - - * src/connection.c: file connection.c was initially added on branch - CABAL. - -2000-11-20 20:12 Guus Sliepen - - * lib/Makefile.am, lib/rbl.c, lib/rbl.h, po/POTFILES.in, - src/Makefile.am, src/conf.c, src/connection.c, src/connection.h, - src/connlist.c, src/connlist.h, src/meta.c, src/meta.h, src/net.c, - src/net.h, src/process.c, src/protocol.c, src/protocol.h, - src/route.c, src/subnet.c, src/subnet.h: - - Integrate rbl trees into tinc. - -2000-11-20 19:06 Ivo Timmermans - - * src/tincd.c: Also include process.h - -2000-11-20 19:05 Ivo Timmermans - - * configure.in: More function and header checks - -2000-11-20 19:02 Ivo Timmermans - - * NEWS: Added this release - -2000-11-19 23:12 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Small fixes - -2000-11-19 12:05 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Deletion also works now. - -2000-11-19 03:04 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Fixed a lot of small things. Tested everything except deletions. - -2000-11-19 00:22 Guus Sliepen - - * lib/rbl.c: - - Fix tree head/tail upon insertion - -2000-11-19 00:21 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Implemented deletions - - Added rbl_foreach() function - -2000-11-18 19:14 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Fixed searching - - Insertion implemented - -2000-11-17 11:03 Guus Sliepen - - * src/: Makefile.am, process.c: - - Removed stray @INCLUDE@ (how did that get there?) - - Use 0 instead of FALSE - -2000-11-17 01:56 Guus Sliepen - - * src/process.c: - - Simplified do_detach - -2000-11-16 23:13 Ivo Timmermans - - * lib/: list.c, list.h, xalloc.h: Use proper prototypes. - -2000-11-16 23:12 Ivo Timmermans - - * src/: process.c, process.h, tincd.c: Move more functions from - tincd.c into process.c. - -2000-11-16 23:11 Ivo Timmermans - - * src/net.c: Delete struct ifr - -2000-11-16 19:06 Ivo Timmermans - - * lib/xmalloc.c: New function: xmalloc_and_zero, which initialises - the allocated memory to all zeroes. - -2000-11-16 18:54 Ivo Timmermans - - * src/process.c: file process.c was initially added on branch - CABAL. - -2000-11-16 18:54 Ivo Timmermans - - * src/process.h: file process.h was initially added on branch - CABAL. - -2000-11-16 18:54 Ivo Timmermans - - * src/: Makefile.am, net.c, process.c, process.h, tincd.c: Move all - process-related functions into process.c. - -2000-11-16 10:18 Guus Sliepen - - * lib/rbl.c: file rbl.c was initially added on branch CABAL. - -2000-11-16 10:18 Guus Sliepen - - * lib/rbl.h: file rbl.h was initially added on branch CABAL. - -2000-11-16 10:18 Guus Sliepen - - * lib/: rbl.c, rbl.h: - - Added balanced tree management stuff as well. (It is not finished - yet.) - -2000-11-15 23:07 Ivo Timmermans - - * src/net.c: Keep a list of running children, and in each loop in - main_loop(), check if one has exited. - -2000-11-15 23:04 Ivo Timmermans - - * lib/: Makefile.am, list.c, list.h: List management and - manipulation routines. - -2000-11-15 14:33 Guus Sliepen - - * src/: Makefile.am, meta.c, net.c, protocol.c: Porting to FreeBSD: - - Reorganized and added some #includes - -2000-11-15 02:28 Ivo Timmermans - - * src/net.c: Let the output from an executed script in - execute_script() go to syslog, with proper error detection. - -2000-11-15 02:06 Ivo Timmermans - - * src/: connlist.h, meta.c, net.c, protocol.c, tincd.c: Use the - HAVE_OPENSSL_xxx_H defined from m4/openssl.m4 during configure. - -2000-11-15 02:02 Ivo Timmermans - - * m4/openssl.m4: Also check for sha.h. - -2000-11-15 01:57 Ivo Timmermans - - * m4/openssl.m4: Also check for rand.h and err.h. If any of these - files does not exist, try the next alternative path. - -2000-11-15 00:18 Ivo Timmermans - - * m4/tuntap.m4: Get rid of the annoying empty line - -2000-11-15 00:02 Ivo Timmermans - - * m4/openssl.m4: Oops, small error. - -2000-11-14 23:57 Ivo Timmermans - - * m4/openssl.m4: Better checks for OpenSSL. I think it can now - detect almost all conceivable installations. - -2000-11-13 23:29 Ivo Timmermans - - * configure.in: Identify version as 1.0pre4-cvs - -2000-11-13 23:01 Ivo Timmermans - - * m4/openssl.m4: file openssl.m4 was initially added on branch - CABAL. - -2000-11-13 23:01 Ivo Timmermans - - * configure.in, m4/openssl.m4: Add a check for openssl that accepts - explicit file locations. - -2000-11-09 22:33 Ivo Timmermans - - * src/netutl.h: Add prototype for destroy_queue - -2000-11-09 22:29 Ivo Timmermans - - * doc/tinc.texi: Updates, updates - -2000-11-09 21:42 Ivo Timmermans - - * README: Wrapped text to 70 (72?) columns for easy reading - -2000-11-09 21:41 Ivo Timmermans - - * NEWS: Final release notes added, also edited release notes for - 1.0pre2 to what the announcement on the mailing list looked like. - -2000-11-08 21:52 Guus Sliepen - - * acconfig.h, configure.in, lib/utils.c, lib/utils.h, src/tincd.c: - - Make checkpoint tracing a compile time option (off by default) - -2000-11-08 19:05 Guus Sliepen - - * THANKS: - - Add Jamie :) - -2000-11-08 18:56 Guus Sliepen - - * src/net.c: - - Applied Jamie Brigg's patch (close sockets after error) - -2000-11-08 01:20 Guus Sliepen - - * src/tincd.c: - - Fixed --config - - Show warning when both netname and config directory are given. - -2000-11-08 01:10 Guus Sliepen - - * configure.in, lib/utils.c, src/net.c, src/tincd.c: Porting to - SunOS 5.8: - - More #includes Linux doesn't seem to need - - Don't do unsetenv() on SunOS - - Use a replacement asprintf() in case the OS doesn't support it It - now compiles properly under SunOS. - -2000-11-07 23:33 Guus Sliepen - - * configure.in, lib/pidfile.c: Porting to SunOS 5.8: - - Include all header files necessary - - Check for flock() function - -2000-11-07 23:02 Guus Sliepen - - * src/protocol.c: - - Open UDP connection for all known hosts. Comments please. - -2000-11-07 22:43 Guus Sliepen - - * src/net.c: Changed execution of tinc-up: - - Do not free() strings that have been putenv()d, see man page of - the latter. - - Do not set IFNAME anymore, it appears that the ioctl to get the - name of the interface does not work at all. Since it is set to - NETNAME in case of tun/tap and it is known beforehand in case of - ethertap, there is no need for it anyway... (though it would've - simplified things). - -2000-11-04 23:57 Guus Sliepen - - * src/: conf.c, conf.h, connlist.c, net.c, net.h, netutl.c, - protocol.c, route.c, subnet.c: - - Prepended config_ to all configuration option names, because it - confused everything (including myself). - - Use connection oriented UDP sockets for both incoming and outgoing - packets. - -2000-11-04 21:44 Guus Sliepen - - * src/: connlist.h, meta.c, net.c, protocol.c: - - Simplified ping mechanism. - -2000-11-04 18:09 Guus Sliepen - - * src/net.c: - - Check for packets that are looping back. - -2000-11-04 18:04 Ivo Timmermans - - * po/nl.po: Updated Dutch translation - -2000-11-04 18:01 Ivo Timmermans - - * po/POTFILES.in: Add route.c to the list of source files. - -2000-11-04 17:54 Guus Sliepen - - * src/protocol.c: - - Forward keys in hex notation, not as binary data. - -2000-11-04 17:39 Guus Sliepen - - * src/protocol.c: - - Don't forget to set packet cipher for added hosts. - -2000-11-04 16:34 Guus Sliepen - - * po/POTFILES.in, po/es.po, po/nl.po, src/connlist.c: - - connlist.c added to translation - -2000-11-04 16:32 Ivo Timmermans - - * src/net.c: In execute_script: - - add an environment variable NETNAME. - - chdir to the configuration directory before execing the script. - -2000-11-04 16:17 Guus Sliepen - - * doc/: Makefile.am, genauth.8: - - Removed manpage for no longer existing genauth. - -2000-11-04 15:52 Guus Sliepen - - * src/net.c: - - Resolve scriptname after fork() - -2000-11-04 15:16 Ivo Timmermans - - * src/net.c: Use putenv() instead of clumsy do-it-yourself in - execute_script. - -2000-11-04 14:25 Ivo Timmermans - - * src/net.c: Small change to the way the environment is copied. - -2000-11-04 12:49 Guus Sliepen - - * src/: connlist.c, connlist.h, net.c, netutl.h, subnet.c: - - Removed even more warnings. - -2000-11-04 11:37 Guus Sliepen - - * src/net.c: - - Removed unused MAC strip/add functions. - -2000-11-03 23:35 Ivo Timmermans - - * src/: conf.c, connlist.c, connlist.h, protocol.c, protocol.h, - subnet.c: Warnings removal pass: always include config.h first; add - a few prototypes in the header files. - - This also fixes a few lint errors/warnings. - -2000-11-03 23:33 Ivo Timmermans - - * src/net.c: Run the scripts tinc-up and tinc-down from a separate - function, which sets the environment as it should be and checks for - errors. - -2000-11-03 23:31 Ivo Timmermans - - * src/tincd.c: Save the environment on startup. - -2000-11-02 23:05 Ivo Timmermans - - * src/net.c, po/nl.po: Changed a few messages wrt. system calls; - updated and changed the Dutch translation a bit. - -2000-11-02 22:43 Ivo Timmermans - - * AUTHORS: Mention fileutils, add a pointer to THANKS for more - details - -2000-11-02 22:41 Ivo Timmermans - - * Makefile.am: Change wsl to Wessel's name and email address in the - ChangeLog creation - -2000-11-02 22:40 Ivo Timmermans - - * NEWS: More exhaustive list of changes - perhaps it can be worded - differently? - -2000-11-02 22:39 Ivo Timmermans - - * THANKS: Changed `I' to `We' - small change, lots of difference :) - -2000-11-02 22:38 Ivo Timmermans - - * configure.in: Only check for linux/if_tun.h once - -2000-11-02 22:34 Ivo Timmermans - - * doc/tinc.texi: Added a perl example to turn an IP address into a - MAC address. - -2000-11-02 22:26 Ivo Timmermans - - * src/Makefile.am: Do not include $(top_srcdir)/cipher, it does no - longer exist. - -2000-10-31 17:10 Guus Sliepen - - * NEWS, README, TODO: - - Update. - -2000-10-30 11:19 Guus Sliepen - - * doc/tinc.conf.5, doc/tincd.8, src/tincd.c: - - Fixed some spelling mistakes and terminology here and there. - -2000-10-30 01:22 Guus Sliepen - - * doc/tinc.conf.5, doc/tincd.8, po/es.po, po/nl.po, src/net.c, - src/tincd.c: - - Small cleanups - - Updated dutch translation - - Updated man pages - -2000-10-29 23:55 Guus Sliepen - - * src/: connlist.h, meta.c, protocol.c, protocol.h, tincd.c: - - Finishing touch: encrypt the meta connections - -2000-10-29 23:10 Guus Sliepen - - * src/: connlist.h, net.c, protocol.c, tincd.c: - - Use CFB mode for encrypting packets: it works and we don't need - padding. - -2000-10-29 11:39 Guus Sliepen - - * src/: net.c, protocol.c: - - Small fixes - - Do proper key exchange - - Encrypt packets - it works, but there is something wrong with the - MAC header after decryption... - -2000-10-29 10:19 Guus Sliepen - - * src/: encr.c, encr.h, net.c, net.h, netutl.c, protocol.c, - tincd.c: - - Removed old encr stuff - -2000-10-29 03:07 Guus Sliepen - - * po/es.po, po/nl.po, src/connlist.c, src/net.c, src/tincd.c: - - Updated dutch translation. - - Shutdown properly. - -2000-10-29 02:27 Guus Sliepen - - * src/: connlist.h, net.h: - - Moved connlist stuff to the proper header file. - -2000-10-29 02:08 Guus Sliepen - - * src/protocol.c: - - Enforce correct order of authentication requests - -2000-10-29 02:46 Guus Sliepen - - * src/net.c: - - Hit people who can't figure out subnet address/mask pairs with a - (clue)bat. - -2000-10-29 02:24 Guus Sliepen - - * src/: conf.c, conf.h, protocol.c: - - Fixed ans_key_h - - Removed tapsubnet configuration option. - -2000-10-29 02:02 Guus Sliepen - - * src/: conf.c, connlist.c, connlist.h, meta.c, net.c, protocol.c, - subnet.c, tincd.c: - - Very big cleanup. - -2000-10-28 23:52 Guus Sliepen - - * src/net.c: - - Override destination ethernet address on incoming packets with - FE:FD:00:00:00:00 - -2000-10-28 23:25 Guus Sliepen - - * src/: net.c, net.h: - - Fixed offsets when reading/writing from/to tap device - -2000-10-28 23:05 Guus Sliepen - - * lib/utils.c, lib/utils.h, src/net.c, src/protocol.c, - src/protocol.h, src/subnet.c, src/subnet.h, src/tincd.c: - - Lots of small fixes - - Exchange subnets on acknowledgement of connection - - Do proper lookup when incoming packets from tap - - off-by-a small number-error when reading/sending tap packets - -2000-10-28 21:34 Ivo Timmermans - - * m4/tuntap.m4: Skip the check for Linux kernel sources - -2000-10-28 18:41 Guus Sliepen - - * src/: connlist.c, connlist.h, net.c, subnet.c, subnet.h: - - Updated subnet list handling. Subnets are added to two lists now, - the owner's list and a global list. It is all fucked up but it - probably works anyway, good enough for pre3 :). - -2000-10-24 17:46 Guus Sliepen - - * src/: conf.c, conf.h, connlist.c, meta.c, net.c, netutl.c, - protocol.c, subnet.c: - - Lots of little stuff modified - - Succesfully reads in subnets from host config file now and adds - them to the list. - -2000-10-23 23:56 Ivo Timmermans - - * configure.in: Oops, echelon change committed to cabal... :) - -2000-10-23 15:52 Guus Sliepen - - * src/route.c: file route.c was initially added on branch CABAL. - -2000-10-23 15:52 Guus Sliepen - - * src/route.c: - - route.c will contain the routing logic. - -2000-10-22 15:47 Ivo Timmermans - - * src/conf.c: read_server_config: Check for result of - read_config_file. - -2000-10-22 15:37 Ivo Timmermans - - * src/net.c: Include linux/sockios.h and net/if.h anyway, - regardless of the value of HAVE_TUNTAP. - -2000-10-21 13:52 Guus Sliepen - - * lib/utils.h, src/meta.c, src/net.c, src/protocol.c, src/tincd.c: - - Fixed all debug levels. - - Seed PRNG before generating a challenge - - Strange thing in challenge decryption: it fails if first bit is - set!? - -2000-10-20 21:46 Guus Sliepen - - * src/: Makefile.am, net.c, tincd.c: - - Removed last reference to genauth from Makefile.am - - Tinc spawns tinc-up and tinc-down scripts which can be used to - configure the network device. The environment variable IFNAME is set - to the name of the interface. - -2000-10-20 18:49 Guus Sliepen - - * doc/es/Makefile.am: file Makefile.am was initially added on - branch CABAL. - -2000-10-20 18:49 Guus Sliepen - - * doc/es/Makefile.am, po/POTFILES.in, po/es.po, po/nl.po, - src/Makefile.am, src/genauth.c, src/tincd.c: - - Made Makefile.am stub for doc/es/ - - Merged genauth into tincd - - Updated dutch translation - -2000-10-20 18:44 Ivo Timmermans - - * lib/: hash.c, hash.h, list.c, list.h: Generalized list and hash - handling functions - -2000-10-20 18:43 Ivo Timmermans - - * lib/: xmalloc.c, xalloc.h: New function: xalloc_and_zero() - -2000-10-20 18:42 Ivo Timmermans - - * lib/Makefile.am: Add all the new files to the sources list for - the utility library - -2000-10-20 17:34 Guus Sliepen - - * src/: connlist.c, connlist.h, genauth.c, net.c, protocol.c, - protocol.h: - - tinc now really does public/private key encryption! It even works, - whee! - -2000-10-19 22:56 Ivo Timmermans - - * lib/: error.c, error.h: Generalized error handling functions - -2000-10-19 22:39 Ivo Timmermans - - * configure.in: Add check for the syslog function - -2000-10-19 16:42 Guus Sliepen - - * src/genauth.c: - - Seed the PRNG using /dev/random before generating the keys. - -2000-10-18 22:12 Ivo Timmermans - - * AUTHORS, Makefile.am, README, THANKS, TODO, acconfig.h, - configure.in, doc/Makefile.am, doc/tinc.conf.5, doc/tinc.texi, - lib/Makefile.am, lib/utils.c, lib/utils.h, lib/xalloc.h, - lib/xmalloc.c, po/POTFILES.in, po/nl.po, redhat/tinc.spec, - src/Makefile.am, src/conf.c, src/conf.h, src/encr.c, src/encr.h, - src/genauth.c, src/net.c, src/net.h, src/netutl.c, src/netutl.h, - src/protocol.c, src/protocol.h, src/tincd.c: Bring head revision up - to date with cabal (try #3) - -2000-10-18 21:44 Ivo Timmermans - - * THANKS, configure.in: Get the head revision up to date with cabal - -2000-10-17 12:15 Ivo Timmermans - - * lib/xmalloc.c: Don't declare cp_file and cp_line in xmalloc() - -2000-10-17 12:14 Ivo Timmermans - - * doc/Makefile.am: Process subdir es/ - -2000-10-16 21:04 Guus Sliepen - - * src/: connlist.c, net.c, protocol.c: - - More fixing. Tinc daemons can now even create activated - connections. - -2000-10-16 18:33 Guus Sliepen - - * lib/utils.c, src/conf.c, src/connlist.c, src/net.c, - src/protocol.c: - - Fixing little things - - Two tinc daemons can connect to eachother now (but they disconnect - right after the ACKs). - -2000-10-16 13:35 Ivo Timmermans - - * configure.in: Output doc/es/Makefile - -2000-10-15 22:30 Guus Sliepen - - * src/net.c: Corrected #ifdefs for tun/tap support. - -2000-10-15 22:21 Ivo Timmermans - - * m4/tuntap.m4: Really #include the if_tun.h files now - -2000-10-15 22:13 Ivo Timmermans - - * m4/tuntap.m4: Linearized checks for if_tun.h - -2000-10-15 21:53 Ivo Timmermans - - * src/net.c: Wrap the tun/tap code in #ifdef HAVE_TUNTAP - -2000-10-15 19:26 Ivo Timmermans - - * m4/tuntap.m4: file tuntap.m4 was initially added on branch CABAL. - -2000-10-15 19:26 Ivo Timmermans - - * acconfig.h, configure.in, m4/tuntap.m4: Add checks for the - presence of the universal tun/tap device driver. - -2000-10-15 02:59 Guus Sliepen - - * lib/utils.c, lib/utils.h, po/POTFILES.in, po/es.po, po/nl.po, - src/conf.c, src/conf.h, src/connlist.c, src/genauth.c, src/meta.c, - src/net.c, src/net.h, src/protocol.c, src/protocol.h, src/subnet.c, - src/tincd.c: - - The daemon actually runs now (somewhat) - - Added support for tun/tap driver (autodetect!) - - More sophisticated checkpoint functionality - - Updated dutch translation - -2000-10-15 00:22 Ivo Timmermans - - * doc/tinc.texi: Add CVS id lines - -2000-10-15 00:17 Ivo Timmermans - - * doc/tinc.texi: Fix `Requirements'-section for GMP and OpenSSL - libraries. - -2000-10-14 19:04 Guus Sliepen - - * lib/utils.c, lib/utils.h, src/conf.c, src/conf.h, src/connlist.c, - src/connlist.h, src/net.c, src/net.h, src/protocol.c, src/tincd.c: - - Second fixing-things pass: it even links now. - - Lots of FIXME comments added to the source code. - -2000-10-14 01:34 Ivo Timmermans - - * configure.in: Don't look for GMP header files - -2000-10-14 01:30 Ivo Timmermans - - * README: Updated new requirements, pointers to the manual - -2000-10-14 01:29 Ivo Timmermans - - * configure.in: Link with OpenSSL, forget libGMP - -2000-10-12 00:00 Guus Sliepen - - * lib/xalloc.h, src/conf.c, src/conf.h, src/connlist.c, - src/connlist.h, src/meta.c, src/net.c, src/net.h, src/netutl.c, - src/netutl.h, src/protocol.c, src/protocol.h, src/subnet.c, - src/subnet.h, src/tincd.c: - - Fixing-things pass: every source file compiles into an object file - now, but linking tincd does not work yet (must link with openssl - libs and define some missing functions). - -2000-10-11 15:42 Guus Sliepen - - * src/: conf.c, conf.h, protocol.c: - - Generalized config file parsing to support multiple configuration - trees. - -2000-10-11 14:07 Guus Sliepen - - * src/genauth.c: - - Changed genauth to produce rsa keypairs instead of random - passphrases. - -2000-10-11 12:35 Guus Sliepen - - * src/connlist.h: file connlist.h was initially added on branch - CABAL. - -2000-10-11 12:35 Guus Sliepen - - * src/connlist.c: file connlist.c was initially added on branch - CABAL. - -2000-10-11 12:35 Guus Sliepen - - * AUTHORS, Makefile.am, configure.in, src/Makefile.am, - src/connlist.c, src/connlist.h, src/encr.h, src/meta.c, src/meta.h, - src/net.c, src/net.h, src/netutl.c, src/netutl.h, src/protocol.h, - src/subnet.c, src/subnet.h: Big and bad commit of my current - tree... - - Added seperate file for connection list handling - - Updating everything to use connlist, meta and subnet files - - Removed dependency on libgmp - - Lots of other stuff... - -2000-10-01 05:21 Guus Sliepen - - * src/subnet.c: file subnet.c was initially added on branch CABAL. - -2000-10-01 05:21 Guus Sliepen - - * src/: meta.h, net.h, subnet.c, subnet.h: - - Added subnet handling code - - Other small changes to header files - -2000-10-01 05:21 Guus Sliepen - - * src/subnet.h: file subnet.h was initially added on branch CABAL. - -2000-09-27 22:32 Ivo Timmermans - - * doc/tinc.texi: Many updates, parts rewritten, added, shuffled - around. - -2000-09-26 16:06 Guus Sliepen - - * src/meta.h: file meta.h was initially added on branch CABAL. - -2000-09-26 16:06 Guus Sliepen - - * src/meta.c: file meta.c was initially added on branch CABAL. - -2000-09-26 16:06 Guus Sliepen - - * src/: meta.c, meta.h, net.c, protocol.c, protocol.h: - - Added meta.c which contains functions to send, receive and - broadcast metadata. It will also handle encryption and decryption, - and possibly compression and checksumming. - - Moved request dispatcher to protocol.c. - -2000-09-25 22:08 Guus Sliepen - - * doc/SECURITY: - - Very detailed example of the authentication phase. - -2000-09-22 18:20 Guus Sliepen - - * src/: net.c, protocol.c: - - Removed options "string" stuff. It was a bad idea... - - free() everything that is allocated. - -2000-09-22 17:06 Guus Sliepen - - * src/protocol.c: - - Severe code reduction and simplification of challenge requests - - "Finished" [add|del]_subnet_h - - Added lots of sanity checks to [add|del]_host_h - -2000-09-17 23:42 Guus Sliepen - - * src/protocol.c: - - Updated authentication scheme. - - Removed all trailing spaces from all lines. - - Added things to add_ and del_subnet_h. - -2000-09-17 22:11 Guus Sliepen - - * doc/SECURITY: - - Included authentication scheme from protocol.c - - Added a few comments about the symmetric cipher. - -2000-09-17 21:57 Guus Sliepen - - * doc/SECURITY: Added document about the used cryptographic - algorithms and the reasons behind them. Feel very free to comment on - this! - -2000-09-17 21:57 Guus Sliepen - - * doc/SECURITY: file SECURITY was initially added on branch CABAL. - -2000-09-17 12:28 Ivo Timmermans - - * doc/es/: tinc-es.html, tinc_toc-es.html: Added Spanish - translation of the docs by Matias Carrasco - -2000-09-17 12:28 Ivo Timmermans - - * doc/es/tinc_toc-es.html: file tinc_toc-es.html was initially - added on branch CABAL. - -2000-09-17 12:28 Ivo Timmermans - - * doc/es/tinc-es.html: file tinc-es.html was initially added on - branch CABAL. - -2000-09-15 14:58 Ivo Timmermans - - * src/: encr.c, net.c, net.h, netutl.c, protocol.c: Second round of - fixes - -2000-09-14 23:51 Ivo Timmermans - - * src/: net.c, net.h, netutl.c, protocol.c: First round of needed - fixes after the overhaul - -2000-09-14 16:34 Ivo Timmermans - - * src/: conf.c, conf.h: New directive: Name. - -2000-09-14 16:32 Ivo Timmermans - - * lib/utils.h, src/net.h: Added some structures and types that are - needed for the overhaul. - -2000-09-14 13:54 Guus Sliepen - - * src/: net.c, protocol.c: - - Lots of small changes. - -2000-09-11 13:40 Ivo Timmermans - - * configure.in: Better checks for SunOS libraries - -2000-09-11 12:05 Guus Sliepen - - * src/: protocol.c, protocol.h: - - Fixed modulo in keylength check - - Updated header file to reflect new protocol code - -2000-09-11 01:11 Guus Sliepen - - * src/protocol.c: - - Some key exchange stuff. (Last commit before going to bed.) - -2000-09-11 00:49 Guus Sliepen - - * src/protocol.c: - - Lots of functions added for the new protocol. - -2000-09-10 23:57 Ivo Timmermans - - * src/protocol.h: Add Guus' name and shift out old protocol - requests - -2000-09-10 20:37 Ivo Timmermans - - * doc/tinc.texi: Correct filenames for passphrases given in the - example - -2000-09-10 18:15 Guus Sliepen - - * src/protocol.c: - - Added more function skeletons for the new protocol. - -2000-09-10 17:18 Guus Sliepen - - * src/protocol.c: - - New protocol. Will break everything else for now. - -2000-09-10 17:16 Ivo Timmermans - - * configure.in: Support for -lsocket and -lnsl on SunOS - -2000-09-10 17:07 Ivo Timmermans - - * doc/PROTOCOL: Updated text, removed protocol flowchart - -2000-09-10 17:05 Ivo Timmermans - - * configure.in: Link with OpenSSL crypto libraries instead of own - blowfish library - -2000-09-06 13:49 Guus Sliepen - - * src/: conf.c, net.c, netutl.c, tincd.c: - - Use strerror() instead of sys_errlist[] for increased portability - (Needed for SunOS) - -2000-08-27 13:05 Ivo Timmermans - - * Makefile.am: Changed CVSROOT path in `make ChangeLog' - -2000-08-21 22:35 Ivo Timmermans - - * Makefile.am: Added a rule to create an rpm - -2000-08-21 14:50 Guus Sliepen - - * doc/tinc.conf.5: Updated tinc.conf manual. - -2000-08-18 16:45 Guus Sliepen - - * doc/tinc.texi: Updated the manual: - - incorporated comments from Stefan Hartsuiker - - updated configuration variables section - - added some text about key types - -2000-08-18 13:17 Guus Sliepen - - * src/encr.c: Commented on some size calculations. - -2000-08-17 19:22 Guus Sliepen - - * po/: es.po, nl.po: Ran update-po and updated dutch translation. - -2000-08-17 18:51 Guus Sliepen - - * src/: encr.c, netutl.c, tincd.c: Fixed all sprintf() spl01ts. - -2000-08-09 16:02 Guus Sliepen - - * src/: conf.c, conf.h, net.c: - - Added two extra configuration options, Interface and InterfaceIP, - to bind the listen socket to a network device or a specific IP. - -2000-08-09 11:34 Guus Sliepen - - * src/net.c: - - Reinstated O_NONBLOCK for meta socket - - Set SO_KEEPALIVE on meta socket - -2000-08-08 19:07 Guus Sliepen - - * src/: net.c, net.h, protocol.c: - - Moved TCP packet reception to meta handler: less kludgy and less - buggy! - -2000-08-08 16:54 Guus Sliepen - - * src/tincd.c: - - Added date/time of build and protocol number to --version output. - -2000-08-08 15:47 Guus Sliepen - - * src/: net.c, protocol.c: Removed calling add_queue for tcponly - packets. - -2000-08-08 10:48 Guus Sliepen - - * src/protocol.c: Fixed PACKET read loop. - -2000-08-07 18:27 Guus Sliepen - - * src/: conf.h, net.c, net.h, protocol.c, protocol.h: - - Lots o' buglets fixed (-Wall helps) - - Made TCPonly work :) - -2000-08-07 16:52 Guus Sliepen - - * src/: conf.c, conf.h, net.c, net.h, protocol.c, protocol.h: - - Added experimental hackish tunneling-over-TCP support. - Just use TCPonly = true in the configuration file. - -2000-07-02 15:40 Guus Sliepen - - * src/net.c: - - Fixed typo. - -2000-07-02 15:36 Guus Sliepen - - * src/: conf.c, net.c: - - Delayed address resolving for ConnectTo lines in configuration - file to allow DynDNS to work without restarting tincd. - -2000-07-02 14:48 Guus Sliepen - - * THANKS: - - Updated THANKS file - -2000-07-02 14:41 Ivo Timmermans - - * configure.in: Include the Spanish translation in the - distribution/build process. - -2000-07-02 14:35 Guus Sliepen - - * po/es.po: file es.po was initially added on branch CABAL. - -2000-07-02 14:35 Guus Sliepen - - * po/es.po: - - Added Spanish translation from Enrique Zanardi. - -2000-07-01 16:40 Guus Sliepen - - * doc/tincd.8: - - Forgot to mention ourselves in the tincd manual page! :) - -2000-07-01 16:32 Guus Sliepen - - * doc/: Makefile.am, PROTOCOL, tincd.8, tincd.x: - - Updated PROTOCOL (a bit) - - Included a real tincd.8 describing the options, signals, debug - levels and files used by tincd. - -2000-07-01 16:32 Guus Sliepen - - * doc/tincd.8: file tincd.8 was initially added on branch CABAL. - -2000-07-01 12:39 Ivo Timmermans - - * po/Makefile.in.in: Autogenerated by gettextize. - -2000-07-01 09:49 Guus Sliepen - - * src/net.h: - - Removed a single unused bit from status_bits_t. - -2000-07-01 09:29 Wessel Dankers - - * doc/HOWTO: Added architecture section, made a start with the - kernel section. ToDo: install tinc myself to see if everything is - as I say =) - -2000-07-01 00:38 Guus Sliepen - - * doc/PROTOCOL: file PROTOCOL was initially added on branch CABAL. - -2000-07-01 00:38 Guus Sliepen - - * doc/PROTOCOL: - - Added documentation for the protocols (most important the meta - protocol) used by tinc. - -2000-06-30 23:16 Wessel Dankers - - * doc/HOWTO: Grrr, recommit - -2000-06-30 23:11 Wessel Dankers - - * doc/HOWTO: This file is now only in the CABAL revision. - -2000-06-30 23:09 Wessel Dankers - - * doc/HOWTO: More about keys - -2000-06-30 23:03 Guus Sliepen - - * src/: encr.c, net.c, protocol.c: - - Made tinc even more silent if no -d flag is given at all. - -2000-06-30 22:57 Wessel Dankers - - * doc/HOWTO: Added extra bit about keys. - -2000-06-30 22:50 Wessel Dankers - - * doc/HOWTO: File added to CABAL (hopefully) - -2000-06-30 22:42 Wessel Dankers - - * doc/HOWTO: added bit on config file, split up sections, added Id: - tag - -2000-06-30 22:16 Wessel Dankers - - * doc/HOWTO: Initial revision. Lots of loose ends, not usable yet. - -2000-06-30 14:41 Guus Sliepen - - * po/nl.po, src/net.c, src/protocol.c: - - Instead of logging an error when remote end closes the connection, - we print a nice message if appropiate debug level is set. - - If we get ADD_HOSTs or DEL_HOSTs for ourself, then connection - lists are really messed up. We restart, and hope our problems go - away. - -2000-06-30 13:45 Guus Sliepen - - * po/nl.po, src/conf.c, src/conf.h, src/net.c, src/tincd.c: - - Removed segfault bug in conf.c (must have been there for ages!) - - Made main_loop() signal proof - - #defined MAXTIMEOUT (15 minutes) - - If something really really bad happens, close all connections, - wait for MAXTIMEOUT seconds, and then restart tinc - -2000-06-29 21:47 Guus Sliepen - - * po/nl.po, src/conf.c, src/conf.h, src/net.c, src/protocol.c, - src/tincd.c: - - Fixed memory leak. - - Implemented SIGHUP configuration file reloading. - - Other small changes. - -2000-06-29 19:09 Guus Sliepen - - * po/nl.po, src/net.c, src/netutl.c, src/protocol.c, - src/protocol.h, src/tincd.c: - - New semantics for BASIC_INFO, ADD_HOST and DEL_HOST requests. This - will improve connection list consistency, ensures the tree property, - and allows for recovery from situations where track of connections - is lost. - -2000-06-29 15:04 Guus Sliepen - - * po/nl.po, src/net.c, src/net.h, src/netutl.c, src/protocol.c: - - Removed all IP_ADDR_S macros, because gettext doesn't like them. - Each connection now has two hostnames: real_hostname (replacing the - old), and vpn_hostname. In those places where hostnames really - aren't usefull IP_ADDR_S has been replaced by %d.%d.%d.%d. - -2000-06-29 09:11 Guus Sliepen - - * po/nl.po: - - Updated Dutch translation. - -2000-06-28 23:06 Ivo Timmermans - - * po/nl.po: Oops, and mention Guus too. - -2000-06-28 23:01 Ivo Timmermans - - * po/nl.po: Removed Free Software Foundation copyright, because - Guus Sliepen contributed significantly. - -2000-06-28 16:34 Guus Sliepen - - * po/nl.po, src/tincd.c: - - Added log message when SIGCHLD is received ("thanks" to Ivo van - Dong) - -2000-06-28 15:41 Guus Sliepen - - * po/nl.po, src/protocol.c: - - Fixed a message in nl.po - - Woops, we forgot to send our connection list to our uplink when we - connect to it... Fixed. - -2000-06-28 13:39 Guus Sliepen - - * po/nl.po: - - Fixed missing " in nl.po - -2000-06-28 13:38 Guus Sliepen - - * po/nl.po, src/protocol.c, src/tincd.c: - - Fixed some spelling errors. - - Paar zpelvautjes gerepareerd, en de Nederlandse vertaling weer bij - de tijd gebracht. - -2000-06-28 12:11 Guus Sliepen - - * src/net.c: - - Extra check op EINTR bij inlezen requests - -2000-06-27 23:05 Guus Sliepen - - * src/net.c: - - Fixes a silly little insignificant buglet. - -2000-06-27 22:55 Guus Sliepen - - * src/protocol.c: - - Purge old connections that are ADD_HOSTed. - -2000-06-27 22:10 Guus Sliepen - - * src/: conf.c, conf.h, net.c, protocol.c: - - Improved handling of errors on connection attempts. - -2000-06-27 17:08 Guus Sliepen - - * src/: conf.c, conf.h, net.c: - - Fixed indirectdata=no problem - - Added support for multiple ConnectTo lines in tinc.conf. - -2000-06-27 14:58 Guus Sliepen - - * src/protocol.c: - - Fixed KEY_CHANGED notification. A lot of notify_others() calls - were wrong (first two arguments swapped). Should probably be - doublechecked. - - Don't retry to connect to hosts with different protocol versions. - -2000-06-26 22:30 Guus Sliepen - - * src/: net.c, protocol.c: - - Moved all connection messages to debug level 1, without -d's only - the startup message will be logged. - - Fixed DEL_HOST rebound. - -2000-06-26 21:39 Guus Sliepen - - * src/: net.c, netutl.c, protocol.c: - - Indirectdata finally REALLY REALLY works now! - - More precise debug messages - -2000-06-26 19:20 Guus Sliepen - - * src/: net.c, protocol.c: Fixes some hostlookups. Fixes - indirectdata for real now (hopefully). - -2000-06-25 22:52 Ivo Timmermans - - * configure.in: Version 1.0pre3. - -2000-06-25 18:39 Guus Sliepen - - * src/: netutl.c, protocol.c: - - More verbose connection list - - Added "myself" as hostname when logging indirect ADD_HOSTs - -2000-06-25 18:20 Guus Sliepen - - * src/: net.c, protocol.c: Hostlookup() is actually being called - now. - -2000-06-25 18:01 Guus Sliepen - - * src/: net.c, net.h, netutl.c, protocol.c: Hostnames are back! - -2000-06-25 17:45 Guus Sliepen - - * src/protocol.c: - - Log possible spoofing attacks. - - Don't broadcast DEL_HOSTs for hosts that haven't been activated - yet. - - If a host sends a TERMREQ, deactivate them. - -2000-06-25 17:42 Ivo Timmermans - - * configure.in, redhat/tinc.spec: Changed version number to - 1.0pre3. - -2000-06-25 17:22 Guus Sliepen - - * src/: encr.h, net.h, netutl.h, protocol.h: Added CVS Id tags to - header files. - -2000-06-25 17:16 Guus Sliepen - - * src/: encr.c, net.c, net.h, netutl.c, protocol.c, tincd.c: Large - cleanup: - - Removed hostname lookup (it blocks, and you can always do it - yourself) - - Reorganized debug levels (after hints from Axel Müller): - 0 Startup message and errors - 1 Connection logging - 2 Meta protocol information - 3 Verbose meta protocol (includes copy of transmitted requests) - 4 Packet information (logs transmission/errors of UDP packets) - 5 Verbose packet information (every single byte, not implemented - yet to protect ourselves from filling up /var/log directories) - - Made log messages more consistent - -2000-06-24 14:35 Guus Sliepen - - * src/net.c: If we have "indirectdata" flag set, we only send data - to our uplink. - -2000-06-23 21:27 Guus Sliepen - - * TODO, src/net.c, src/net.h, src/protocol.c, src/protocol.h: First - step for implementation of the "indirectdata" directive. This should - allow _leaf_ tincds to be behind firewalls. The protocol has - changed and is INCOMPATIBLE with previous versions. The PROT_CURRENT - value has been incremented. - -2000-06-17 22:55 Ivo Timmermans - - * src/: conf.c, conf.h: Configuration directive `IndirectData'. - -2000-06-17 22:30 Ivo Timmermans - - * redhat/tinc: Merge changes from 1.6-1.8. - -2000-06-17 10:30 Guus Sliepen - - * redhat/tinc: Added another semicolon for bash2 compliance (thanks - to Jamie Briggs) - -2000-06-16 07:44 Guus Sliepen - - * redhat/tinc: Applied patch from Jamie Briggs for bash2 - conformance. - -2000-06-06 12:24 Ivo Timmermans - - * lib/Makefile.am, src/Makefile.am: Include ../intl in the include - path, and add @INTLLIBS@ to the list of libraries. - -2000-06-04 14:14 Ivo Timmermans - - * po/Makefile.in.in: These files are created by gettextize (run by - autogen.sh) (should have known that). - -2000-06-04 13:50 Ivo Timmermans - - * configure.in: Check for __gmpz_powm for libgmp3. - -2000-06-03 10:27 Guus Sliepen - - * TODO: Removed items in TODO list that are already implemented. - Only two items left. - -2000-06-02 19:30 Ivo Timmermans - - * THANKS: Alphabetized the list, added Lubomír Bulej, removed - Sander Smeenk and Tijs van Bakel, put merits after all names. - -2000-05-31 20:23 Ivo Timmermans - - * src/: net.c, encr.c, netutl.c, tincd.c: Miscellaneous copyright - updates. - -2000-05-31 20:21 Ivo Timmermans - - * src/genauth.c: Handle locale settings. - -2000-05-31 20:18 Ivo Timmermans - - * po/nl.po: Updated Dutch translation. - -2000-05-31 20:17 Ivo Timmermans - - * NEWS: Include news for 1.0pre2. - -2000-05-30 23:36 Ivo Timmermans - - * src/protocol.c: Only accept an ADD_HOST request for a host that - already exists in our conn_list if the nexthop field matches the - sender. This is a workaround for older clients. - -2000-05-30 14:38 Ivo Timmermans - - * src/net.c: In terminate_connection, only send a notification to - hosts that are directly connected to us. (DEL_HOST gets forwarded - automatically.) - -2000-05-30 14:31 Ivo Timmermans - - * src/net.c: When a connection is terminated, all hosts that are - still connected get notified of the lost connections. - -2000-05-30 13:18 Ivo Timmermans - - * src/: conf.c, conf.h, netutl.c: Added new configuration directive - `Hostnames', which controls the resolving of IP addresses to - hostnames. - -2000-05-30 01:40 Guus Sliepen - - * src/: net.c, protocol.c: Only activate a connection upon - receiving it's public key if it's an incoming connection. When it's - outgoing, we need to receive an ack first. - -2000-05-30 00:27 Ivo Timmermans - - * NEWS: Updated changes list for version 1.0pre2. - -2000-05-30 00:20 Ivo Timmermans - - * src/net.c: Bounds check for request id (between 0 and 255). - -2000-05-30 00:15 Ivo Timmermans - - * po/nl.po: Dutch translation of tinc. - -2000-05-29 23:40 Ivo Timmermans - - * src/Makefile.am: Define LOCALEDIR in CFLAGS. - -2000-05-29 23:40 Ivo Timmermans - - * configure.in: Include GNU gettext checks. - -2000-05-29 23:38 Ivo Timmermans - - * acconfig.h: Update acconfig.h to include values for gettext - inclusion. - -2000-05-29 23:36 Ivo Timmermans - - * ABOUT-NLS, Makefile.am, system.h: Include system.h and ABOUT-NLS. - -2000-05-29 23:04 Ivo Timmermans - - * Makefile.am: Include intl/ directory in the list of subdirs. - -2000-05-29 23:01 Ivo Timmermans - - * po/Makefile.in.in, po/POTFILES.in, Makefile.am, configure.in, - src/conf.c, src/encr.c, src/genauth.c, src/net.c, src/netutl.c, - src/protocol.c, src/tincd.c: Internationalization of tinc. - -2000-05-27 22:23 Guus Sliepen - - * src/: net.c, protocol.c: Terminate a connection on any error. - Furthermore, disallow del_host, add_host and other important - requests until remote host has properly authenticated itself. - -2000-05-27 21:44 Guus Sliepen - - * src/net.c: Made tinc persistent. If no outgoing connection can be - established right after the start of the daemon, it won't quit - anymore but will retry in 5 minutes. Also, 5 minutes is now the - maximum time to wait for a retry. - -2000-05-27 21:23 Guus Sliepen - - * src/: net.c, netutl.c, protocol.c: Fixed typos. When terminating - a connection, it's status is not only set to remove=1 but also - active=0. - -2000-05-27 21:04 Guus Sliepen - - * src/: net.c, netutl.c, protocol.c: Fix for a DoS attack: - A remote user could telnet to the tinc daemon and type only this - line: 61 6 00000000/00000000:28f - This would deny any packets to be sent to other tinc networks - (except for to the hosts that run tincd's themselves). Solution is - to skip hosts in lookup_conn() that have not been activated yet. - Fixed potential conn_list table corruption: - If a new connection is accepted but a connection with the same - subnet would already exist in the connection list, the OLD - connection is terminated. - -2000-05-27 15:21 Guus Sliepen - - * doc/: tinc.conf.5, tinc.texi: Documentation updates. Removed all - references to configuration variable "AllowConnect", since it is NOT - used in tinc. Added information about "VpnMask". Elaborated a bit - about "private" and "virtual" networks. - -2000-05-26 13:25 Ivo Timmermans - - * redhat/tinc: Updated by Lubomir Bulej and Mads Kiilerich: it uses - /etc/tinc/nets.boot and the VpnMask directive in the config files. - -2000-05-22 00:38 Ivo Timmermans - - * doc/tinc.conf.sample: Add an example of using VpnMask. - -2000-05-19 02:33 Ivo Timmermans - - * README: Updated copyright notice. - -2000-05-16 18:07 Guus Sliepen - - * TODO: TODO file reinstated: - - Append your name to items if you're working on them. - - Remove them if you fixed the problem/implemented that feature. - - Add any (suspected) bugs. - -2000-05-16 15:09 Guus Sliepen - - * src/: conf.c, conf.h: Stub for VpnMask config directive. - -2000-05-15 20:28 Ivo Timmermans - - * src/conf.c, THANKS, doc/tinc.conf.sample: Unlimited length in the - config file, thanks to Cris van Pelt. - -2000-05-15 17:54 Ivo Timmermans - - * redhat/tinc.spec: Updated to newer version. - -2000-05-14 23:07 Ivo Timmermans - - * src/net.c: Give IP address instead of hex number when connecting - tcp socket failed. - -2000-05-14 23:04 Ivo Timmermans - - * configure.in: Changed version to 1.0pre2. - -2000-05-14 22:56 Ivo Timmermans - - * configure.in: Add check for mpz_powm in libgmp3. - -2000-05-14 15:50 Ivo Timmermans - - * src/protocol.c: Only print an error with send_termreq if - debug_lvl is 2 or more. - -2000-05-14 15:06 Guus Sliepen - - * src/net.c: Fixed typos. - -2000-05-14 15:02 Guus Sliepen - - * src/: net.c, net.h: Changed ping behaviour (backwards - compatible). If we don't have any data to send, we don't need to - check if the connection is still alive. Furthermore, if we receive - any kind of data from the other end, we know it's alive, so we don't - need to check it either. So, PING requests are only sent if we send - packets but there is no response. - -2000-05-14 14:22 Guus Sliepen - - * AUTHORS, README, THANKS, doc/tinc.conf.5, doc/tinc.texi, - src/conf.c, src/conf.h, src/encr.c, src/encr.h, src/genauth.c, - src/net.c, src/net.h, src/netutl.c, src/netutl.h, src/protocol.c, - src/protocol.h, src/tincd.c: Cleanups. - -2000-05-14 13:39 Guus Sliepen - - * src/: conf.c, conf.h, net.c: Proxymode removed. - -2000-05-12 15:31 Ivo Timmermans - - * doc/tinc.texi: Deleted the protocol description. - -2000-05-08 20:44 Guus Sliepen - - * src/: conf.c, conf.h, net.c: Added new config variable - "ProxyMode". If enabled, all outgoing packets are sent to the uplink - (ConnectTo), which will have to forward them for us (kernel should - do that). This is for people behind firewalls. - -2000-05-05 12:48 Ivo Timmermans - - * redhat/tinc: Added semicolons required by bash2 (Mads Kiilerich). - -2000-05-05 01:17 Ivo Timmermans - - * src/: encr.c, protocol.c: Include sys/types.h. - -2000-05-05 01:16 Ivo Timmermans - - * src/Makefile.am: Don't link in libdl. - -2000-05-04 02:01 Ivo Timmermans - - * configure.in: Check for the existance of libdl. - -2000-05-04 02:00 Ivo Timmermans - - * acconfig.h: More for getopt support. - -2000-05-04 02:00 Ivo Timmermans - - * lib/xmalloc.c: Include stdio.h for fprintf. - -2000-05-04 01:47 Ivo Timmermans - - * lib/: Makefile.am, getopt.c, getopt1.c, getopt.h: getopt_long() - support for platforms that don't have it. - -2000-05-04 01:00 Ivo Timmermans - - * lib/xmalloc.c: Don't use error.h or error(), put #error in front - of cpp errors. - -2000-05-03 20:02 Guus Sliepen - - * src/net.c: Squashed gcc warning. - -2000-05-03 19:59 Guus Sliepen - - * src/: net.c, protocol.c: Fixes typo and UDP network byte order. - -2000-05-03 17:37 Guus Sliepen - - * src/net.c: Outgoing packets now use network byte order in header. - -2000-05-03 17:01 Ivo Timmermans - - * redhat/: tinc, tinc.spec: Fix a typo, better handling of the info - document. (from Mads Kiilerich) - -2000-05-02 12:16 Guus Sliepen - - * src/: net.h, protocol.c: Replaced sprintf() by safer snprintf(), - removed possible buffer overflow by one byte. - -2000-05-02 11:55 Guus Sliepen - - * src/: net.c, net.h, protocol.c: Previous fix fixed. Meta protocol - should be really flawless from now on! - -2000-05-02 11:10 Guus Sliepen - - * src/net.c: Fixed small mistake that would prevent forwarding - requests. - -2000-05-02 00:00 Ivo Timmermans - - * NEWS: Mentioned new metaprotocol. - -2000-05-01 23:47 Ivo Timmermans - - * doc/tinc.conf.5, doc/tinc.conf.sample, doc/Makefile.am, - doc/tincd.conf.5, doc/tincd.conf.sample, redhat/tinc.spec: More - tincd->tinc updates. - -2000-05-01 23:31 Ivo Timmermans - - * src/: encr.c, net.h, protocol.c: Fixed meta protocol. - -2000-05-01 23:31 Ivo Timmermans - - * redhat/tinc.spec: Committed by Mads Kiilerich. - -2000-05-01 21:17 Ivo Timmermans - - * redhat/tinc.spec: Updates by Mads Kiilerich. - -2000-05-01 20:07 Guus Sliepen - - * src/: encr.c, net.c, net.h, netutl.c, protocol.c, protocol.h: - Meta protocol overhaul. Tinc is now incompatible with previous - versions, furthermore this version does NOT work yet because of a - problem with sending keys (these should be converted to base36 or - something like that). It is possible to telnet to the tinc daemon - now and type some commands by hand though :). - -2000-05-01 18:28 Ivo Timmermans - - * redhat/tinc: Committed by Lubomír Bulej. - -2000-04-30 22:48 Ivo Timmermans - - * src/protocol.c: Key forwarding, write one byte extra. - -2000-04-30 21:49 Ivo Timmermans - - * src/protocol.c: Protocol fix (ANS_KEY). This breaks 0.3.3 - protocol compatibility. - -2000-04-30 21:03 Ivo Timmermans - - * src/protocol.c: Send one less byte from an ANS_KEY request. - -2000-04-30 20:57 Ivo Timmermans - - * src/protocol.c: Read one less byte from an ANS_KEY request. - -2000-04-30 18:34 Ivo Timmermans - - * src/protocol.c: Removed debug messages. - -2000-04-30 18:31 Ivo Timmermans - - * src/protocol.c: Read public keys the right way (tm). - -2000-04-30 18:11 Ivo Timmermans - - * src/: net.c, net.h, netutl.c, protocol.c, protocol.h: New way of - handling the meta protocol. - -2000-04-30 15:23 Ivo Timmermans - - * src/net.c: Replaced check for status.active by status.dataopen in - check_network_activity. - -2000-04-30 03:16 Ivo Timmermans - - * src/netutl.c: Initially, the vpn_mask of a connection is - 255.255.255.255 to avoid confusion with lookup_conn. - -2000-04-30 03:15 Ivo Timmermans - - * src/: net.c, protocol.c: Got rid of the nasty hacks... and - replaced it by another one. - -2000-04-29 22:39 Ivo Timmermans - - * src/: protocol.c, protocol.h: Filled up the protocol structs with - unused bytes. - -2000-04-29 22:38 Ivo Timmermans - - * Makefile.am: Added `deb' target. - -2000-04-29 15:56 Ivo Timmermans - - * redhat/tinc, doc/tinc.texi, redhat/tinc.spec: More updates wrt. - the change from tincd->tinc. - -2000-04-28 13:33 Guus Sliepen - - * src/net.c: Oops! Reference to write_n() removed and changed into - neat write() call. - -2000-04-27 22:57 Guus Sliepen - - * src/net.c: Removed write_n() function. - -2000-04-27 15:47 Ivo Timmermans - - * src/tincd.c: Default config file name is tinc.conf, and pidfile - is tinc.pid. - -2000-04-27 02:07 Ivo Timmermans - - * README: Updated version number to 1.0. - -2000-04-27 01:56 Ivo Timmermans - - * Makefile.am, configure.in: Version to 1.0pre1; Create Makefile - and build in debian/. - -2000-04-27 00:42 Ivo Timmermans - - * doc/tinc.texi: Add an entry to dir. - -2000-04-26 19:42 Guus Sliepen - - * src/: conf.c, encr.c, net.c, netutl.c, protocol.c: Cleanups: - - Changed recv/send calls into read/write calls for streams - - Made all sizeof() functions use a variable name instead of type - -2000-04-26 16:54 Ivo Timmermans - - * redhat/tinc.spec: From Mads Kiilerich. - -2000-04-26 00:15 Guus Sliepen - - * src/encr.c: Converted every &variable[0] to variable. - -2000-04-26 00:00 Ivo Timmermans - - * src/net.c: Debug level tweaking. - -2000-04-25 22:50 Guus Sliepen - - * src/net.c: When trying to talk to a host that is in the netmask - of a tinc server but not the tinc server itself, and no keys have - been exchanged yet, the key request would be directed to the host - instead of the server. Fixed. - -2000-04-25 22:17 Guus Sliepen - - * src/net.c: Fixed typo and removed some unnecessary variables. - -2000-04-25 22:10 Guus Sliepen - - * src/: net.c, net.h: Packet queues fixed. They caused the trouble - when resending keys. - -2000-04-25 21:23 Ivo Timmermans - - * autogen.sh: Create a ChangeLog file, automake requires it. - -2000-04-25 21:21 Ivo Timmermans - - * doc/Makefile.summ: [no log message] - -2000-04-25 20:57 Guus Sliepen - - * src/: encr.c, net.c, netutl.c, protocol.c: Added checkpoints to - beginning and ending of every function. - -2000-04-25 19:38 Ivo Timmermans - - * Makefile.am: Remove ChangeLog with a `make cvs-clean'. - -2000-04-25 19:35 Ivo Timmermans - - * Makefile.am: Don't include TODO in the dist. - -2000-04-25 17:08 Ivo Timmermans - - * src/Makefile.am: Propagate CFLAGS from configure to gcc. - -2000-04-25 17:07 Ivo Timmermans - - * Makefile.am: Delete all the files that are created by autogen.sh - on a `make cvs-clean'. - -2000-04-25 12:40 Ivo Timmermans - - * doc/tinc.texi: Spelling fixes. - -2000-04-25 12:27 Ivo Timmermans - - * redhat/tinc.spec: Contributed by Mads Kiilerich. - -2000-04-25 12:21 Ivo Timmermans - - * autogen.sh, m4/Makefile.am: Generate this Makefile.am from - Makefile.am.in. - -2000-04-25 11:43 Ivo Timmermans - - * AUTHORS: [no log message] - -2000-04-25 11:42 Ivo Timmermans - - * THANKS: Added Mads Kiilerich, removed Guus Sliepen. - -2000-04-25 03:45 Ivo Timmermans - - * doc/tinc.texi: Changes largely from Mads Kiilerich. Removed - section about encryption. - -2000-04-25 03:26 Ivo Timmermans - - * m4/aclocal-include.m4: Remove test for GNOME. - -2000-04-25 03:25 Ivo Timmermans - - * ChangeLog: Use `make ChangeLog' to create this file from the CVS - logs. - -2000-04-25 03:23 Ivo Timmermans - - * acconfig.h: Don't define HAVE_NAMESPACES and HAVE_STL. - -2000-04-25 03:22 Ivo Timmermans - - * configure.in: Remove check for bigendianness. - -2000-04-25 03:15 Ivo Timmermans - - * TODO: This file is obsolete, most of the ideas are already in - echelon. - -2000-04-25 03:10 Ivo Timmermans - - * autogen.sh: s/Gnome/tinc/g - -2000-04-25 02:50 Ivo Timmermans - - * config.guess, config.h.in, config.sub, install-sh, ltconfig, - aclocal.m4, autogen.sh, configure.in, ltmain.sh, missing, - mkinstalldirs, stamp-h.in, m4/aclocal-include.m4: The shell script - autogen.sh can create all these removed files, but be sure to have - autoconf, automake, libtool and more installed. - -2000-04-25 02:11 Ivo Timmermans - - * configure.in: Don't try to create cipher/idea/Makefile. - -2000-04-24 11:39 Guus Sliepen - - * src/protocol.c: Bug found! Wrong pointer was used for handling - multiple ADD_HOST requests at once. (See line 606.) - -2000-04-24 10:32 Guus Sliepen - - * src/protocol.c: Added extra checks for desynchronized connection - lists. Hopefully this will fix those strange segmentation faults. - -2000-04-21 00:50 Ivo Timmermans - - * Makefile.am: Added cvs-clean. - -2000-04-20 21:14 Ivo Timmermans - - * NEWS: Keep make dist(dir) happy. - -2000-04-18 22:44 Ivo Timmermans - - * redhat/README: A short notice from Mads Kiilerich. - -2000-04-18 22:43 Ivo Timmermans - - * redhat/tinc.spec: Submitted changes by Mads Kiilerich. - -2000-04-18 22:30 Ivo Timmermans - - * doc/Makefile.am: Include genauth.8 in the distribution. - -2000-04-18 22:26 Ivo Timmermans - - * Makefile.am, configure.in, redhat/Makefile.am: Include the - directory redhat in the build process. - -2000-04-18 18:04 Ivo Timmermans - - * src/tincd.c: Address for bugreports changed to tinc@nl.linux.org. - -2000-04-18 17:59 Ivo Timmermans - - * doc/: tincd.conf.5, tincd.x: Updated manpages. - -2000-04-18 17:59 Ivo Timmermans - - * doc/genauth.8: New manpage for genauth. - -2000-04-18 17:09 Ivo Timmermans - - * redhat/: tinc, tinc.spec: Submitted by Mads Kiilerich. - -2000-04-17 19:04 Ivo Timmermans - - * src/genauth.c: Default passphrase length of 1024, added -h/--help - options. - -2000-04-17 18:59 Ivo Timmermans - - * src/genauth.c: Check if stdout is a terminal, if so, print a - verbose message. - -2000-04-17 18:52 Ivo Timmermans - - * src/encr.c: Check for an illegal length of passphrase in - read_passphrase(). - -2000-04-17 18:23 Ivo Timmermans - - * lib/xmalloc.c, src/tincd.c: Pass the requested size from - xmalloc() and xrealloc() on to xalloc_fail_func() - -2000-04-17 17:38 Ivo Timmermans - - * src/genauth.c: Only one round of reading bits out of urandom; - Reading `bytes' bytes out of it; Print a newline after completion. - -2000-04-12 18:22 Ivo Timmermans - - * configure.in: Moved to version number 1.0. - -2000-04-06 20:28 Ivo Timmermans - - * src/tincd.c: New option -D, don't detach. - -2000-03-28 21:16 Ivo Timmermans - - * src/tincd.c: Ignore SIGCHLD. - -2000-03-28 21:09 Ivo Timmermans - - * src/tincd.c: Kill the parent after any error conditions in - detach(). - -2000-03-28 00:59 Ivo Timmermans - - * src/encr.c: Upon regeneration, free the old encryption key - `securely\' by overwriting it. - -2000-03-28 00:30 Ivo Timmermans - - * src/net.c: Get rid of the message `zxnrbl\'. - -2000-03-26 01:33 Ivo Timmermans - - * AUTHORS, README, stamp-h.in, COPYING, ChangeLog, INSTALL, - Makefile.am, NEWS, THANKS, TODO, acconfig.h, aclocal.m4, - config.guess, config.h.in, config.sub, configure.in, install-sh, - ltconfig, ltmain.sh, missing, mkinstalldirs, m4/Makefile.am, - m4/Makefile.am.in, m4/README, lib/Makefile.am, lib/README, - m4/malloc.m4, m4/perl.m4, m4/realloc.m4, lib/alloca.c, - lib/malloc.c, lib/memcmp.c, lib/pidfile.c, lib/realloc.c, - lib/xmalloc.c, lib/pidfile.h, lib/utils.c, lib/utils.h, - lib/xalloc.h, src/Makefile.am, src/conf.c, src/encr.c, src/net.c, - src/netutl.c, src/protocol.c, src/conf.h, src/genauth.c, - src/tincd.c, src/encr.h, src/net.h, src/netutl.h, doc/Makefile.am, - src/protocol.h, doc/texinfo.tex, doc/tinc.texi, doc/tincd.conf.5, - doc/GNUmakefile, doc/Makefile.maint, doc/Makefile.summ, - doc/help2man, doc/tincd.conf.sample, doc/tincd.x: Initial revision - -2000-03-26 01:33 Ivo Timmermans - - * AUTHORS, README, stamp-h.in, COPYING, ChangeLog, INSTALL, - Makefile.am, NEWS, THANKS, TODO, acconfig.h, aclocal.m4, - config.guess, config.h.in, config.sub, configure.in, install-sh, - ltconfig, ltmain.sh, missing, mkinstalldirs, m4/Makefile.am, - m4/Makefile.am.in, m4/README, lib/Makefile.am, lib/README, - m4/malloc.m4, m4/perl.m4, m4/realloc.m4, lib/alloca.c, - lib/malloc.c, lib/memcmp.c, lib/pidfile.c, lib/realloc.c, - lib/xmalloc.c, lib/pidfile.h, lib/utils.c, lib/utils.h, - lib/xalloc.h, src/Makefile.am, src/conf.c, src/encr.c, src/net.c, - src/netutl.c, src/protocol.c, src/conf.h, src/genauth.c, - src/tincd.c, src/encr.h, src/net.h, src/netutl.h, doc/Makefile.am, - src/protocol.h, doc/texinfo.tex, doc/tinc.texi, doc/tincd.conf.5, - doc/GNUmakefile, doc/Makefile.maint, doc/Makefile.summ, - doc/help2man, doc/tincd.conf.sample, doc/tincd.x: Initial CVS - version for tinc 0.3. +Version 1.0.36 August 26 2019 +------------------------------------------------------------------------ + +Guus Sliepen (8): + Remove the call to RAND_load_file(). + Update THANKS. + Backport tinc 1.1's str2net() function. + Update THANKS. + Fix spelling errors found by codespell. + Reformat all code using astyle. + Add a missing check for a pathname being too long. + Releasing 1.0.36. + +Rosen Penev (2): + Fix compilation when OpenSSL has no ENGINE support + Fix compilation without deprecated OpenSSL APIs + +Quentin Rameau (1): + Double-quote nodes in graphviz network file + +Werner Schreiber (1): + Fix segfault when dest->mtu is 0. + +Version 1.0.35 October 05 2018 +------------------------------------------------------------------------ + +Guus Sliepen (12): + Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738) + Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758) + Check the return value from snprintf(). + Check the return values from BN_hex2bn() and RAND_load_file(). + Fix all warnings when compiling with -Wall -W -pedantic. + Fix two small memory leaks. + Don't check for NULL-pointers before calling free(). + Update THANKS. + Fix checks for Cygwin-related macros. + Fix spelling errors. + Update README and links to required libraries. + Releasing 1.0.35. + +AMRI Amine (1): + Fixing typo + +Rafael Sadowski (1): + OpenBSD has a proper tap device. + +Version 1.0.34 June 12 2018 +------------------------------------------------------------------------ + +Guus Sliepen (10): + Add missing thanks to the NEWS message. + Fix building documentation when using OpenBSD's make. + Fix #ifdefs that were broken due to commit d178b58. + Don't use SOL_IP and SOL_IPV6. + Make systemd service file handling identical to tinc 1.1. + Rename distro/ to systemd/. + Document how to enable tinc at boot time using systemd. + Fix all spelling errors found by codespell. + Properly implement tinc.texi's dependency on tincinclude.texi. + Releasing 1.0.34. + +Maximilian Stein (1): + Fix SEGFAULT when trying to connect to IPv6 peer in non-IPv6 environment + +wangliushuai (1): + Remove redundant 'break'. + +Version 1.0.33 November 04 2017 +------------------------------------------------------------------------ + +Guus Sliepen (31): + Udpate THANKS. + Fix a potential memory leak. + Use AC_CONFIG_MACRO_DIR(). + Give absolute path for #include to AC_CHECK_HEADERS(). + Prepare for automatic code formatting using Artistic Style. + Never remove items from cmdline_conf. + Use stack-allocated strings for temporary filenames. + Fix a few minor memory leaks. + Remove unused/obsolete checks from configure.ac. + Use getcwd() instead of get_current_dir_name(). + Remove xmalloc.c, backport xalloc.h from tinc 1.1. + Update all header guards. + Convert sizeof foo to sizeof(foo). + Reformat all code using astyle. + Don't call ERR_remove_state(). + Unconditionally include stdbool.h and inttypes.h. + Remove more obsolete autoconf checks. + Remove obsolete m4/README. + Fix some "make distcheck" errors. + Add some information about the requirements of a chroot environment. + Handle tun/tap device returning EPERM or EBUSY. + Disable PMTU discovery when TCPOnly is used. + Fix all -Wall -W compiler warnings. + Realign comments. + Remove unused functions. + Ensure all parameters have names in header files. + Support autoconf's --runstatedir option. + Const correctness. + Fix compilation errors when --enable-uml is used. + Update THANKS. + Releasing 1.0.33. + +Rafael Sadowski (1): + fix tinc.conf for OpenBSD + +nemunaire (1): + Allow compilation from a build directory + +Version 1.0.32 September 02 2017 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Don't dereference myself->incipher if it's NULL. + Merge remote-tracking branch 'VittGam/master' + Use /dev/udp instead of /dev/ip on Solaris. + Use getmsg()/putmsg() instead of read()/write() on Solaris. + Fix Solaris DeviceType = tap in router Mode. + Bind outgoing TCP sockets. + Move logging of "would block" messages to debug level 4. + Set KillMode=mixed in the systemd service file. + Don't forget about outgoing connections on host file read errors. + Fix Proxy = exec. + Set status.proxy_passed early for Proxy = exec. + Don't try to bind Proxy = exec sockets to an address. + Releasing 1.0.32. + +Vittorio Gambaletta (VittGam) (1): + route: Support ToS/DiffServ priority inheritance when routing IPv6 packets. + +Version 1.0.31 January 15 2017 +------------------------------------------------------------------------ + +Guus Sliepen (1): + Releasing 1.0.31. + +Élie Bouttier (1): + Remove ExecStop in tinc@.service + +Version 1.0.30 October 30 2016 +------------------------------------------------------------------------ + +Guus Sliepen (11): + Allow non-empty lines after status code from a HTTP proxy. + Fix proxy reply parsing broken by the previous commit. + Log only the first line of a proxy request rejection message. + Delay sending the real ID request until after a proxy request is granted. + Use AES256 and SHA256 by default, also for the meta-connections. + Enforce maximum amount of bytes sent/received on meta-connections. + Fix bit shifting arithmetic so the code actually does what the last commit message says. + Really fix byte budget calculation. + Use AES in CTR mode instead of OFB mode for meta-connections. + Use CFB mode for meta-connections to improve security. + Releasing 1.0.30. + +Version 1.0.29 October 09 2016 +------------------------------------------------------------------------ + +Guus Sliepen (11): + Preserve IPv6 scope_id in edges. + Ensure compatibility with OpenSSL 1.1.0. + Add -Wall to CFLAGS. + Check return value of RSA_generate_key_ex(). + Force nul-termination of strings after vsnprintf(). + Log warnings about dropped packets only with debug level 5 or higher. + Add a copy of ax_append_flag.m4. + Add ax_require_defined.m4. + Fix possibly unitialized variable. + Fix compiler warnings about format string errors on BSD. + Releasing 1.0.29. + +Version 1.0.28 April 10 2016 +------------------------------------------------------------------------ + +Guus Sliepen (8): + Fix compiling bsd/device.c on systems without utun. + Really remove use of __DATE__ and __TIME__ to facilitate reproducible builds. + Add systemd service files. + Update .gitignore. + Ensure the service files are in the tarball. + Explicitly mention that LibreSSL can be used as well. + Update links in the documentation. + Releasing 1.0.28. + +Version 1.0.27 April 10 2016 +------------------------------------------------------------------------ + +Guus Sliepen (26): + Add missing AM_PROG_CC_C_O to configure.ac. + Attribution for various contributors. + Update "now" after connect() when making outgoing connections. + Add ability to use proxies to connect to hostnames when there is no nameserver. + Only add a reflexive address when we're sure it's working. + Fix compatibility with TAP-Win32 9.0.0.21 and later. + Fix warnings from the Clang Static Analyzer. + Improve performance of edge updates. + Clarify that scripts are called synchronously. + Small fixes for the documentation. + Add warnings for bad combinations of Device and Interface. + Fix forwarding of edge updates. + Don't compile getopt*.c if the system provides getopt_long(). + Update .gitignore. + Update THANKS. + Use iface instead of interface. + Update copyright notices. + Remove use of __DATE__ and __TIME__ to facilitate reproducible builds. + Cast 0xff to char before comparing it to another char. + Get rid of a warning when compiling tinc using MinGW. + Every BSD flavor has a tap device nowadays. + Use devname() if available to support devfs cloning on BSD. + Use SIOCGIFADDR on BSDs that support it. + Enable silent builds by default. + Add support for OS X utun interfaces. + Releasing 1.0.27. + +Vittorio Gambaletta (VittGam) (6): + Fix DecrementTTL option. + Fix source IP address for ICMP unreachable packets generated by tinc. + Try to reply with node address only when decrementing the TTL. + Fix DecrementTTL option for packets destined to the local node. + s/broadcast_packet_helper/route_broadcast/ + Remove forward declaration for do_decrement_ttl. + +LunarShaddow (3): + fix typo + re-arrange include sequence to avoid a mingw introduced bug. + Proofing README. + +Florian Weik (1): + Fix NAME variable in subnet-* scripts for local subnets. + +Nathan Stratton Treadway (1): + Fix invalid checksum generation. + +Version 1.0.26 July 05 2015 +------------------------------------------------------------------------ + +Guus Sliepen (14): + Use VittGam's real name. + Attribution for Saverio Proto. + Always call res_init() before getaddrinfo(). + Fix --logfile without a filename on Windows. + Never call putenv() with data on the stack. + Return non-zero exit code when encountering configuration errors during startup. + Fix autoconf check for function attributes. + Fix spelling of FORTIFY_SOURCE. + Update copyright notices. + Attribution for various contributors. + Only check for -fno-strict-overflow if -fwrapv does not work. + Fix unputenv() on Windows. + Don't try to call res_init() if ./configure told us it doesn't exist. + Releasing 1.0.26. + +Jo-Philipp Wich (1): + fix musl compatibility + +Version 1.0.25 December 22 2014 +------------------------------------------------------------------------ + +Guus Sliepen (7): + Fix date of last NEWS entry. + Remember ToS/Diffserv priority for each socket individually. + Attribution for various contributors. + Automatically choose a tap device on Mac OS X when using switch Mode. + Update documentation for Mac OS X. + Check whether res_init() really lives in libresolv. + Releasing 1.0.25. + +Borg (3): + Fixed scripts calling under Win32. + Get MAC of TAP device. + Fixed tinc-up script calling on Win32. + +Alexis Hildebrandt (1): + Add support to link against libresolv Mac OS X + +Baptiste Jonglez (1): + Use the description from the 1.1 man page for the IndirectData option + +David Pflug (1): + Update README.android + +Jochen Voss (1): + Fix some typos in the manual. + +Tomislav ÄŒohar (1): + Configure minimum reconnect timeouts. + +VittGam (1): + Support ToS/DiffServ priority handling for IPv6 meta and UDP connections. + +Version 1.0.24 May 11 2014 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Remove useless variable 'hard' from try_harder(). + Merge pull request #14 from luckyhacky/master + Add an autoconf check for res_init(). + Nexthop calculation should always use the shortest path. + Fix issues found by Coverity. + Fix warnings found by GCC 4.9. + Fix a few more issues found by Coverity. + Fix a few more issues found by Coverity. + Drop h and hh length modifiers from printf format strings. + Fix a bug that could prevent tinc from starting correctly on Windows. + FIx the autoconf checks for res_init(). + Remove the warnings when IP_DONTFRAGMENT/IPV6-DONTFRAG is not supported. + Releasing 1.0.24. + +Steffan Karger (3): + Use constant time memcmp() when comparing packet HMACs. + Use cryptographically strong random when generating keys. + Check RAND_bytes() return value, fail when getting random fails. + +Armin Fisslthaler (1): + reload /etc/resolv.conf in SIGALRM handler + +Loic Dachary (1): + fix documentation typo + +luckyhacky (1): + update to openssl version 1.0.1g due to lack of heartbleed bug in prior version of openssl + +refs/tags/1.0.23-android-1 March 11 2014 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Mention in the manual that multiple Address staments are allowed. + If no Port is specified, set myport to actual port of first listening socket. + Enable compiler hardening flags by default. + Update support for Solaris. + Include for PATH_MAX. + Stricter check for raw socket support. + Use hardcoded value for TUNNEWPPA if net/if_tun.h is missing on Solaris. + Fix incorrectly merged bits from 80cd2ff73071941a5356555b85a00ee90dfd0e16. + Don't enable -fstack-protector-all. + Remove or lower the priority of some debug messages. + Clarify StrictSubnets. + Attribution for various contributors. + Handle errors from TAP-Win32/64 adapter in a better way. + +Florent Clairambault (2): + Adding "conf.d" configuration dir support. + Adding some documentation around the /etc/tinc/$NET/conf.d directory. + +Vilbrekin (1): + Update android build instructions. Disable PIE as this is not supported on some devices. + +Version 1.0.23 October 19 2013 +------------------------------------------------------------------------ + +Guus Sliepen (9): + Check for writability when waiting for a socket to finish connecting. + Don't send PING requests on connections which are not active yet. + Fix segfault when Name = $HOST but $HOST is not set. + Fix typos in the documentation. + Modernize the build system. + Get rid of the splay tree implementation. + Add description of IffOneQueue and MaxTimeout to the info manual. + Clean up child processes from proxy type exec. + Releasing 1.0.23. + +Version 1.0.22 August 13 2013 +------------------------------------------------------------------------ + +Guus Sliepen (7): + Better optional argument handling. + Fix a typo. + Set $NAME when calling host-up/down and subnet-up/down scripts. + Don't use vasprintf() anymore on Windows. + Don't echo broadcast packets back when Broadcast = direct. + Update copyright notices. + Releasing 1.0.22. + +Etienne Dechamps (1): + Fix combination of Mode = router and DeviceType = tap on Linux. + +Version 1.0.21 April 22 2013 +------------------------------------------------------------------------ + +Guus Sliepen (2): + Drop packets forwarded via TCP if they are too big (CVE-2013-1428). + Releasing 1.0.21. + +Version 1.0.20 March 03 2013 +------------------------------------------------------------------------ + +Guus Sliepen (30): + Use /dev/tap0 by default on FreeBSD and NetBSD when using Mode = switch. + Document how to load the tap driver on FreeBSD. + Update THANKS file. + Also clarify hostnames=[yes|no] in tinc.conf(5). + Attribution for Vil Brekin and some code style cleanups. + Don't ignore Makefile.am. + Fix links in documenation. + Attribution for Martin Schürrer. + Add strict checks to hex to binary conversions. + Clear connection options and status fields in free_connection_partially(). + Fix warnings from cppcheck. + Clear Ethernet header when reading packets from a tun device. + Clear status and options fields of unreachable nodes. + Fix warnings from groff. + Using alloca() for a constant sized buffer is very silly. + Make sure PMTU discovery works in switch mode with VLAN tags. + Mention in the manual that support for LZO and zlib can be disabled. + Fix configure script help text for --enable options. + Don't take the address of a variable whose scope is about to disappear. + Send broadcast packets using a random socket, and properly support IPv6. + Remove text saying you must have one of PrivateKey or PrivateKeyFile in tinc.conf. + Fix support for tunemu on iOS devices. + Make sure PriorityInheritance also works in switch mode. + Detect increases in PMTU. + Fix a compiler warning. + Fix segmentation fault when trying to connect via a SOCKS5 proxy. + Don't send proxy requests for incoming connections. + Fix compiler warnings on Windows. + Fix detection of rejected SOCKS5 proxy requests. + Releasing 1.0.20. + +Vilbrekin (5): + Basic patch for android cross-compilation. + Replace hard-code with new ScriptsInterpreter configuration property. + Add basic .gitignore file, cleaning (most) files generated by autotools. + Use __ANDROID__ define rather than dirty hard-code to allow android NDK cross-compilation. + Android cross-compilation instructions. + +Martin Schürrer (1): + Output details of encryption errors + +Mesar Hameed (1): + Minor clarification, tinc.conf hostnames=[yes|no] variable only resolves names for logging purposes. + +Version 1.0.19 June 25 2012 +------------------------------------------------------------------------ + +Guus Sliepen (14): + Support :: in IPv6 Subnets. + Remove newline from log message. + Add support for systemd style socket activation. + Allow environment variables to be used for Name. + Allow broadcast packets to be sent directly instead of via the MST. + Add basic support for SOCKS 4 and HTTP CONNECT proxies. + Add support for SOCKS 5 proxies. + Add support for proxying through an external command. + Document new proxy types. + Small fixes in proxy code. + #include on Windows. + Fix compiler warnings. + Fix crash when using Broadcast = direct. + Releasing 1.0.19. + +Anthony G. Basile (1): + configure.in: fix AC_ARG_ENABLE and AC_ARG_WITH + +Michael Tokarev (1): + add (errnum) in front of windows error messages + +Version 1.0.18 March 25 2012 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Always try next Address when an outgoing connection fails to authenticate. + Allow a port to be specified in BindToAddress statements. + Add support for multicast communication with UML/QEMU/KVM. + Set default value of DecrementTTL to "no". + Add #ifdefs in case not all platforms support IPv4 and IPv6 multicast. + Allow scoped addresses to be used for IPv6 multicast socket. + Fix compiler warnings. + Fix return value type of vde_send(). + Fix some more compiler warnings. + Document OpenBSD "ifconfig link0" and Linux "ip tuntap" commands. + Fix return type of vde_recv() as well. + Mark DecrementTTL option experimental. + Releasing 1.0.18. + +Version 1.0.17 March 10 2012 +------------------------------------------------------------------------ + +Guus Sliepen (32): + Prevent read_rsa_public_key() from returning an uninitialized RSA structure. + Return false instead of void when there is an error. + Fix compilation of VDE and UML interfaces. + Add vde/device.c to the tarball. + Fix a few small memory leaks. + Allow linking with multiple device drivers. + Set FD_CLOEXEC flag on all sockets. + Allow multiple BindToAddress statements. + Merge branch 'master' of black:tinc + Send packets back using the same socket as they were received on. + Allow setting DeviceType to tun or tap on Linux. + Merge branch 'master' of black:tinc + Only compile raw socket code when it is supported on that platform. + Decrement TTL of incoming packets. + Don't bind outgoing TCP sockets anymore. + Rename connection_t *broadcast to everyone. + Allow disabling of broadcast packets. + Move initialization of char *priority up to prevent freeing an uninitialized pointer. + Document the command line flag -o and provide --option as well. + Fix a bug that caused tinc to ignore all but the last listening socket. + Fix check for raw socket support. + Pass index into listen_socket[] to handle_incoming_vpn_data(). + Add LocalDiscovery option which tries to detect peers on the local network. + Don't send ICMP Time Exceeded messages for other Time Exceeded messages. + Stricter checks against routing loops. + Only use broadcast at the start of the PMTU discovery phase. + Only log errors sending UDP packets when debug level >= 5. + Accept Subnets passed with the -o option when StrictSubnets = yes. + Add missing ICMP6 message type definitions. + Make sure disabling old RSA keys works on Windows. + Update copyright notices. + Releasing 1.0.17. + +Nick Hibma (1): + Add missing ICMP message type definitions. + +Version 1.0.16 July 23 2011 +------------------------------------------------------------------------ + +Guus Sliepen (4): + Make code to detect two nodes with the same Name less triggerhappy. + Flush output buffer in send_tcppacket(). + Use usleep() instead of sleep(), MinGW complained. + Releasing 1.0.16. + +Version 1.0.15 June 24 2011 +------------------------------------------------------------------------ + +Guus Sliepen (9): + Reorder checks for libraries to allow ./configure LDFLAGS=-static. + Make return value of SetPriorityClass() behave the same as setpriority(). + Fix sparse warnings and add an extra sprinkling of const. + Remove newlines from log messages. + Remove a few unnecessary #includes. + Attribution for Loïc Grenié. + Improved --logfile option. + Remove redundant @CFLAGS@ from AM_CFLAGS. + Releasing 1.0.15. + +Loïc Grenié (1): + Nearly tickless tinc. + +Version 1.0.14 May 08 2011 +------------------------------------------------------------------------ + +Guus Sliepen (48): + Fix reading configuration files that do not end with a newline. Again. + Define WINVER before including any other header file on Windows. + Use intptr_t instead of long to store a pointer. + OpenSSL 1.0.0 compiled for 64 bit Windows requires linking with -lcrypt32. + Fix all warnings when compiling with mingw64. + Use strrchr() insteaad of rindex(). + Detect and prevent two nodes with the same Name being on the VPN simultaneously. + Use 64 bit counters to keep track of bytes sent/received from the virtual network interface. + Do not append an address to ANS_KEY messages if we don't know any address. + Merge local host configuration with server configuration. + Remove duplicate command-line option parsing. + Attribution for Julien Muchembled. + Attribution for Timothy Redaelli. + Ensure there is a newline character before a PEM key is written. + Abort disabling old PEM keys on I/O errors. + Remove unused variables. + Quit when there are too many consecutive errors on the tun/tap device. + Read error counter must be static. + Add short options -R and -U to the tincd(8) manpage. + Don't use strlen() on a NULL pointer. + Provide usleep() for Windows. + Use variable length arrays instead of alloca(). + Fix warning message when setting SO_RCVBUF or SO_SNDBUF fails. + Free replay window when freeing a node_t. + Fix variable length array declaration. + Attribution for Brandon Black. + Use setpriority() instead of nice() on UNIX-like systems. + Always send MTU probes at least once every PingInterval. + Close all filedescriptors in Solaris close_device(). + Limit field width when scanning PID file. + Replace bogus #else with #endif. + Remove unused variables. + Document the behavior of "-n." + Update the manual. + Update the NEWS. + Proper check and dropin replacement for usleep(). + Fix typo spotted by Andrew Scheller. + Add support for VDE through libvdeplug. + Fix spurious misidentification of incoming UDP packets. + Prevent anything from updating our own UDP address. + Do not set indirect flag on edges from nodes with multiple addresses. + Increase threshold for detecting two nodes with the same Name. + Always use the default signal handler for ABRT signals. + Check for EVP_EncryptInit_ex instead of SHA1_Version in OpenSSL. + Update THANKS and copyright information. + Ensure proper linking with OpenSSL with recent versions of MinGW. + Include when using intptr_t. + Releasing 1.0.14. + +Brandon L Black (4): + Experimental IFF_ONE_QUEUE support for Linux + Configurable SO_RCVBUF/SO_SNDBUF for the UDP socket + Configurable ReplayWindow size, zero disables + Improved handling of queue-jumping packets on receive + +Julien Muchembled (2): + New '-o' option to configure server or hosts from command line + Fix command-line '-o' option for host configuration + +Timothy Redaelli (2): + Fix warnings showed using -D_FORTIFY_SOURCE=2 + Fix warnings under BSD + +Michael Tokarev (1): + Treat netname="." in a special way. + +Rumko (1): + DragonFlyBSD support + +Version 1.0.13 April 11 2010 +------------------------------------------------------------------------ + +Guus Sliepen (20): + Clamp MSS to miminum MTU in both directions. + Simplify reading lines from configuration files. + Check for dirent.h. + Preload all Subnets in TunnelServer mode. + Add the StrictSubnets option. + Add the Forwarding option. + Add the DirectOnly option. + Fixes for the Forwarding option. + ConnectTo does not mean tinc does not listen for incoming connections anymore. + Log unauthorized Subnets when StrictSubnets is set. + Fix typo. + Convert Port to numeric form before sending it to other nodes. + Ensure ICMP_NET_ANO is defined. + Reload Subnets when getting a HUP signal and StrictSubnets is used. + Fix reloading Subnets when StrictSubnets is set. + Ensure subnet-up/down scripts are called after HUP when necessary. + Fixes for definitions under Windows. + Don't redefine MAX if it already exists. + Mark Forwarding and DirectOnly options as being experimental. + Releasing 1.0.13. + +Timothy Redaelli (2): + Add --disable-lzo configure option + Add --disable-zlib configure option + +Sven-Haegar Koch (1): + Never delete Subnets when StrictSubnets is set + +Version 1.0.12 February 03 2010 +------------------------------------------------------------------------ + +Guus Sliepen (21): + When learning MAC addresses, only check our own Subnets for previous entries. + Remove unused variable in lookup_subnet_*() functions. + Forget addresses of unreachable nodes. + Do not fragment packets smaller than RFC defined minimum MTUs. + Allow port to be specified in Address statements. + Use xstrdup() instead of xasprintf() to copy static strings. + Allow Port and PMTUDiscovery options in tinc.conf, always enable PMTUDiscovery by default. + Clamp MSS of IPv4 SYN packets. + Ping nodes immediately when receiving SIGALRM. + Optimise handling of select() returning <= 0. + Also clamp MSS of TCP over IPv6 packets. + Make MSS clamping configurable, but enabled by default. + Fix subnet-up/down scripts being called with an empty SUBNET. + Run subnet-up/down scripts for local MAC addresses as well. + Be liberal in accepting KEY_CHANGED/REQ_KEY/ANS_KEY requests. + Determine peer's reflexive address and port when exchanging keys. + Immediately exchange keys when establishing a meta connection. + Try to set DF bit on BSDs as well. + Update copyright notices. + Ensure peers with a meta connection always have our key. + Releasing 1.0.12. + +Version 1.0.11 November 01 2009 +------------------------------------------------------------------------ + +Guus Sliepen (16): + Fix a possible crash when sending the HUP signal. + Starting to work towards 1.0.11. + Handle weighted Subnets in switch and hub modes. + Clarify and increase level of log message about MTU probes to unreachable nodes. + Add dummy device. + Use uint32_t instead of long int for connection options. + Allow UDP packets with an address different from the corresponding TCP connection. + Always reply to MTU probes via UDP. + Make maxmtu equal to minmtu when fixing the path MTU to a node. + Forward packets to not directly reachable hosts via UDP if possible. + Use IP_DONTFRAGMENT instead of IP_MTU_DISCOVER on Windows. + Use WSAGetLastError() to determine cause of network errors on Windows. + Move socket error interpretation to utils.h. + Fast handoff of roaming MAC addresses. + Start a tinc service if it already exists. + Releasing 1.0.11. + +Michael Tokarev (1): + Remove localedir leftovers. + +Version 1.0.10 October 18 2009 +------------------------------------------------------------------------ + +Guus Sliepen (78): + Update documentation for git. + Consistently allocate device and iface variables on the heap. + Only send packets via UDP if UDP communication is possible. + Move free()s at the end om main() to the proper destructor functions. + Change flush_events() to expire_events(). + Add missing cleanup functions in close_network_connections(). + Use a global list to track outgoing connections. + Remove unused definitions from net.h. + Allow reading config files with CRLF endings on Unix systems. + Validate Name before using it in a filename when generating a keypair. + Disable old RSA keys when generating new ones. + Handle neighbor solicitation requests without link layer addresses. + Allow weight to be assigned to Subnets. + Update THANKS and copyright information. + Disable PMTUDiscovery in switch and hub modes. + Use a simple Random Early Drop algorithm in send_tcppacket(). + Handle UDP packets from different and ports than advertised. + If PMTUDiscovery is not set, do not forward packets via TCP unnecessarily. + Fix link to Mattias Nissler's tun/tap driver for MacOS/X. + Fix initialisation of packet decryption context broken by commit 3308d13e7e3bf20cfeaf6f2ab17228a9820cea66. + Use xrealloc instead of if(ptr) ptr = xmalloc(). + Add declaration for sockaddrcmp_noport(). + Use packet size before decompression to calculate path MTU. + Do not forward broadcast packets when TunnelServer is enabled. + Add ProcessPriority option. + Add some const where appropriate. + Properly set HMAC length for incoming packets. + Don't try to send MTU probes to unreachable nodes. + Remove pending MTU probe events when a node's reachability status changes. + Do not log errors when recvfrom() returns EAGAIN or EINTR. + Change level of some debug messages, zero pointer after freeing hostname. + Always remove a node from the UDP tree before freeing it. + Add xasprintf() and xvasprintf(). + Check the return value of fscanf() when reading a PID file. + Replace asprintf() by xasprintf(). + UNIX signal numbers start at 1. + Ensure tinc compiles with gcc -std=c99. + Convert bitfields to integers in a safe way. + Add the GPL license to the repository. + Another safe bitfield conversion. + Add support for iPhones and recent iPods. + Don't stat() on iPhone/iPod. + Put Subnet weight in a separate environment variable. + Allow PMTUDiscovery in switch and hub modes again. + Handle unicast packets larger than PMTU in switch mode. + Remove superfluous call to avl_delete(). + Apparently it's impolite to ask GCC to subtract two pointers. + Use only rand(), not random(). + Also do not use drand48(), it is not available on Windows. + Allow compiling for Windows XP and higher. + Remove dropin random() function, as it is not used anymore. + Use access() instead of stat() for checking whether scripts exist. + Raise default crypto algorithms to AES256 and SHA256. + Remove extra {. + Use a mutex to allow the TAP reader to process packets faster on Windows. + Raise default RSA key length to 2048 bits. + Send large packets we cannot handle properly via TCP. + Update copyright information. + Remove all occurences of $Id$. + Remove Ivo's old email addresses. + Update the address of the Free Software Foundation in all copyright headers. + K&R style braces. + Remove checkpoint tracing. + Drop support for localisation. + Add more authors to the copyright headers. + Update the NEWS. + Remove autogenerated files from EXTRA_DIST. + Don't disconnect clients in TunnelServer mode who send unauthorised ADD_SUBNETs. + Remove code duplication when checking ADD_EDGE/DEL_EDGE messages. + Revert "Raise default crypto algorithms to AES256 and SHA256." + Ensure that the texinfo manual can be converted to HTML. + Small updates to the documentation. + Use MTU probes to regularly ping other nodes over UDP. + Allow the cloning /dev/tap interface to be used on FreeBSD and NetBSD. + Remove debugging message when reading packets from a BSD device. + Include missing header. + Fix description of the WEIGHT environment variable. + Releasing 1.0.10. + +Michael Tokarev (17): + Allow tunnelserver to work with clients that have other peers. + Enable PMTUDiscovery only if BOTH sides wants it. + Rename setup_network_connections() and split out try_outgoing_connections() + Implement privilege dropping + bugfix: initialize pid (as read from pidfile) to zero + bugfix: move mlock to after detach() so it works for child, not parent + bugfix: chdir(/) after chroot + change error messages in droppriv code to match the rest + format 'not supported on this platform' error message + TunnelServer: Don't disconnect client on DEL_SUBNET too + ignore indirect edge registrations in tunnelserver mode + don't log every strange packet coming to the UDP port + Fix ans_key exchange in recent changes + tunnelserver: log which ADD_SUBNET was refused + cleanup setpriority thing to make it readable + try outgoing connections before chroot/drop_privs + Remove extra semicolon in my definition of setpriority() + +Florian Forster (2): + src/linux/device.c: Fix segfault when running without `--net'. + src/net_socket.c: Bind outgoing TCP sockets to `BindToAddress'. + +Borg (1): + Removed last gettext function. + +Version 1.0.9 December 26 2008 +------------------------------------------------------------------------ + +Guus Sliepen (18): + Handle SERVICE_CONTROL_INTERROGATE requests. Thanks to Carsten Ralle for noticing this. + Make sure the prefixlength of subnets is sane. + Fix reading configuration files that do not end with a newline. + Do not try to send REQ_KEY or ANS_KEY requests to unreachable nodes. + Prevent freeing a NULL pointer when a hostname is unresolvable. + Correct debug message. + Treat virtual network device as tap if Mode = switch or hub. + Use TUNIFHEAD by default on FreeBSD to make sure IPv6 works. + Make sure IPv6 sockets are IPv6 only. + Update Dutch translation. + Update copyright information. + Enable PMTU discovery by default. + Update documentation. + Update the manpage as well, and some whitespace to make its source more legible. + Handle broadcast and multicast packets in router mode. + Apply patch from Max Rijevski fixing a memory leak when closing connections. + Add missing parentheses in check for IPv4 multicast addresses. + Releasing 1.0.9. + +Version 1.0.8 May 16 2007 +------------------------------------------------------------------------ + +Guus Sliepen (8): + Apply patch from Scott Lamb preventing an infinite loop when sending SIGALRM. + Apply patch from Scott Lamb fixing some memory and resource leaks. + Close the proper filedescriptor (if it exists). + Apply patch from "dnk" making sockets non-blocking under Windows. + Make sure connection->name is never NULL. + Update dutch translation. + Don't free struct addrinfo too early. Spotted by Christian Cier-Zniewski. + Releasing 1.0.8. + +Version 1.0.7 January 05 2007 +------------------------------------------------------------------------ + +Guus Sliepen (7): + Use a ringbuffer in shared memory to transfer packets from the tapreader thread to the main thread. + Tapreader socket should be bound to localhost only. + Fix generic BSD tun device to write only the actual packet length. + rename() cannot replace existing files on Windows. + No things to do for the 1.0 branch except bugfixing. + Update copyright notices. + Releasing 1.0.7. + +Version 1.0.6 December 18 2006 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Make sure resolved addressed for outgoing connections are freed, if there are any. + Search for lzo/lzo1x.h, lzo2/lzo1x.h and lzo1x.h. + When building the minimum spanning tree, make sure we start from a reachable node. + Use the correct next pointer. + Remove unnecessary stuff from configure.in. + Remove old Spanish translation. + Fix rule that creates html version of manpages. + Use standard autoconf macros instead of our own. + We do properly check for malloc and realloc. + Remove the test for linux/if_tun.h. + Do a simple test for linux/if_tun.h instead of no test at all. + Prevent compiler warnings about redefinition of EAI_FAMILY on FreeBSD 6.1. + Releasing 1.0.6. + +Version 1.0.5 November 14 2006 +------------------------------------------------------------------------ + +Guus Sliepen (32): + Prevent possible buffer overflows when using very large (>= 8192 bit) RSA keys. + Add alloca.h to the list of necessary header files. + Enable OpenSSL ENGINE, so crypto hardware gets used. Thanks to Andreas van Cranenburgh. + EVP_Cleanup() when quitting. + Apply patch from Scott Lamb unifying configuration of TCP socket options. + Apply patch from Scott Lamb adding an output buffer for the TCP sockets. + Make sure $NAME is set correctly when executing tinc-down script. + Missing #include. + Export flush_meta(). + Fix signedness compiler warnings. + Fix a bug in handling prefixlengths that are not a multiple of 4. + Update copyright notices, remove Ivo's email address. + Restore length of the original packet in send_udppacket(). + Use memcpy() to copy sockaddrs returned by getaddrinfo(). + Add generic host-up and host-down scripts. + Do not break strict aliasing of status_t structs. + Fix format string warnings. + Remove unused variables. + Remove unused parameter from maskcmp(). + Remove unused variable. + memcpy() addresses from packet headers before calling the lookup functions. + The "active" bit in node.status is not used. + Added graph dumping ability based on Markus Goetz's patch. + popen() requires pclose(). + Support and autodetect LZO version 2.0 and later. + Support and autodetect LZO version 2.0 and later. + Document GraphDumpFile option. + Update Dutch translation. + Nodes use events, so event system should be initialised first and destroyed last. + When deleting an entire tree, start at head, not at root. + EWOULDBLOCK does not exist on platforms without O_NONBLOCK + Releasing 1.0.5. + +Version 1.0.4 May 04 2005 +------------------------------------------------------------------------ + +Guus Sliepen (17): + Make sure broadcast packet reach the local network interface. + Fix splay tree code. + subnet-up/down hooks + subnet-up/down hooks, use list_t for the todo list. + Small fix. + Free memory used by connection_t after it is deleted from the connection tree. + Use the proper free function. + Correct size argument for strncat(). + Nodes should only be in the node_udp_tree if they are reachable. + Don't try to add a non-existing node back to the node_udp_tree. + Remove unused (and potentially segfaulting) net2str() call. + Be on the safe side with initialisation of c->name. + Searching through splay trees may change the tree variable. + Several splay tree fixes. + Describe subnet-up/down scripts in documentation. + Update copyright notices. + Releasing 1.0.4. + +Version 1.0.3 November 11 2004 +------------------------------------------------------------------------ + +Guus Sliepen (77): + Removed items in TODO list that are already implemented. Only two items + Applied patch from Jamie Briggs for bash2 conformance. + Added another semicolon for bash2 compliance (thanks to Jamie Briggs) + Adding even more stuff from the CABAL branch. + Synchronise HEAD with CABAL branch. + This will become 2.0. + Some device.c files weren't synchronised. + Makevars file was accidentily removed. + Forgot to synchronise po/ directory... + Add description of new authentication scheme. + Add Opaque option which prevent information from being forwarded to certain nodes. + Replace Opaque and Strict options with a TunnelServer option. + Complain if pid file cannot be created. + Read MaxTimeout from tinc.conf like the manpage says. + Missing space between words. + Don't retry if configuration is wrong from the beginning. + Fix proxy-neighborsolicitation. + Code beautification, start of multicast support. + Forget multicast. Always inline some function. + Let tinc figure out the exact MTU of the link. + More sensible name, and try to set PMTU discovery on IPv6 sockets as well. + Describe the TunnelServer and PMTUDiscovery options. + Better name, show probed MTU in dump. + Improvements for PMTU discovery and IPv4 packet fragmentation. + Missing definitions. + Small fixes for PMTU discovery. + Don't forget to update destination MAC address. + Small updates. + Remove autogen.sh, the autoreconf program does exactly that. + Replace cvs-clean with a much better svn-clean. + Remove CVS related cruft. + Eat trailing whitespace in config files. + Only read our public key if it wasn't already in the private key file. + Updating dutch translation. + Even better svn-clean command. + Applied Martin Kihlgren's IdentityGenerosity patch, + Fix declaration of update_node_address(). + Use Subversion to create ChangeLog, better svn-clean rule. + Revert Martin Kihlgren's patch, it doesn't work the way it should. + Move CABAL branch to its rightful place: the trunk. + Update copyrights, links, email addresses and let Subversion update $Id$ keywords. + Increase MTU by 4 bytes to allow VLAN tagged Ethernet frames in hub and switch mode. + Clean up environment after executing scripts. + Handle timeouts during connecting the same way as other errors. + Added UML network socket handling. + Don't set $INTERFACE automatically, don't quit on EINTR/EAGAIN. + Marking potential late packets was in the wrong place. + Remove duplicate #include "system.h" + Move all #ifdef HAVE_HEADER_H #include to have.h, + Fix several #includes. + strndupa() is too arcane for some environments. + Allow tinc to work with the latest TAP-Win32 driver. + Correct return value. + Don't let tinc service depend on NDIS component. + Support alternative tun/tap driver from http://www-user.rhrk.uni-kl.de/~nissler/tuntap/ + Generic device driver for *BSD and MacOS/X + static + Check for sys/uio.h, net/if_tun.h and net/if_tap.h + Don't include .svn directory in sample configuration. + Splay trees. + Hoopjumping to get the default directories in the manuals properly. + Update to make it compile again. + Fixed another bug in late packet handling. + Hopefully this really fixes late packet handling. + Missing check for NULL-pointer. + Use the generic BSD tun/tap code. + Fix order of arguments for tar. + Let compiler decide when to inline. + Support tunneling IPv6 on Solaris. + Add BlockingTCP option, useful when using TCPOnly on slow or congested links. + Update documentation. + Set BSD tuns to broadcast mode. On OpenBSD, this enables IPv6 on the tun device! + Remove duplication. + Updated dutch translation. + Short readme about how to compile tinc from a Subversion checkout. + Add more people who have contributed to tinc. + Releasing 1.0.3. + +Ivo Timmermans (52): + Check for __gmpz_powm for libgmp3. + Changed version number to 1.0pre3. + Autogenerated by gettextize. + Bring head revision up to date with cabal (try #3) + Add check for the syslog function + Generalized error handling functions + Add all the new files to the sources list for the utility library + New function: xalloc_and_zero() + Generalized list and hash handling functions + First try to create a graphical frontend for tinc configuration + Updating HEAD branch #1; removing obsolete files. + Updating HEAD branch #2; removing debian/ dir. + Updating HEAD branch #3; more obsolete files removed. + Updating HEAD branch #4; Merging CABAL -> HEAD. + Updating HEAD branch #5; Last files from CABAL. + Ok, I forgot these ;) + More updates + More... + Last bits (hopefully) + Main pokey interface files. + Pokey interface definition + Write src/pokey/Makefile + Also compile in pokey/ + Remove debug level declaration + Update copyright info + Remove debug_lvl + New logging system to replace syslog() calls with a generic function. + Rename log_message to log + Add syslog() wrapper + Add syslog wrapper + Some magic + Added priority definitions from syslog.h + log_default_hook was renamed to log_default + Added prototype for log_syslog + Use logging.h instead of syslog.h + Compile in logging.c + Things to ignore... + Use new logging system + Include logging.h + Renamed libvpn to libtinc + Rename libvpn to libtinc + ... + Print newline when writing to stderr + *** empty log message *** + Moving files, first attempt at gcrypt compatibility, more interface + Commit diff test + Another file moved; random interface stuff. + Callbacks + Moved event.c/h + test + test 2 + Hm. + +Wessel Dankers (5): + Initial revision. Lots of loose ends, not usable yet. + added bit on config file, split up sections, added Id: tag + Added extra bit about keys. + More about keys + This file is now only in the CABAL revision. + +cvs2svn (1): + This commit was generated by cvs2svn to compensate for changes in r1352, + +Version 1.0.2 November 08 2003 +------------------------------------------------------------------------ + +Guus Sliepen (47): + Simplify fake getname/addrinfo() functions, possibly fixing freeing a NULL pointer. + stat() batch files under Windows. + Don't getsockopt() SO_ERROR. We get the error from send()/recv() anyway. + Fix fake getnameinfo() and check more arguments. + Fix --logfile under Windows. + Use the event log under Windows. + Compilation fix. + Do what the SDK documentation tells. + If we're not in main_loop() and the service is stopped, exit immediately. + Allow tinc to handle unknown type addresses from other tinc daemons. + Don't overwrite the first " when installing a service. + Add checkpoints. + When purging nodes, only delete them if nobody references them anymore. + Remove debug message. + Add license exception from Markus Oberhumer. + Remove old edges from unreachable nodes to us. This prevents the hosts/NAME-up + We don't have to tell GCC how to cast. + Prevent multiple inclusions. + Remove pidfile when exitting. + Update translations. + Check for short packets from the tun/tap device and from other tinc daemons. + Generate keys with 0x10001 as public exponent, which has less prime factors + Better length checks. + Copy structs from packets to the stack before using them, to prevent + const + Ethernet protocol types. + Unused variable in struct. + Don't confuse users with "Address family not supported" warnings. + Use CPPFLAGS, LDFLAGS and LIBS as appropiate. + PIDs are of type pid_t, and use %ld when reading/writing them to the pidfile. + Make sure type of AF_UNKNOWN is sa_family_t. + Forgot to #include "xalloc.h" + Update missing definitions, structs describing headers get __packed__ attribute. + Missing declaration. + Set media status for newer TAP-Win32 driver. + Some platforms don't know sa_family_t or define it other than uint16_t. + Update documentation. + Fix ASCII art. + Check return value of EVP_* functions, and check if length before en/decryption + Check all EVP_ function calls. + Parentheses in the wrong spots. + Fix bug that could lead to an assertion failure in libcrypto when multiple + Small fixes in documentation. + Fix another bug in meta.c. + Update dutch translation. + Add missing definitions. + Release notes for 1.0.2 + +Version 1.0.1 August 14 2003 +------------------------------------------------------------------------ + +Guus Sliepen (24): + Windows uses backslashes... + Tell windows to be patient. + Remove unused stuff from doc/. + Correct error message when remote host closed connection. + Simplify execute_script(). It will probably work under Windows as well. + Allow empty lines in config files. + Make rule for sample-config.tar.gz. + Readd quotes. + Typo. + Better error messages under Windows. + Log error first, try to close later. + Quote when needed and don't try stuff that doesn't work under Windows. + Under Windows, the installation directory can be found in the registry. + Better error checking and reporting. + Small things. + Simpler checking of permissions on private RSA key and other fixes. + Check for fchmod(). + Only system() needs script name quoted. + Update documentation. + Add a description for the Service control panel. + Updated dutch translation. + Small fixes. + Fix permissions check for rsa_key.priv. + Update. + +Version 1.0 August 08 2003 +------------------------------------------------------------------------ + +Guus Sliepen (111): + Thank some more people. + Run graph() after edge_del() when updating an edge. + Add documentation for BindToAddress. + Fix PriorityInheritance. + PrivateKeyFile instead of PrivateKey. + Run graph algorithm when replacing a second connection from the same host + Add $NAME for tinc-up/down scripts. + - Fix indentation in some places. + Various fixes for autoconf and OpenSSL 0.9.7 and a missing header. + Make sure send_meta() writes everything. + Typo. + - Avoid memory leak caused by OpenSSL 0.9.7a. + - Speed up checksumming + Don't copy more than necessary. + Checksums must also work for uneven number of bytes. + HUP signal now closes connections to hosts if their host config file is + Better handling of late packets. + Make sure outgoing_t is completely freed. + - Per-node EVP_CIPHER_CTX to avoid initialisation overhead. + Small fixes to make LZO compression work. + Small fixes. + Fix links. + Fix warning and add missing checks for LZO library. + Call make_names() before doing anything else. + If we have a Linux tun/tap device and we are in router mode, open the device + AddressFamily is "any" by default. + Remove mymac stuff from device.c. + Fixes from Wessel Danker's libavl. + More braces to make gcc happy. + Update documentation. + Update dutch translation. + Typo and conversion to UTF-8. + There are two lzo compression levels. + Really make tinc default to any addressfamily. + This subtle pointer arithmetic thingy is (I'm very sure of it) the cause + - simplify configure.in + Check for IPv6 header files. + Define logger(), cleans up source code and allows us to write log entries + Sprinkling the source with static and attributes. + Provide all missing IPv6 definitions in lib/ipv6.h. + Actually add ipv6.h. + More missing definitions. + More missing IPv6 definitions and autoconf checks to make sure it compiles + Simplify logging, update copyrights and some minor cleanups. + Update copyrights. + Removing distribution specific files from CVS. + Format string checking for logger(). + Export mymac. + Make use of the CIPE driver. Woohoo, tinc for Windows! + Windows headers declare a struct interface somewhere. + Big header file cleanup: everything that has to do with standard system + Even more missing definitions. + Remove all #ifndefs from route.c + Update all device.c files. + Check for ethernet/ipv4/ipv6 related structures. + Use iface instead of interface because it might already be declared in + Oops. + No UNIX style permissions under Windows. + Be consistent. + Oops. + Check for sys/mman.h. + Use functions from logger.c + Copy cygwin driver to mingw directory. It doesn't work (yet). + Add section about configuring Cygwin and CIPE on Windows. + Option to specify pidfile location. + Use bools and enums where appropriate. + Run setup_device() after parsing configuration but before claiming we're ready. + Don't initialise a CIPHER_CTX if cipher == NULL. + Sprinkle around a lot of const and some C99 initialisers. + More generic handling of tap device under Windows. + More checks for missing functions. + Fix compile errors and warnings. + Update dutch translation and make sure all device drivers are included in + Update configure scripts. + Make sure it works. + Make sure (at least) the MinGW device driver works. + Native Windows support. + Cleanups. + Update documentation and remove stuff that's too outdated. + Remove doc/es/ and src/device.c from the distribution. + No C99 initialisers, gcc 2.95.3 doesn't like it. + Replacement for stdbool.h + Prevent definitions from messing up attributes. + Check if the compiler knows about the __malloc__ attribute. + Wrong argument. + Remove forgotten braces. + No easy way to properly detect header files... + Woops! + Wrong function... + Prevent system headers from including our own headers. + Allow whitespace in values. + Oops. + Windows has no symbolic links as we know it. + When compiling with MinGW, link with ws2_32. + Install tinc as a service under Windows (MinGW). Remove cleanup_and_exit(), + Error messages. + Cleanups and error messages. + Missing include. + Oops. + Updated dutch translation. + Explain how tinc detaches and how it is "killed" under Windows. + Typo and another thing to think about. + Clean up last part of main(). + Old gcc compilers don't like declarations in the middle of a function. + Cygwin needs windows.h. + Keep Windows happy. + Remove newlines from log messages. + Update dutch translation + Simplify translation + Use our own port when connecting to ourself. + Sync CABAL branch with release-1_0 branch. + +Ivo Timmermans (2): + Fix saving of debug level for startup level 0 + Call RSA_blinding_on(), as advised in the paper on + +Wessel Dankers (1): + its: Engels voor "van het" - 3e persoon enkelvoud, genitief, onzijdig + +Version 1.0pre8 September 16 2002 +------------------------------------------------------------------------ + +Guus Sliepen (73): + Support for MaxOS/X. + Add BindToAddress variable, similar to the late BindToIP. + Added Nick Patavalis for his RedHat package. + Informative log message if execl() failed. + Fix very stupid bug in node_del(), which might have caused corruption of + Only purge once when there are no more connections. + Support RSA_PUBKEYs (as opposed to RSAPublicKeys) so tinc accepts + Make it work correctly with NetBSD tun device. + Use correct includes on NetBSD. + Cleanup: + Use inttypes.h instead of stdint.h. + - netinet/* include files depend on netinet/in_systm.h. + Added Darwin (MacOS/X) tun device handling. + Use darwin/device.c when compiling on MacOS/X. + Include darwin/device.c in distribution. + Autoconf cleanup. Works for both 2.13 and 2.53, although running autoconf + Add configuration details for NetBSD and Darwin (MacOS/X). + Reset listen_sockets after SIGHUP. + Update comments about IPv6 autoconfiguration. + s/sliepen.warande.net/sliepen.eu.org/g + Fix for prefixlengths of 32 (IPv4) and 128 (IPv6) bits. + Allow list of environment variables to be passed to execute_script(). + Allow identical subnets from different owners. + Clear subnets before using them. + Started port to Cygwin. + Added stub device.c for Cygwin. + Include complete fake-getname/addrinfo from OpenSSH. + Allow tincd to be locked into main memory. + Don't bother to chown, and correctly document ConnectTo. + Added support for raw sockets. This can be used instead of tun/tap devices. + Gettext 1.11.5 compatibility. + Check for ranlib. + Replacement for the current routing algorithm. + Make sure setlocale() is available. + Drop graph and edge stuff. Use new node stuff instead. + A reachable node is always more preferable to an unreachable one... + Woops. + Reduce KEY_CHANGED traffic. + Prevent looping DEL_NODE/ADD_NODE messages after a node disconnects. + Don't forget to set prevhop to myself for new connections. + Just ignore wrong ADD_NODEs instead of replying with a DEL_NODE, in the + Revert to edge and graph stuff. This time, use a directed graph. + Small fixes. + Generalized request broadcasting/forwarding. + Updated dutch translation. + Small updates. + Run autopoint and libtoolize before creating initial makefiles. + Add missing headers. + Typo. + Only reset seqno's when a key is sent or received. + Remove global edge_tree. + edge_weight_compare() shouldn't rely on edge_compare(). + Reset the *correct* seqnos. + Fix MST algorithm. + Why don't these connection_t's get cleaned up? + Cleanups: + Switch to K&R style indentation. + Switch to K&R style indentation. + Remove redundant spaces. + Let GCC check format string and arguments of send_request(). + Fix compiler warnings. + Clean up after indent. + Link with libintl if necessary. + Fix placement of #include "config.h" + Make sure malloc() is declared. + What was I thinking? + MacOS/X needs #define _P1003_1B_VISIBLE in order to use mlockall(). + port_t isn't used anymore and conflicts with MacOS/X headers. + Small fixes so tinc compiles out of the box on SunOS 5.8 + Updated dutch translation. + Use /dev/net/tun as default for tun/tap device under Linux. + Update documentation. + Remarks about 1.0pre8 release. + +Ivo Timmermans (9): + Put #ifndef checks for HAVE_RAND_PSEUDO_BYTES in the correct places. + Typo + OSX support + getnameinfo fixes + Add /sw/{include,lib} to search paths if they exist + Include a few more header files + Include netbsd's device.c in make dist + Added Alessandro Gatti + Added AM_MAINTAINER_MODE + +Wessel Dankers (1): + This should work much better. + +Version 1.0pre7 April 09 2002 +------------------------------------------------------------------------ + +Guus Sliepen (9): + Make configure --help output look nicer. + Don't check_network_activity() if select() is interrupted by a signal. + check_rsa() is broken, I don't know why, just remove it for now. + Fix maskcheck() and maskcmp(). + Automake forgets about depcomp, remind it. + masklength is better known as prefixlength. + masklength is better known as prefixlength + Updated dutch translation. + Remarks about 1.0pre7 release. + +Version 1.0pre6 March 27 2002 +------------------------------------------------------------------------ + +Guus Sliepen (91): + Forgot to merge new files from pre5. + Last bits of the merger. + Sensible defaults for $INTERFACE. + - If no PrivateKeyFile is specified, /etc/tinc/netname/rsa_key.priv is assumed. + Small fix. + Added support for packet compression, thanks to Mark Glines. + Don't use sa_sigaction (which NetBSD doesn't like) at all if we don't use siginfo. + Get rid of sys/signal.h. + Added device.c for NetBSD, actually a copy of the OpenBSD one. + Add check for NetBSD. + - Non-blocking connect()s. + Fix segfault when receiving HUP signal. + Use AF_UNSPEC for listening sockets if AddressFamily = any. + Forward packets in router mode. + Fix maskcmp() and maskcpy(). + Cache results of lookup_subnet_...(). + Protocol now also exchanges cipher/digest/maclength/compression for the + Preserve inpkt->len, needed for broadcasts. + - Use gai_strerror() where appropriate + - Change SA_LEN to SALEN, former one is already defined on some platforms. + Tweaking IPv6 support. + Allow multiple listening sockets. + Fix send_request() bug. + Make BindToInterface work. + Fix listening sockets. + If "PriorityInheritance = yes" is specified in tinc.conf, the value of the + Create/bind TCP and UDP listening sockets in pairs. + Updated documentation. + Updated dutch translation. + - Global time_t now, so that we don't have to call time() too often. + Document and clean up MAC address expiry. + Woops. + Check if BindToDevice and PriorityInheritance are supported. + Fix forwarding of IPv6 packets. + po/POTFILES and po/Makefile should not be generated by configure. + Autodetect $MAKE/gmake/make. + Small fixes to improve portability. + Don't retry to make outgoing connections when exitting. + Cleanups, spelling fixes, allow symbol names for signals (-k option), + prune_connections() before build_fdset(). + Try to reply to neighbor solicitation requests. + New strategy: forward icmp6 neighbor solicitations to intended target. + Simplified implementation of Kruskal's minimum spanning tree algorithm. + Packet sequence number/authentication warnings only if debug_lvl >= 5. + Remove silly cache thingy. + Put #ifdef NEIGHBORSOL around corresponding code. + Revert changes to Kruskal's algo. + Neighbor solicitation requests now work (I think). + Oops, don't forget to actually put the checksum in the response packet. + Different way of detecting neighbor solicitation requests. + Typo. + Unmap v4mapped sockaddrs. + Only unmap IPv6 addresses. + #define s6_addr32, needed for FreeBSD. + Fix #define s6_addr32. + Remember sockaddrs of listening sockets, use appropriate one when sending + Cleanup. + Don't use s6_addr[16|32] anymore. + Updated dutch translation. + Updated SSSP algorithm to automatically detect indirect links (if a node uses + Put a break on requests that run around in circles. + - Added support for jumbograms. + Fix add_edge_h(). + Fix compiler warnings, strictly use long int and %lx for options. + send_ack() was broken. + free() request strings when deleting past requests from the tree. + Don't run graph algorithms if no edge is deleted in terminate_connection(). + Reset retry timeout when receiving the first PONG, not right after receiving the ACK. + Don't try to execute scripts unless they exist. + Execute hosts/name-up when a node becomes reachable, and hosts/name-down + Set $INTERFACE correctly when using ethertap while compiled with tun/tap support. + Updated dutch translation. + Respect type field. + OpenBSD tun device uses address family number instead of Ethernet type. + Configuration variables were still handled case sensitively. + Set myself->status.reachable. + Updated documentation. + Tell a little bit more about security. + Send REQ_KEY only once until ANS_KEY has arrived. + Fix execute_script(). + Small correction. + Merge do_prune() with build_fdset(). Probably fixes the invalid filedescriptor error. + Extend list_t with the number of elements in the list. + Limit the amount of packets in a queue to 8. + Small updates. + Remove cruft. + Recent automake uses $(AMTAR) instead of $(TAR) + Remove symlink to device.c when doing a make dist. + Fix format strings. + Update dutch translation. + Update with information about the pre6 release. + +Version 1.0pre5 February 10 2002 +------------------------------------------------------------------------ + +Guus Sliepen (109): + Small fixes to allow correct compilation under FreeBSD (tested with 4.3) + Make sure Solaris is happy too. + Fix subnet_lookup() for overlapping subnets. Needs rethinking. + Added proxy-arp support. No more ifconfig -arp needed. Works like a charm + - tinc can now act as a switch or a hub too (as opposed to a router only) + Changed some stuff to allow correct generation of po/Makefile after a + Updated dutch translation. + - This oneliner removes the need for ifconfig tap? hw ether fe:fd:0:0:0:0 + Fix bug where lookup_subnet_ipv4() could go into an infinite loop. + You can now put an option "Mode" in tinc.conf, and choose from: + Add missing? counting of total_socket_in. + Log and warn about duplicate subnet_add()'s for the same subnet. + Fixes to make switching work between hosts that have no meta-connection. + Save configure cache more often. + Changed drastically because it didn't work correctly: + Only reset seconds_till_retry when we activate the outgoing connection. + Woops - big bug in send_key_changed fixed. + - Solaris compile fixes + Check for and add -ldl. + Remove #warnings I used for debugging stuff. + Reinstated search for if_tun.h in kernel source tree, because apparently + Spanish translation removed. Nobody maintains it, and it is severely + ABOUT-NLS is created by autogen.sh. + Don't build Spanish translation. + Execute tinc-down BEFORE tap device is closed. This is a. more symmetric + es.po revived. + Also remove po/Makefile.in.in, which is generated by autogen.sh. + Log error if two hosts connect with same IP/port tuple. + Fix gcc 3.0 warnings. + Check for dlopen in standard libraries first (needed for DEC OSF). + It appears that autogen.sh doesn't like es.po if it isn't mentioned in + Update of RedHat build scripts. + Dutch translation updated. + More items marked as done. + Fix printf format bug. + Fix compiler warning. + Check for all potential duplicate entries in the id tree. + - Always use instead of just + Don't load table of verbose OpenSSL errormessages. + Correct inclusion of standard if_tun.h header file. + Split connection list into two lists: + Correctly use the active_tree. + Remove all unnecessary status.meta and status.active checks. + Added purge_tree for connection_t's which are no longer in the connection, + Updated terminate_connection() so you can choose if DEL_HOSTs should be + Always close all sockets in terminate_connection(). + Woohoo! tinc now compiles, runs and actually *works* on Solaris! + Started writing a document about how daemons connect to each other. + Described problem in more detail. + Small update. + Correctie. + Written down a possible solution. + Discuss how sending ADD_EDGEs would be better than sending ADD_HOSTs. + More on edges. + Don't use %m in fprintf(). + Write public key to rsa_key.pub instead of rsa_key.priv (if not host + The val variable in a config_t is never used as a long. + Explicitly log which type of tunnel device is used. + Don't send DEL_HOSTs when !status.meta + Fix signed comparison bug in lookup_subnet_ipv4(). + Remove IndirectData support for now, new implementation will be added + Revised reconnection mechanism, always try out all ConnectTo lines. + Optional signal number for -k option. + config_t* is a const parameter in get_config_val(). + - Try old TUN/TAP ioctl() request if the one from if_tun.h fails. + Not only keep track of nexthop, but also of lastbutonehop. If destination cl + Show next- and lastbutonehop when dumping connectionlist to syslog. + Try next connectto instead of the same over and over. + Fill in next- and lastbutonehop for myself. + - Renamed lastbutonehop to prevhop. + Fix bug where tinc would crash because of a portscan or a connection from a + - Use ping timeout mechanism to close connections that don't authenticate + Fix bug when dropping an old connection in favour of a new one from the + Updated dutch translation. + Started implementing doc/CONNECTIVITY. + Small corrections. + Further implementation of doc/CONNECTIVITY. connection.[ch] is now split into a + Removed everything from connection.c that has already been moved to node.c and + Revamp configuration handling: + More updates to new node/vertex/connection combo. + - Split tap device stuff out of net.[ch] + Added FreeBSD tap device handling. + Solaris tun device handling cleaned up a bit and added. + Forgot to remove some old #ifdef stuff. + Added OpenBSD tun device handling. Untested though. + Forgot the tun specific stuff. + Support new files (node/vertex/device.[ch]) and OpenBSD. + Big bad commit: + Make sure everything links. + Various small fixes to make tinc runnable again. + What was I thinking? s/vertex/edge/g. + - More s/vertex/edge/g + - More changes needed for Kruskal's algorithm + Working version of Kruskal's algorithm. The running time is very bad though. + Various fixes, tinc is now somewhat capable of actually working again. + More updates to protocol handlers and reimplemented terminate_connection(). + - Small fixes to graph algorithms + Don't forget to read public RSA key when making an outgoing connection. + Show cfg->variable instead of cfg->value when complaining about wrong type. + Avoid connecting to another node twice, and check name of outgoing connections. + Some very small fixes + Use PEM functions as suggested by OpenSSL docs. + Several bugfixes. + *** empty log message *** + Be liberal in what you accept: allow unknown edges to be deleted. + Correctly check if subnet owner exists. + Various fixes needed for Solaris. + More fixes for Solaris. + Merging of the entire pre5 branch. + +Ivo Timmermans (32): + New make target: `make release' + Changed version number to 1.0-cvs + Don't distribute autogen.sh in a release + Don't include the debian/ dir in a release + Small fix to make it compile again + Killing tincd with SIGINT causes it to toggle between the current + Check for getaddrinfo + Check for getnameinfo, gai_strerror, freeaddrinfo + Credit OpenSSH + Check for struct addrinfo + Deprecated get_config_ip and get_config_port + Use struct addrinfo in connection_t to hold all host data such as IP + Changed prototype for lookup_connection to use struct addrinfo + Changed lookup_connection to use struct addrinfo + Removed definitions of ipv4_t, ipv6_t, port_t + Obsoleted all IP types in favor of struct addrinfo + Changed to use struct addrinfo where needed. + get_config_{ip,port} removed. + Don't compile/link netutl.c. + Obsoleted. + Don't include netutl.h. + (re)added port to struct node_t + Added HAVE_STRUCT_ADDRINFO + Added dropin replacements for get*info and helper functions. + First part of rewriting things to use struct addrinfo. + lookup_node_udp changed. + Don't include netutl.h. + route_ipv4 and route_ipv6 replaced by route_ip. + get_config_subnet needs to be fixed. + Fixed silly typo: "np" instead of "no" + Don't include netutl.h. + Conversion to struct addrinfo is almost complete for this file. + +Wessel Dankers (1): + make is not always GNU make. + +Version 1.0pre4 May 25 2001 +------------------------------------------------------------------------ + +Guus Sliepen (97): + Porting to FreeBSD: + - Added balanced tree management stuff as well. (It is not finished yet.) + - Simplified do_detach + - Removed stray @INCLUDE@ (how did that get there?) + - Fixed searching + - Implemented deletions + - Fix tree head/tail upon insertion + - Fixed a lot of small things. Tested everything except deletions. + - Deletion also works now. + - Small fixes + - Integrate rbl trees into tinc. + - Proper initialization of rbltree structures. + - Various small fixes. + - More fixes. + - Check for NULL tree->delete callback + - Cleaned up and checked for some more NULL pointers in rbl.c + - Write pidfile AFTER detaching... + - No more %as. + - Work with the correct key buffer in ans_key_h + - More porting to FreeBSD and Solaris. + - Fixed all (except 2) compiler warnings gcc -Wall gave. + - #include instead of + - Don't link with -ldl anymore + Another big & bad commit: + - Added Armijn to the list + - Added daemon() replacement. + - Use only one socket for all UDP traffic (for compatibility) + - Don't even think about using sscanf with %as anymore + - AVL tree routines: faster than RBL, and also more stable. + - Doubled size of trace buffer for easier debugging. + - Let user choose whether keys are in the config files or separate + - Updated dutch translation. + - Check and follow symlinks in is_safe_path + - Changed license of AVL tree library to GPL. + - Updated manual pages. + - Updated texinfo manual. + - Typo. + - Changed list routines to give it the same look'n'feel as the rbl and + - Reinstated a queue for outgoing packets. + - Added header file for route.c. The routing routines in it are not used + - Description of protocol and authentication updated. + - It's 2001, all copyright notices are updated. + - Fixed IPv6 subnet lookup routine. + - Added indirectdata and tcponly functionality. + - Squashed another nasty bug. + - Sign was wrong in search_closest_smaller/greater + - Cleaned up subnet_t + - Only send out DEL_HOSTs for hosts with a meta connection + Added sample configuration directory. + - Copy entire sample-config directory to /etc/tinc/example upon installing. + - Allow ASN1 style keys to be in the config files. + FreeBSD compile fixes (thanks to XeF4) + Fix memory leak in avl_insert() if item was already inserted. + Updated dutch translation. + Removed another local definition of the variable "errno" + Added .cvsignore files to get rid of warnings and prevent autogenerated + Ignore file for src/ + - Updated CVS_CREATED to remove intl/ directory and some other + Added description of the proposed new authentication scheme. + Corrected check for errors after read() calls. + Add missing \n. + Free node->data and node, not node->data twice. + Copy packets before putting them in the queue. + Encrypt network packets in CBC mode instead of CFB mode. + Implemented new authentication scheme from doc/SECURITY2. + Added process.c to the translated files. + - Make sure METAKEY is smaller than the modulus of the RSA key + Don't forget to reconnect if outgoing connection fails during + - Fixed Interface option (untested) + Removed lots of compiler warnings. + Removed compiler warning. + Various small fixes. + Added explaination of our key exchange using RSA encryption. + - route.c is now used to determine destination + Updated translation. + Added a description of what is going on in net.c and route.c, and how + Fixed a race condition triggered by receive_meta() and the new + Fixed bug in setup_signals() that would make tinc die when unexpected + Ignore alarm signals if we do not need to respond to them. + Check indirectdata option before forwarding certain requests. + Depend on new ssl package and install alias for universal TUN/TAP module. + Correctly cycle through ConnectTo variables. + - s/ip_t/ipv4_t/g + - Make sure correct information is supplied for both old kernels (with + More revisions to the documentation: + Changed URL from kernelnotes.org to linuxdoc.org. + Add randomness to PING/PONG packets to prevent crypto attacks on quiet + Since this is incompatible with some earlier versions, PROT_CURRENT is + All features for 1.0 are implemented now, we just have to check the + Only send key_changed if it was previously requested. + Small fixes: + Small corrections to the manuals. + With recent kernels the tun device file is located in /dev/net. + TCPonly now works (in a relatively clean way too). + Merged PROTOCOL, NETWORK and SECURITY2 with the texinfo manual. + Documents are merged. Now we only need to check the ports and the TCPonly + Fix sample configuration to show keys in PEM format and correct tapdevice. + +Ivo Timmermans (88): + Add a check for openssl that accepts explicit file locations. + Identify version as 1.0pre4-cvs + Better checks for OpenSSL. I think it can now detect almost all conceivable installations. + Oops, small error. + Get rid of the annoying empty line + Also check for rand.h and err.h. If any of these files does not + Also check for sha.h. + Use the HAVE_OPENSSL_xxx_H defined from m4/openssl.m4 during + Let the output from an executed script in execute_script() go to + List management and manipulation routines. + Keep a list of running children, and in each loop in main_loop(), + Move all process-related functions into process.c. + New function: xmalloc_and_zero, which initialises the allocated memory + Delete struct ifr + Move more functions from tincd.c into process.c. + Use proper prototypes. + Added this release + More function and header checks + Also include process.h + Get rid of all libtool references at once. libtool was only used by + Honor the --localstatedir option to configure, instead of hardcoded /var. + Add more checks to ensure that filedescriptors are right in + Declare fd. + Do not use the C library's daemon() call. + Do not check for the daemon() system call + Do not attempt to retreive ChangeLog information only from the CABAL + Set localstatedir to /var + Use cvs2cl instead of rcs2log to generate the ChangeLog. + Set CFLAGS to -O2 -Wall when running configure + Alter CFLAGS, somehow INCLUDES doesn't propagate properly. Still + Set errno to 0 before trying to kill the other process. + Explain how to tell configure where OpenSSL lives. + Call autogen.sh instead of configure alone; and make cvs-clean instead + Add default tinc-up and tinc-down scripts for a Debian system. These + Updated Spanish translation, provided by Enrique Zanardi. + Give an error message if daemon() failed. + Check for the function strsignal, and define it to "" if it is not + Sort items to either 1.0 or future release goals. + Use sigaction to set signal handlers, the previous commit (1.1.2.16) + Save RSA public and private keys to a separate file, instead of + dropin.c/h contain a set of drop-in replacements for non-standard C + Check for get_current_dir_name. There is a replacement function in + Added a check for a scanf that knows about %as. + Implemented a readline() function that will read an entire line into a + xstrdup now takes a const pointer as an argument. + Use readline() in read_config_file() instead of fgets. + Also free the pointer returned by readline(). + Updated Dutch translation + Implemented is_safe_path, and extended ask_and_safe_open. + Read the PEM file pointed to by the configuration directive + The file is safe if it doesn't exist. + In readline(): initialise the line to zero length; + Better error checking when reading the RSA private key. + Avoid printing duplicate messages from read_rsa_keys + New function read_rsa_public_key(); + All full stops have two spaces after them. (Silly commit, I know.) + Tagged `Storing private key in separate file' as done. + readline() accepts two extra parameters, buf and buflen, to avoid + Use buffer instead of line in read_config_file(), line may be assigned + Stated that distributing executables linked with OpenSSL is permitted + Include COPYING.README in the distribution. + Added documentation merger + Sort configuration directives + Option -d accepts an argument to set the debug level immediately. + Massive long awaited documentation update. It's not finished yet, + Oops. I did some VERY wrong things with readline(). Fixed now. + Tiny bits of code beautifying + Install a file in /etc/modutils/tinc, containing all necessary aliases + Ported it back to /bin/sh. + Give a warning about having to re-create the keys + Re-introduced MyVirtualIP and VpnMask, as dummy options. + Various small changes. + Include autogen.sh (needed for the Debian package). + Forget router.c + Added lint target, requires lclint. + Fix error reporting of read_config + Set Architecture to `any' + Change version to 1.0pre4 + Second draft of the release notes + Merged documentation with various updates I had lying around + Get the Debian changelog up to date + Get the PO files up to date with the current source + Fixed some errors + Distribute the sample config as a .tar.gz + Unpack sample-config.tar.gz when installing + More files to ignore in CVS + tinc_TUNTAP now substitutes the values outside the AC_CACHE_CHECK + Authentication done + +Wessel Dankers (1): + Important bugfix in avl_insert_before() and avl_insert_after() + +Version 1.0pre3 November 09 2000 +------------------------------------------------------------------------ + +Guus Sliepen (119): + Debian init.d script automatically sets tap device's MTU to 1448 now. + First step for implementation of the "indirectdata" directive. This should + If we have "indirectdata" flag set, we only send data to our uplink. + Large cleanup: + Added CVS Id tags to header files. + - Log possible spoofing attacks. + Hostnames are back! + Hostlookup() is actually being called now. + - More verbose connection list + Fixes some hostlookups. Fixes indirectdata for real now (hopefully). + - Indirectdata finally REALLY REALLY works now! + - Moved all connection messages to debug level 1, without -d's only the + - Fixed KEY_CHANGED notification. A lot of notify_others() calls were + - Fixed indirectdata=no problem + - Improved handling of errors on connection attempts. + - Purge old connections that are ADD_HOSTed. + - Fixes a silly little insignificant buglet. + - Extra check op EINTR bij inlezen requests + - Fixed some spelling errors. + - Fixed missing " in nl.po + - Fixed a message in nl.po + - Added log message when SIGCHLD is received ("thanks" to Ivo van Dong) + - Updated Dutch translation. + - Removed all IP_ADDR_S macros, because gettext doesn't like them. Each + - New semantics for BASIC_INFO, ADD_HOST and DEL_HOST requests. This will + - Fixed memory leak. + - Removed segfault bug in conf.c (must have been there for ages!) + - Instead of logging an error when remote end closes the connection, + - Made tinc even more silent if no -d flag is given at all. + - Added documentation for the protocols (most important the meta protocol) + - Removed a single unused bit from status_bits_t. + - Updated PROTOCOL (a bit) + - Forgot to mention ourselves in the tincd manual page! :) + - Added Spanish translation from Enrique Zanardi. + - Updated THANKS file + - Delayed address resolving for ConnectTo lines in configuration file to + - Fixed typo. + - Added experimental hackish tunneling-over-TCP support. + - Lots o' buglets fixed (-Wall helps) + Fixed PACKET read loop. + Removed calling add_queue for tcponly packets. + - Added date/time of build and protocol number to --version output. + - Moved TCP packet reception to meta handler: less kludgy and less buggy! + - Reinstated O_NONBLOCK for meta socket + - Added two extra configuration options, Interface and InterfaceIP, to + Fixed all sprintf() spl01ts. + Ran update-po and updated dutch translation. + Commented on some size calculations. + Updated the manual: + Updated tinc.conf manual. + Fix rules (thanks to Laurence) + - Use strerror() instead of sys_errlist[] for increased portability + - New protocol. Will break everything else for now. + - Added more function skeletons for the new protocol. + - Lots of functions added for the new protocol. + - Some key exchange stuff. (Last commit before going to bed.) + - Fixed modulo in keylength check + - Lots of small changes. + Added document about the used cryptographic algorithms and the reasons + - Included authentication scheme from protocol.c + - Updated authentication scheme. + - Severe code reduction and simplification of challenge requests + - Removed options "string" stuff. It was a bad idea... + - Very detailed example of the authentication phase. + - Added meta.c which contains functions to send, receive and broadcast + - Added subnet handling code + Removing cipher directory (all will be covered by OpenSSL). + Big and bad commit of my current tree... + - Changed genauth to produce rsa keypairs instead of random passphrases. + - Generalized config file parsing to support multiple configuration trees. + - Fixing-things pass: every source file compiles into an object file now, + - Second fixing-things pass: it even links now. + - The daemon actually runs now (somewhat) + Corrected #ifdefs for tun/tap support. + - Fixing little things + - More fixing. Tinc daemons can now even create activated connections. + - Seed the PRNG using /dev/random before generating the keys. + - tinc now really does public/private key encryption! It even works, whee! + - Made Makefile.am stub for doc/es/ + - Removed last reference to genauth from Makefile.am + - Fixed all debug levels. + - route.c will contain the routing logic. + - Lots of little stuff modified + - Updated subnet list handling. Subnets are added to two lists now, the + - Lots of small fixes + - Fixed offsets when reading/writing from/to tap device + - Override destination ethernet address on incoming packets with + - Very big cleanup. + - Fixed ans_key_h + - Hit people who can't figure out subnet address/mask pairs with a + - Enforce correct order of authentication requests + - Moved connlist stuff to the proper header file. + - Updated dutch translation. + - Removed old encr stuff + - Small fixes + - Use CFB mode for encrypting packets: it works and we don't need padding. + - Finishing touch: encrypt the meta connections + - Small cleanups + - Fixed some spelling mistakes and terminology here and there. + - Update. + Removed config file parsing and interface setup. This will be handled by + - Removed unused MAC strip/add functions. + - Removed even more warnings. + - Resolve scriptname after fork() + - Removed manpage for no longer existing genauth. + - connlist.c added to translation + - Don't forget to set packet cipher for added hosts. + - Forward keys in hex notation, not as binary data. + - Check for packets that are looping back. + - Simplified ping mechanism. + - Prepended config_ to all configuration option names, because it confused + Changed execution of tinc-up: + - Open UDP connection for all known hosts. Comments please. + Porting to SunOS 5.8: + Porting to SunOS 5.8: + - Fixed --config + - Applied Jamie Brigg's patch (close sockets after error) + - Add Jamie :) + - Make checkpoint tracing a compile time option (off by default) + +Ivo Timmermans (77): + Alphabetized the list, added Lubom�r Bulej, removed Sander Smeenk and Tijs van Bakel, put merits after all names. + Don't touch VPNMASK if it's defined, otherwise use $MSK. + These files are created by gettextize (run by autogen.sh) (should have known that). + Include ../intl in the include path, and add @INTLLIBS@ to the list of libraries. + Merge changes from 1.6-1.8. + Configuration directive `IndirectData'. + Changed version number to 1.0pre3. + Version 1.0pre3. + Removed Free Software Foundation copyright, because Guus Sliepen contributed significantly. + Oops, and mention Guus too. + Include the Spanish translation in the distribution/build process. + (Quoting Laurence Lane:) + Also chomp $VPNMASK + Added a rule to create an rpm + Changed CVSROOT path in `make ChangeLog' + Link with OpenSSL crypto libraries instead of own blowfish library + Updated text, removed protocol flowchart + Include openssl/blowfish.h + Support for -lsocket and -lnsl on SunOS + Correct filenames for passphrases given in the example + Add Guus' name and shift out old protocol requests + Better checks for SunOS libraries + Added some structures and types that are needed for the overhaul. + New directive: Name. + First round of needed fixes after the overhaul + Second round of fixes + Added Spanish translation of the docs by Matias Carrasco + Many updates, parts rewritten, added, shuffled around. + Link with OpenSSL, forget libGMP + Updated new requirements, pointers to the manual + Don't look for GMP header files + Update Depends lines to reflect the dependencies on OpenSSL + Fix `Requirements'-section for GMP and OpenSSL libraries. + Add CVS id lines + Add checks for the presence of the universal tun/tap device driver. + Wrap the tun/tap code in #ifdef HAVE_TUNTAP + Linearized checks for if_tun.h + Really #include the if_tun.h files now + Output doc/es/Makefile + Process subdir es/ + Don't declare cp_file and cp_line in xmalloc() + Get the head revision up to date with cabal + Changed changelog + Include linux/sockios.h and net/if.h anyway, regardless of the value of HAVE_TUNTAP. + read_server_config: Check for result of read_config_file. + Oops, echelon change committed to cabal... :) + Skip the check for Linux kernel sources + This file is no longer needed. + - Synchronized changelog with the package's changelog. + Do not include $(top_srcdir)/cipher, it does no longer exist. + Added a perl example to turn an IP address into a MAC address. + Only check for linux/if_tun.h once + Changed `I' to `We' - small change, lots of difference :) + More exhaustive list of changes - perhaps it can be worded differently? + Change wsl to Wessel's name and email address in the ChangeLog creation + Mention fileutils, add a pointer to THANKS for more details + Changed a few messages wrt. system calls; updated and changed the Dutch translation a bit. + Don't include shlibs, as it no longer exists. + Oops, and include doc-base.tinc (new file). + - If necessary, patch po/Makefile.in from po-Makefile.in.in.diff to + Minor cosmetic change. + Save the environment on startup. + Run the scripts tinc-up and tinc-down from a separate function, which + Warnings removal pass: always include config.h first; add a few + Small change to the way the environment is copied. + Use putenv() instead of clumsy do-it-yourself in execute_script. + Do not include the passphrases directory + In execute_script: + Add route.c to the list of source files. + Updated Dutch translation + Build-depends on libtool + Build-Depends on gettext + Final release notes added, also edited release notes for 1.0pre2 to what the announcement on the mailing list looked like. + Wrapped text to 70 (72?) columns for easy reading + Bop version number to 1.0pre3-1 + Updates, updates + Add prototype for destroy_queue + +Wessel Dankers (3): + File added to CABAL (hopefully) + Grrr, recommit + Added architecture section, made a start with the kernel section. + +Version 1.0pre2 May 31 2000 +------------------------------------------------------------------------ + +Ivo Timmermans (56): + Deleted the protocol description. + Perl version of the system startup script. + Only print an error with send_termreq if debug_lvl is 2 or more. + Add check for mpz_powm in libgmp3. + Version 1.0pre1-0.1. + Changed version to 1.0pre2. + Give IP address instead of hex number when connecting tcp socket failed. + Add shlibs control file for the blowfish library. + Inserted useful content. + Add initscript, tincd->tinc. + Add description, better dependancies. + Mention both upstream authors. + tincd->tinc + .deb version number 1.0pre2-0.4. + Updated to newer version. + Exit with zero status if is empty. + Unlimited length in the config file, thanks to Cris van Pelt. + Depend on perl5. + *** empty log message *** + Look if the tap devices exist before bluntly remaking them. + Use the new VpnMask directive to add a route to the rest of the VPN. + This file is generated with dpkg-buildpackage. + Read /etc/tinc/nets.boot to find the networks that have to be started. + Create a default /etc/tinc/nets.boot after installation, containing all directories under /etc/tinc by default. + Version 1.0pre2-0.3 + Don't distribute the file files. + Find networks in instead of . + Include postinst in the distribution. + Errors will not terminate the script or result in a nonzero exit code. + Updated copyright notice. + Fixed typo. + Mask the vpn net with the vpn netmask, route would give an error if the netmask didn't match the net. + When VpnMask is not present in the config file, silently use $MSK as vpnmask. + Add an example of using VpnMask. + Use /etc/tinc/example as a base directory for an example. /etc/tinc/example/README points to /usr/share/doc/tinc/README.Debian. + Create an empty /etc/tinc/nets.boot. + Updated by Lubomir Bulej and Mads Kiilerich: it uses /etc/tinc/nets.boot and the VpnMask directive in the config files. + Internationalization of tinc. + Include intl/ directory in the list of subdirs. + Include system.h and ABOUT-NLS. + Update acconfig.h to include values for gettext inclusion. + Include GNU gettext checks. + Define LOCALEDIR in CFLAGS. + Dutch translation of tinc. + Bounds check for request id (between 0 and 255). + Updated changes list for version 1.0pre2. + Added new configuration directive `Hostnames', which controls the resolving of IP addresses to hostnames. + When a connection is terminated, all hosts that are still connected get notified of the lost connections. + In terminate_connection, only send a notification to hosts that are directly connected to us. (DEL_HOST gets forwarded automatically.) + Only accept an ADD_HOST request for a host that already exists in our conn_list if the nexthop field matches the sender. This is a workaround for older clients. + Include news for 1.0pre2. + Tell about /etc/tinc/nets.boot. + Updated Dutch translation. + Version 1.0pre2-1. + Handle locale settings. + Miscellaneous copyright updates. + +Guus Sliepen (16): + Proxymode removed. + Cleanups. + Changed ping behaviour (backwards compatible). If we don't have any data + Fixed typos. + Test for existence of configured tinc networks. This will also make + Stub for VpnMask config directive. + TODO file reinstated: + VpnMask truely works now. + Typo. + Fixed last typo. Init.d now uses ifconfig command to set both the tap's IP + Documentation updates. Removed all references to configuration variable + Fix for a DoS attack: + Fixed typos. When terminating a connection, it's status is not only set to + Made tinc persistent. If no outgoing connection can be established right + Terminate a connection on any error. Furthermore, disallow del_host, + Only activate a connection upon receiving it's public key if it's an + +Version 1.0pre1 May 08 2000 +------------------------------------------------------------------------ + +Ivo Timmermans (84): + Get rid of the message `zxnrbl\'. + Upon regeneration, free the old encryption key `securely\' by overwriting it. + Kill the parent after any error conditions in detach(). + Ignore SIGCHLD. + New option -D, don't detach. + Moved to version number 1.0. + Only one round of reading bits out of urandom; + Pass the requested size from xmalloc() and xrealloc() on to xalloc_fail_func() + Check for an illegal length of passphrase in read_passphrase(). + Check if stdout is a terminal, if so, print a verbose message. + Default passphrase length of 1024, added -h/--help options. + Submitted by Mads Kiilerich. + New manpage for genauth. + Updated manpages. + Address for bugreports changed to tinc@nl.linux.org. + Include the directory redhat in the build process. + Include genauth.8 in the distribution. + Submitted changes by Mads Kiilerich. + A short notice from Mads Kiilerich. + Keep make dist(dir) happy. + Added cvs-clean. + These files are not needed in release 1.0. + Don't compile in `idea'. + Don't include idea/idea.h. + Don't try to create cipher/idea/Makefile. + The shell script autogen.sh can create all these removed files, but be + s/Gnome/tinc/g + This file is obsolete, most of the ideas are already in echelon. + Remove check for bigendianness. + Don't define HAVE_NAMESPACES and HAVE_STL. + Use `make ChangeLog' to create this file from the CVS logs. + Remove test for GNOME. + Changes largely from Mads Kiilerich. + Added Mads Kiilerich, removed Guus Sliepen. + *** empty log message *** + Generate this Makefile.am from Makefile.am.in. + Contributed by Mads Kiilerich. + Spelling fixes. + Delete all the files that are created by autogen.sh on a `make cvs-clean'. + Propagate CFLAGS from configure to gcc. + Don't include TODO in the dist. + Remove ChangeLog with a `make cvs-clean'. + Initial CVS. + *** empty log message *** + Create a ChangeLog file, automake requires it. + *** empty log message *** + Debug level tweaking. + From Mads Kiilerich. + The make command is in /usr/bin. + Add an entry to dir. + Omit TODO. + Version to 1.0pre1; + Filled in the details, license from libblowfish copied. + Updated version number to 1.0. + Default config file name is tinc.conf, and pidfile is tinc.pid. + More updates wrt. the change from tincd->tinc. + Added `deb' target. + Filled up the protocol structs with unused bytes. + Got rid of the nasty hacks... and replaced it by another one. + Initially, the vpn_mask of a connection is 255.255.255.255 to avoid confusion with lookup_conn. + Replaced check for status.active by status.dataopen in check_network_activity. + New way of handling the meta protocol. + Read public keys the right way (tm). + Removed debug messages. + Read one less byte from an ANS_KEY request. + Send one less byte from an ANS_KEY request. + Protocol fix (ANS_KEY). This breaks 0.3.3 protocol compatibility. + Key forwarding, write one byte extra. + Committed by Lubom�r Bulej. + Updates by Mads Kiilerich. + Committed by Mads Kiilerich. + Fixed meta protocol. + More tincd->tinc updates. + Mentioned new metaprotocol. + Fix a typo, better handling of the info document. (from Mads Kiilerich) + Don't use error.h or error(), put #error in front of cpp errors. + getopt_long() support for platforms that don't have it. + Include stdio.h for fprintf. + More for getopt support. + Check for the existance of libdl. + Don't link in libdl. + Include sys/types.h. + Copied most of the code from the redhat script. + Added semicolons required by bash2 (Mads Kiilerich). + +Guus Sliepen (18): + Added extra checks for desynchronized connection lists. Hopefully this will + Bug found! Wrong pointer was used for handling multiple ADD_HOST requests + Added checkpoints to beginning and ending of every function. + Packet queues fixed. They caused the trouble when resending keys. + Fixed typo and removed some unnecessary variables. + When trying to talk to a host that is in the netmask of a tinc server but + Converted every &variable[0] to variable. + Cleanups: + Removed write_n() function. + Oops! Reference to write_n() removed and changed into neat write() call. + Meta protocol overhaul. Tinc is now incompatible with previous versions, + Fixed small mistake that would prevent forwarding requests. + Previous fix fixed. Meta protocol should be really flawless from now on! + Replaced sprintf() by safer snprintf(), removed possible buffer overflow + Outgoing packets now use network byte order in header. + Fixes typo and UDP network byte order. + Squashed gcc warning. + Added new config variable "ProxyMode". If enabled, all outgoing packets diff --git a/INSTALL b/INSTALL index b42a17a..8865734 100644 --- a/INSTALL +++ b/INSTALL @@ -1,182 +1,368 @@ +Installation Instructions +************************* + + Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software +Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + Basic Installation ================== - These are generic installation instructions. + Briefly, the shell command './configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the 'README' file for +instructions specific to this package. Some packages provide this +'INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. - The `configure' shell script attempts to guess correct values for + The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). +those values to create a 'Makefile' in each directory of the package. +It may also create one or more '.h' files containing system-dependent +definitions. Finally, it creates a shell script 'config.status' that +you can run in the future to recreate the current configuration, and a +file 'config.log' containing compiler output (useful mainly for +debugging 'configure'). + + It can also use an optional file (typically called 'config.cache' and +enabled with '--cache-file=config.cache' or simply '-C') that saves the +results of its tests to speed up reconfiguring. Caching is disabled by +default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. +to figure out how 'configure' could check whether to do them, and mail +diffs or instructions to the address given in the 'README' so they can +be considered for the next release. If you are using the cache, and at +some point 'config.cache' contains results you don't want to keep, you +may remove or edit it. - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. + The file 'configure.ac' (or 'configure.in') is used to create +'configure' by a program called 'autoconf'. You need 'configure.ac' if +you want to change it or regenerate 'configure' using a newer version of +'autoconf'. -The simplest way to compile this package is: + The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + 1. 'cd' to the directory containing the package's source code and type + './configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running 'configure' might take a while. While running, it prints + some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 2. Type 'make' to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with - the package. + 3. Optionally, type 'make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. - 4. Type `make install' to install the programs and any data files and - documentation. + 4. Type 'make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the 'make install' phase executed with root + privileges. - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly + 5. Optionally, type 'make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior 'make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing 'make clean'. To also remove the + files that 'configure' created (so you can compile the package for + a different kind of computer), type 'make distclean'. There is + also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. + 7. Often, you can also type 'make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide 'make + distcheck', which can by used by developers to test that all other + targets like 'make install' and 'make uninstall' work correctly. + This target is generally not run by end users. + Compilers and Options ===================== Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure +the 'configure' script does not know about. Run './configure --help' +for details on some of the pertinent environment variables. -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + You can give 'configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here is +an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. +the 'configure' script. 'configure' automatically checks for the source +code in the directory that 'configure' is in and in '..'. This is known +as a "VPATH" build. - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. + With a non-GNU 'make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use 'make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple '-arch' options to the +compiler but only a single '-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the 'lipo' tool if you have problems. Installation Names ================== - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. + By default, 'make install' installs the package's commands under +'/usr/local/bin', include files under '/usr/local/include', etc. You +can specify an installation prefix other than '/usr/local' by giving +'configure' the option '--prefix=PREFIX', where PREFIX must be an +absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. +pass the option '--exec-prefix=PREFIX' to 'configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. +options like '--bindir=DIR' to specify different values for particular +kinds of files. Run 'configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the default +for these options is expressed in terms of '${prefix}', so that +specifying just '--prefix' will affect all of the other directory +specifications that were not explicitly provided. - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + The most portable way to affect installation locations is to pass the +correct locations to 'configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +'make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, 'make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +'${prefix}'. Any directories that were specified during 'configure', +but not in terms of '${prefix}', must each be overridden at install time +for the entire installation to be relocated. The approach of makefile +variable overrides for each directory variable is required by the GNU +Coding Standards, and ideally causes no recompilation. However, some +platforms have known limitations with the semantics of shared libraries +that end up requiring recompilation when using this method, particularly +noticeable in packages that use GNU Libtool. + + The second method involves providing the 'DESTDIR' variable. For +example, 'make install DESTDIR=/alternate/directory' will prepend +'/alternate/directory' before all installation names. The approach of +'DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of '${prefix}' +at 'configure' time. Optional Features ================= - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving 'configure' the +option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. + + Some packages pay attention to '--enable-FEATURE' options to +'configure', where FEATURE indicates an optional part of the package. +They may also pay attention to '--with-PACKAGE' options, where PACKAGE +is something like 'gnu-as' or 'x' (for the X Window System). The +'README' should mention any '--enable-' and '--with-' options that the package recognizes. - For packages that use the X Window System, `configure' can usually + For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. +you can use the 'configure' options '--x-includes=DIR' and +'--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of 'make' will be. For these packages, running './configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with 'make V=1'; while running './configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with 'make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC +is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX 'make' updates targets which have the same time stamps as their +prerequisites, which makes it generally unusable when shipped generated +files such as 'configure' are involved. Use GNU 'make' instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its '' header file. The option '-nodtk' can be used as a +workaround. If GNU CC is not installed, it is therefore recommended to +try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put '/usr/ucb' early in your 'PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in '/usr/bin'. So, if you need '/usr/ucb' +in your 'PATH', put it _after_ '/usr/bin'. + + On Haiku, software installed for all users goes in '/boot/common', +not '/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common Specifying the System Type ========================== - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: + There may be some features 'configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, 'configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +'--build=TYPE' option. TYPE can either be a short name for the system +type, such as 'sun4', or a canonical name which has the form: + CPU-COMPANY-SYSTEM -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. +where SYSTEM can have one of these forms: - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. + OS + KERNEL-OS + + See the file 'config.sub' for the possible values of each field. If +'config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option '--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with '--host=TYPE'. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. + If you want to set default values for 'configure' scripts to share, +you can create a site shell script called 'config.site' that gives +default values for variables like 'CC', 'cache_file', and 'prefix'. +'configure' looks for 'PREFIX/share/config.site' if it exists, then +'PREFIX/etc/config.site' if it exists. Or, you can set the +'CONFIG_SITE' environment variable to the location of the site script. +A warning: not all 'configure' scripts look for a site script. -Operation Controls +Defining Variables ================== - `configure' recognizes the following options to control how it + Variables not defined in a site shell script can be set in the +environment passed to 'configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the 'configure' command line, using 'VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified 'gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an +Autoconf limitation. Until the limitation is lifted, you can use this +workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +'configure' Invocation +====================== + + 'configure' recognizes the following options to control how it operates. -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. +'--help' +'-h' + Print a summary of all of the options to 'configure', and exit. -`--help' - Print a summary of the options to `configure', and exit. +'--help=short' +'--help=recursive' + Print a summary of the options unique to this package's + 'configure', and exit. The 'short' variant lists options used only + in the top level, while the 'recursive' variant lists options also + present in any nested packages. -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' +'--version' +'-V' + Print the version of Autoconf used to generate the 'configure' script, and exit. -`configure' also accepts some other, not widely useful, options. +'--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally 'config.cache'. FILE defaults to '/dev/null' to + disable caching. + +'--config-cache' +'-C' + Alias for '--cache-file=config.cache'. + +'--quiet' +'--silent' +'-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to '/dev/null' (any error + messages will still be shown). + +'--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + 'configure' can determine that directory automatically. + +'--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: for + more details, including other options available for fine-tuning the + installation locations. + +'--no-create' +'-n' + Run the configure checks, but stop before creating any output + files. + +'configure' also accepts some other, not widely useful, options. Run +'configure --help' for more details. diff --git a/Makefile.am b/Makefile.am index 805c312..8e43fe5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,36 +2,14 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = m4 intl lib src doc po +SUBDIRS = src doc systemd -ACLOCAL_AMFLAGS = +ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = system.h COPYING.README depcomp - -CVS_CREATED = ABOUT-NLS configure aclocal.m4 config.h.in config.guess \ - config.sub install-sh ltconfig ltmain.sh missing mkinstalldirs \ - stamp-h.in m4/Makefile.am ChangeLog po/Makefile.in.in \ - po/tinc.pot src/.libs intl depcomp +EXTRA_DIST = COPYING.README README.android ChangeLog: - cvs2cl -U cvsusers --fsf + git log > ChangeLog -cvs-clean: maintainer-clean - for f in $(CVS_CREATED) `find . -name Makefile.in` tinc-$(VERSION).tar.gz; do\ - rm -Rf "$$f"; \ - done - -deb: - dpkg-buildpackage -rfakeroot - -rpm: dist - cp $(distdir).tar.gz /usr/src/redhat/SOURCES/ - cp redhat/tinc.spec /usr/src/redhat/SOURCES/ - cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec - -release: - rm -f ChangeLog - $(MAKE) ChangeLog - echo "Please edit the NEWS file now..." - /usr/bin/editor NEWS - $(MAKE) dist +astyle: + astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] diff --git a/Makefile.in b/Makefile.in index 46f73d7..2940df5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,8 @@ -# Makefile.in generated automatically by automake 1.5 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. -# 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. @@ -12,179 +13,376 @@ # 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 +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ +build_triplet = @build@ host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INCLUDES = @INCLUDES@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ - -AUTOMAKE_OPTIONS = gnu - -SUBDIRS = m4 intl lib src doc po - -ACLOCAL_AMFLAGS = - -EXTRA_DIST = system.h COPYING.README depcomp - -CVS_CREATED = ABOUT-NLS configure aclocal.m4 config.h.in config.guess \ - config.sub install-sh ltconfig ltmain.sh missing mkinstalldirs \ - stamp-h.in m4/Makefile.am ChangeLog po/Makefile.in.in \ - po/tinc.pot src/.libs intl depcomp - subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = intl/Makefile +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = 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 = README ./stamp-h.in ABOUT-NLS AUTHORS COPYING ChangeLog \ - INSTALL Makefile.am Makefile.in NEWS THANKS TODO acconfig.h \ - aclocal.m4 config.guess config.h.in config.sub configure \ - configure.in install-sh missing mkinstalldirs +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ + COPYING ChangeLog INSTALL NEWS README THANKS compile \ + config.guess config.sub depcomp install-sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = src doc systemd +ACLOCAL_AMFLAGS = -I m4 +EXTRA_DIST = COPYING.README README.android all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && \ - CONFIG_HEADERS= CONFIG_LINKS= \ - CONFIG_FILES=$@ $(SHELL) ./config.status +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; -$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) +$(top_builddir)/config.status: $(top_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 +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ distclean-hdr: - -rm -f config.h -intl/Makefile: $(top_builddir)/config.status $(top_srcdir)/intl/Makefile.in - cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status -uninstall-info-am: + -rm -f config.h stamp-h1 # 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; \ +# 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. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ @@ -192,167 +390,293 @@ $(RECURSIVE_TARGETS): else \ local_target="$$target"; \ fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ 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 +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags -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=; \ +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$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) + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique GTAGS: - here=`CDPATH=: && cd $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am -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)/intl $(distdir)/po - @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; \ +distdir-am: $(DISTFILES) + @case `sed 15q $(srcdir)/NEWS` in \ + *"$(VERSION)"*) : ;; \ + *) \ + echo "NEWS not updated; not releasing" 1>&2; \ + exit 1;; \ + esac + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ - cp -pR $$d/$$file $(distdir) \ - || exit 1; \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done - for subdir in $(SUBDIRS); do \ + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -d $(distdir)/$$subdir \ - || mkdir $(distdir)/$$subdir \ - || exit 1; \ - (cd $$subdir && \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" \ - distdir=../$(distdir)/$$subdir \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done - -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -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) + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_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 + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) - dc_install_base=`CDPATH=: && cd $(distdir)/=inst && pwd` \ - && cd $(distdir)/=build \ - && ../configure --srcdir=.. --prefix=$$dc_install_base \ - --with-included-gettext \ + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --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) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ && $(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' + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: - install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive @@ -363,15 +687,22 @@ install-am: all-am installcheck: installcheck-recursive install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -380,81 +711,98 @@ clean: clean-recursive clean-am: clean-generic 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 + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: +html: html-recursive + +html-am: + info: info-recursive info-am: install-data-am: +install-dvi: install-dvi-recursive + +install-dvi-am: + install-exec-am: +install-html: install-html-recursive + +install-html-am: + install-info: install-info-recursive +install-info-am: + install-man: +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-recursive - + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic -uninstall-am: uninstall-info-am +pdf: pdf-recursive -uninstall-info: uninstall-info-recursive +pdf-am: -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-generic clean-recursive dist dist-all distcheck distclean \ - distclean-generic distclean-hdr 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-recursive tags tags-recursive \ - uninstall uninstall-am uninstall-info-am \ - uninstall-info-recursive uninstall-recursive +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + dist-zstd distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile ChangeLog: - cvs2cl -U cvsusers --fsf + git log > ChangeLog -cvs-clean: maintainer-clean - for f in $(CVS_CREATED) `find . -name Makefile.in` tinc-$(VERSION).tar.gz; do\ - rm -Rf "$$f"; \ - done +astyle: + astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] -deb: - dpkg-buildpackage -rfakeroot - -rpm: dist - cp $(distdir).tar.gz /usr/src/redhat/SOURCES/ - cp redhat/tinc.spec /usr/src/redhat/SOURCES/ - cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec - -release: - rm -f ChangeLog - $(MAKE) ChangeLog - echo "Please edit the NEWS file now..." - /usr/bin/editor NEWS - $(MAKE) dist # 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/NEWS b/NEWS index 0317dd5..c587e87 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,494 @@ +Version 1.0.36 August 26 2019 + + * Fix compiling tinc with certain versions of the OpenSSL library. + * Fix parsing some IPv6 addresses with :: in them. + * Fix GraphDumpFile output to handle node names starting with a digit. + * Fix a potential segmentation fault when fragmenting packets. + +Thanks to Rosen Penev, Quentin Rameau and Werner Schreiber for their +contributions to this version of tinc. + +Version 1.0.35 October 5 2018 + + * Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738). + * Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758). + * Minor fixes in the documentation. + +Thanks to Amine Amri and Rafael Sadowski for their contributions to this +version of tinc. + +Version 1.0.34 June 12 2018 + + * Fix a potential segmentation fault when connecting to an IPv6 peer via a + proxy. + * Minor improvements to the build system. + * Make the systemd service file identical to the one from the 1.1 branch. + * Fix a potential problem causing IPv4 sockets to not work on macOS. + +Thanks to Maximilian Stein and Wang Liu Shuai for their contributions to this +version of tinc. + +Version 1.0.33 November 4 2017 + + * Allow compilation from a build directory. + * Source code cleanups. + * Fix some options specified on the command line not surviving a HUP signal. + * Handle tun/tap device returning EPERM or EBUSY. + * Disable PMTUDiscovery when TCPOnly is used. + * Support the --runstatedir option of the autoconf 2.70. + +Thanks to Rafael Sadowski and Pierre-Olivier Mercier for their contributions to +this version of tinc. + +Version 1.0.32 September 2 2017 + + * Fix segmentation fault when using Cipher = none. + * Fix Proxy = exec. + * Support PriorityInheritance for IPv6 packets. + * Fixes for Solaris tun/tap support. + * Bind outgoing TCP sockets when ListenAddress is used. + +Thanks to Vittorio Gambaletta for his contribution to this version of tinc. + +Version 1.0.31 January 15 2017 + + * Remove ExecStop in tinc@.service. + +Thanks to Élie Bouttier for his contribution to this version of tinc. + +Version 1.0.30 October 30 2016 + + * Fix troubles connecting to some HTTP proxies. + + * Add mitigations for the Sweet32 attack when using a 64-bit block cipher. + + * Use AES256 and SHA256 as the default encryption and digest algorithms. + +Version 1.0.29 October 9 2016 + + * Fix UDP communication with peers with link-local IPv6 addresses. + + * Ensure compatibility with OpenSSL 1.1.0. + + * Ensure autoreconf can be run without requiring autoconf-archive. + + * Log warnings about dropped packets only at debug level 5. + +Version 1.0.28 April 10 2016 + + * Fix compilation on BSD platforms. + + * Add systemd service files. + +Version 1.0.27 April 10 2016 + + * When using Proxy, let the proxy resolve hostnames if tinc can't. + + * Fixes and improvements of the DecrementTTL option. + + * Fixed the $NAME variable in subnet-up/down scripts for the local Subnets. + + * Fixed potentially wrong checksum generation when clamping the MSS. + + * Properly choose between the system's or our own copy of getopt. + + * Fixed compiling tinc for Cygwin with MinGW installed. + + * Added support for OS X utun interfaces. + + * Documentation updates and minor fixes. + +Thanks to Vittorio Gambaletta, LunarShaddow, Florian Weik and Nathan Stratton +Treadway for their contributions to this version of tinc. + +Version 1.0.26 July 5 2015 + + * Tinc now forces glibc to reload /etc/resolv.conf for every hostname lookup. + + * Fixed --logfile without a filename on Windows. + + * Ensure tinc can be compiled when using musl libc. + +Thanks to Jo-Philipp Wich for his contribution to this version of tinc. + +Version 1.0.25 December 22 2014 + + * Documentation updates. + + * Support linking against -lresolv on Mac OS X. + + * Fix scripts on Windows when using the ScriptsInterpreter option. + + * Allow a minimum reconnect timeout to be specified. + + * Support PriorityInheritance on IPv6 sockets. + +Thanks to David Pflug, Baptiste Jonglez, Alexis Hildebrandt, Borg, Jochen Voss, +Tomislav ÄŒohar and VittGam for their contributions to this version of tinc. + +Version 1.0.24 May 11 2014 + + * Various compiler hardening flags are enabled by default. + + * Updated support for Solaris, allowing switch mode on Solaris 11. + + * Configuration will now also be read from a conf.d directory. + + * Various updates to the documentation. + + * Tinc now forces glibc to reload /etc/resolv.conf after it receives SIGALRM. + + * Fixed a potential routing loop when IndirectData or TCPOnly is used and + broadcast packets are being sent. + + * Improved security with constant time memcmp and stricter use of OpenSSL's + RNG functions. + + * Fixed all issues found by Coverity. + +Thanks to Florent Clairambault, Vilbrekin, luckyhacky, Armin Fisslthaler, Loïc +Dachary and Steffan Karger for their contributions to this version of tinc. + +Version 1.0.23 October 19 2013 + + * Start authentication immediately on outgoing connections (useful for sslh). + + * Fixed segfault when Name = $HOST but $HOST is not set. + + * Updated the build system and the documentation. + + * Clean up child processes left over from Proxy = exec. + +Version 1.0.22 August 13 2013 + + * Fixed the combination of Mode = router and DeviceType = tap. + + * The $NAME variable is now set in subnet-up/down scripts. + + * Tinc now gives an error when unknown options are given on the command line. + + * Tinc now correctly handles a space between a short command line option and + an optional argument. + +Thanks to Etienne Dechamps for his contribution to this version of tinc. + +Version 1.0.21 April 22 2013 + + * Drop packets forwarded via TCP if they are too big (CVE-2013-1428). + +Thanks to Martin Schobert for auditing tinc and reporting this vulnerability. + +Version 1.0.20 March 03 2013 + + * Use /dev/tap0 by default on FreeBSD and NetBSD when using switch mode. + + * Minor improvements and clarifications in the documentation. + + * Allow tinc to be cross-compiled with Android's NDK. + + * The discovered PMTU is now also applied to VLAN tagged traffic. + + * The LocalDiscovery option now makes use of all addresses tinc is bound to. + + * Fixed support for tunemu on iOS devices. + + * The PriorityInheritance option now also works with switch mode. + + * Fixed tinc crashing when using a SOCKS5 proxy. + +Thanks to Mesar Hameed, Vilbrekin and Martin Schürrer for their contributions +to this version of tinc. + +Version 1.0.19 June 25 2012 + + * Allow :: notation in IPv6 Subnets. + + * Add support for systemd style socket activation. + + * Allow environment variables to be used for the Name option. + + * Add basic support for SOCKS proxies, HTTP proxies, and proxying through an + external command. + +Thanks to Anthony G. Basile and Michael Tokarev for their contributions to +this version of tinc. + +Version 1.0.18 March 25 2012 + + * Fixed IPv6 in switch mode by turning off DecrementTTL by default. + + * Allow a port number to be specified in BindToAddress, which also allows tinc + to listen on multiple ports. + + * Add support for multicast communication with UML/QEMU/KVM. + +Version 1.0.17 March 10 2012 + + * The DeviceType option can now be used to select dummy, raw socket, UML and + VDE devices without needing to recompile tinc. + + * Allow multiple BindToAddress statements. + + * Decrement TTL value of IPv4 and IPv6 packets. + + * Add LocalDiscovery option allowing tinc to detect peers that are behind the + same NAT. + + * Accept Subnets passed with the -o option when StrictSubnets = yes. + + * Disabling old RSA keys when generating new ones now also works properly on + Windows. + +Thanks to Nick Hibma for his contribution to this version of tinc. + +Version 1.0.16 July 23 2011 + + * Fixed a performance issue with TCP communication under Windows. + + * Fixed code that, during network outages, would cause tinc to exit when it + thought two nodes with identical Names were on the VPN. + +Version 1.0.15 June 24 2011 + + * Improved logging to file. + + * Reduced amount of process wakeups on platforms which support pselect(). + + * Fixed ProcessPriority option under Windows. + +Version 1.0.14 May 8 2011 + + * Fixed reading configuration files that do not end with a newline. Again. + + * Allow arbitrary configuration options being specified on the command line. + + * Allow all options in both tinc.conf and the local host config file. + + * Configurable replay window, UDP send and receive buffers for performance tuning. + + * Try harder to get UDP communication back after falling back to TCP. + + * Initial support for attaching tinc to a VDE switch. + + * DragonFly BSD support. + + * Allow linking with OpenSSL 1.0.0. + + Thanks to Brandon Black, Julien Muchembled, Michael Tokarev, Rumko and Timothy + Redaelli for their contributions to this version of tinc. + +Version 1.0.13 Apr 11 2010 + + * Allow building tinc without LZO and/or Zlib. + + * Clamp MSS of TCP packets in both directions. + + * Experimental StrictSubnets, Forwarding and DirectOnly options, + giving more control over information and packets received from/sent to other + nodes. + + * Ensure tinc never sends symbolic names for ports over the wire. + +Version 1.0.12 Feb 3 2010 + + * Really allow fast roaming of hosts to other nodes in a switched VPN. + + * Fixes missing or incorrect environment variables when calling host-up/down + and subnet-up/down scripts in some cases. + + * Allow port to be specified in Address statements. + + * Clamp MSS of TCP packets to the discovered path MTU. + + * Let two nodes behind NAT learn each others current UDP address and port via + a third node, potentially allowing direct communications in a similar way to + STUN. + +Version 1.0.11 Nov 1 2009 + + * Fixed potential crash when the HUP signal is sent. + + * Fixes handling of weighted Subnets in switch and hub modes, preventing + unnecessary broadcasts. + + * Works around a MinGW bug that caused packets to Windows nodes to always be + sent via TCP. + + * Improvements to the PMTU discovery code, especially on Windows. + + * Use UDP again in certain cases where 1.0.10 was too conservative and fell + back to TCP unnecessarily. + + * Allow fast roaming of hosts to other nodes in a switched VPN. + +Version 1.0.10 Oct 18 2009 + + * Fixed potential crashes during shutdown and (in rare conditions) when other + nodes disconnected from the VPN. + + * Improved NAT handling: tinc now copes with mangled port numbers, and will + automatically fall back to TCP if direct UDP connection between nodes is not + possible. The TCPOnly option should not have to be used anymore. + + * Allow configuration files with CRLF line endings to be read on UNIX. + + * Disable old RSA keys when generating new ones, and raise the default size of + new RSA keys to 2048 bits. + + * Many fixes in the path MTU discovery code, especially when Compression is + being used. + + * Tinc can now drop privileges and/or chroot itself. + + * The TunnelServer code now just ignores information from clients instead of + disconnecting them. + + * Improved performance on Windows by using the new ProcessPriority option and + by making the handling of packets received from the TAP-Win32 adapter more + efficient. + + * Code cleanups: tinc now follows the C99 standard, copyright headers have + been updated to include patch authors, checkpoint tracing and localisation + features have been removed. + + * Support for (jailbroken) iPhone and iPod Touch has been added. + + Thanks to Florian Forster, Grzegorz Dymarek and especially Michael Tokarev for + their contributions to this version of tinc. + +Version 1.0.9 Dec 26 2008 + + * Fixed tinc as a service under Windows 2003. + + * Fixed reading configuration files that do not end with a newline. + + * Fixed crashes in situations where hostnames could not be resolved or hosts + would disconnect at the same time as session keys were exchanged. + + * Improved default settings of tun and tap devices on BSD platforms. + + * Make IPv6 sockets bind only to IPv6 on Linux. + + * Enable path MTU discovery by default. + + * Fixed a memory leak that occurred when connections were closed. + + Thanks to Max Rijevski for his contributions to this version of tinc. + +Version 1.0.8 May 16 2007 + + * Fixed some memory and resource leaks. + + * Made network sockets non-blocking under Windows. + + Thanks to Scott Lamb and "dnk" for their contributions to this version of tinc. + +Version 1.0.7 Jan 5 2007 + + * Fixed a bug that caused slow network speeds on Windows. + + * Fixed a bug that caused tinc unable to write packets to the tun device on + OpenBSD. + +Version 1.0.6 Dec 18 2006 + + * More flexible detection of the LZO libraries when compiling. + + * Fixed a bug where broadcasts in switch and hub modes sometimes would not + work anymore when part of the VPN had become disconnected from the rest. + +version 1.0.5 Nov 14 2006 + + * Lots of small fixes. + + * Broadcast packets no longer grow in size with each hop. This should + fix switch mode (again). + + * Generic host-up and host-down scripts. + + * Optionally dump graph in graphviz format to a file or a script. + + * Support LZO 2.0 and later. + + Thanks to Scott Lamb for his contributions to this version of tinc. + +version 1.0.4 May 4 2005 + + * Fix switch and hub modes. + + * Optionally start scripts when a Subnet becomes (un)reachable. + +version 1.0.3 Nov 11 2004 + +* Show error message when failing to write a PID file. + +* Ignore spaces at end of lines in config files. + +* Fix handling of late packets. + +* Unify BSD tun/tap device handling. This allows IPv6 on tun devices and + anything on tap devices as long as the underlying OS supports it. + +* Handle IPv6 on Solaris tun devices. + +* Allow tinc to work properly under Windows XP SP2. + +* Allow VLAN tagged Ethernet frames in switch and hub mode. + +* Experimental PMTUDiscovery, TunnelServer and BlockingTCP options. + +version 1.0.2 Nov 8 2003 + +* Fix address and hostname resolving under Windows. + +* Remove warnings about non-existing scripts and unsupported address families. + +* Use the event logger under Windows. + +* Fix quoting of filenames and command line arguments under Windows. + +* Strict checks for length incoming network packets and return values of + cryptographic functions, + +* Fix a bug in metadata handling that made the tinc daemon abort. + +version 1.0.1 Aug 14 2003 + +* Allow empty lines in config files. + +* Fix handling of spaces and backslashes in filenames under native Windows. + +* Allow scripts to be executed under native Windows. + +* Update documentation, make it less Linux specific. + +version 1.0 Aug 4 2003 + +* Lots of small bugfixes and code cleanups. + +* Throughput doubled and latency reduced. + +* Added support for LZO compression. + +* No need to set MAC address or disable ARP anymore. + +* Added support for Windows 2000 and XP, both natively and in a Cygwin + environment. + +version 1.0pre8 Sep 16 2002 + +* More fixes for subnets with prefixlength undivisible by 8. + +* Added support for NetBSD and MacOS/X. + +* Switched from undirected graphs to directed graphs to avoid certain race + conditions and improve scalability. + +* Generalized broadcasting and forwarding of protocol messages. + +* Cleanup of source code. + + version 1.0pre7 Apr 7 2002 * Don't do blocking read()s when getting a signal. diff --git a/README b/README index d75d7f6..127cde2 100644 --- a/README +++ b/README @@ -1,10 +1,10 @@ -This is the README file for tinc version 1.0pre7. Installation +This is the README file for tinc version 1.0.36. Installation instructions may be found in the INSTALL file. -tinc is Copyright (C) 1998-2002 by: +tinc is Copyright (C) 1998-2019 by: -Ivo Timmermans , -Guus Sliepen , +Ivo Timmermans, +Guus Sliepen , and others. For a complete list of authors see the AUTHORS file. @@ -31,37 +31,58 @@ launch a denial of service attack by replaying intercepted packets. The current version adds sequence numbers and message authentication codes to prevent such attacks. +On September the 15th of 2003, Peter Gutmann contacted us and showed us a +writeup describing various security issues in several VPN daemons. He showed +that tinc lacks perfect forward security, the connection authentication could +be done more properly, that the sequence number we use as an IV is not the best +practice and that the default length of the HMAC for packets is too short in +his opinion. We do not know of a way to exploit these weaknesses, but these +issues are being addressed in the tinc 1.1 branch. + +The Sweet32 attack affects versions of tinc prior to 1.0.30. + +On September 6th, 2018, Michael Yonly contacted us and provided +proof-of-concept code that allowed a remote attacker to create an +authenticated, one-way connection with a node, and also that there was a +possibility for a man-in-the-middle to force UDP packets from a node to be sent +in plaintext. The first issue was trivial to exploit on tinc versions prior to +1.0.30, but the changes in 1.0.30 to mitigate the Sweet32 attack made this +weakness much harder to exploit. These issues have been fixed in tinc 1.0.35. +The new protocol in the tinc 1.1 branch is not susceptible to these issues. + Cryptography is a hard thing to get right. We cannot make any guarantees. Time, review and feedback are the only things that can prove the security of any cryptographic product. If you wish to review -tinc or give us feedback, you are stronly encouraged to do so. +tinc or give us feedback, you are strongly encouraged to do so. -Changes to configuration file format since 1.0pre5 --------------------------------------------------- +Compatibility +------------- -Some configuration variables have different names now. Most notably "TapDevice" -should be changed into "Device", and "Device" should be changed into -"BindToDevice". +Version 1.0.35 is compatible with 1.0pre8, 1.0 and later, but not with older +versions of tinc. Note that since version 1.0.30, tinc requires all nodes in +the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the +AES256 and SHA256 algorithms. Requirements ------------ -Since 1.0pre3, we use OpenSSL for all cryptographic functions. So you -need to install this library first; grab it from -http://www.openssl.org/. We recommend version 0.9.5 or better. If -this library is not installed on you system, configure will fail. The -manual in doc/tinc.texi contains more detailed information on how to -install this library. +The OpenSSL library is used for all cryptographic functions. You can find it at +https://www.openssl.org/. You will need version 1.0.1 or later with support for +AES256 and SHA256 enabled. If this library is not installed on your system, the +configure script will fail. The manual in doc/tinc.texi contains more detailed +information on how to install this library. Alternatively, you may also use the +LibreSSL library. -Since 1.0pre6, the zlib library is used for optional compression. You need this -library whether or not you plan to enable the compression. You can find it at -http://www.gzip.org/zlib/. Because of a possible exploit in earlier versions we -recommand that you download version 1.1.4 or later. +The zlib library is used for optional compression. You can +find it at https://zlib.net/. Because of a possible exploit in +earlier versions we recommend that you download version 1.1.4 or later. -In order to compile tinc, you will also need autoconf, automake, GNU make, m4 -and gettext. +The LZO library is also used for optional compression. You can +find it at https://www.oberhumer.com/opensource/lzo/. + +In order to compile tinc, you will need a C99 compliant compiler. Features @@ -70,17 +91,7 @@ Features This version of tinc supports multiple virtual networks at once. To use this feature, you may supply a netname via the -n or --net options. The standard locations for the config files will then be -/etc/tinc//. Because of this feature, tinc will send packets -directly to their destinations, instead of to the uplink. If this -behaviour is undesirable (for instance because of firewalls or other -restrictions), please use an older version of tinc (I would recommend -tinc-0.2.19). - -In order to force the kernel to accept received packets, the -destination MAC address will be set to FE:FD:00:00:00:00 upon -reception. The MAC address of the ethertap or tun/tap interface must -also be set to this address. See the manual for more detailed -information. +/etc/tinc//. tincd regenerates its encryption key pairs. It does this on the first activity after the keys have expired. This period is adjustable in the @@ -96,22 +107,27 @@ Since pre5, tinc can operate in several routing modes. The default mode, determine the destination of packets. The other two modes, "switch" and "hub", allow the tinc daemons to work together like a single network switch or hub. This is useful for bridging networks. The latter modes only work properly on -Linux and FreeBSD. +Linux, FreeBSD and Windows. The algorithms used for encryption and generating message authentication codes can now be changed in the configuration files. All cipher and digest algorithms supported by OpenSSL can be used. Useful ciphers are "blowfish" (default), -"bf-ofb", "des", "des3", etcetera. Useful digests are "sha1" (default), "md5", -etcetera. +"bf-ofb", "des", "des3", et cetera. Useful digests are "sha1" (default), "md5", +et cetera. Support for routing IPv6 packets has been added. Just add Subnet lines with IPv6 addresses (without using :: abbreviations) and use ifconfig or ip (from the iproute package) to give the virtual network interface corresponding IPv6 -addresses. Autoconfiguration will not work in router mode. Tunneling IPv6 -packets only works on Linux, FreeBSD and possibly OpenBSD. +addresses. tinc does not provide autoconfiguration for IPv6 hosts. Consider +using radvd or zebra if you need it. + +It is also possible to make tunnels to other tinc daemons over IPv6 networks, +if the operating system supports IPv6. tinc will automatically use both IPv6 +and IPv4 when available, but this can be changed by adding the option +"AddressFamily = ipv4" or "AddressFamily = ipv6" to the tinc.conf file. + +Normally, when started tinc will detach and run in the background. In a native +Windows environment this means tinc will install itself as a service, which will +restart after reboots. To prevent tinc from detaching or running as a service, +use the -D option. -It is also possible to make tunnels to other tinc daemons over IPv6 networks. -In order to enable this feature the option "AddressFamily = any" or -"AddressFamily = ipv6" must be added to the tinc.conf file. The host -configuration files should contain IPv6 addresses for the "Address" variables, -or hostnames which have an AAAA or A6 record. diff --git a/README.android b/README.android new file mode 100644 index 0000000..7925bdb --- /dev/null +++ b/README.android @@ -0,0 +1,25 @@ +Quick how-to cross compile tinc for android (done from $HOME/android/): + +- Download android NDK and setup local ARM toolchain: +wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +tar xfj android-ndk-r9d-linux-x86.tar.bz2 +./android-ndk-r9d/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain + +- Download and cross-compile openSSL for ARM: +wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz +tar xfz openssl-1.0.1h.tar.gz +cd openssl-1.0.1h +./Configure dist +make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib +cd - + +- Clone and cross-compile tinc: +git clone git://tinc-vpn.org/tinc +cd tinc +autoreconf -fsi +CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1g --with-openssl-include=$HOME/android/openssl-1.0.1g/include/ --disable-hardening +make -j5 + +- Strip tincd binary to make it smaller +/tmp/my-android-toolchain/bin/arm-linux-androideabi-strip src/tincd + diff --git a/THANKS b/THANKS index e4cfd6d..a0f7966 100644 --- a/THANKS +++ b/THANKS @@ -1,25 +1,126 @@ -We would like to thank +We would like to thank the following people for their contributions to tinc: - * Hans Bayle (for making some useful coding suggestions and fixing a - bug or two) - * Lubomír Bulej (for the Redhat system init script) - * Wessel Dankers (for the name `tinc' and various suggestions) - * Mads Kiilerich (for finding some bugs and some errors in the - documentation, and for making several suggestions to make it all - more userfriendly, and the Redhat package) - * James MacLean (for fixing several mission critical bugs, and for - giving me a few good ideas, and, most of all, for the wonderful - testing and debugging) - * Robert van der Meulen (early configuration code) - * Cris van Pelt (small fixes) - * Enrique Zanardi (for the Spanish translation) - * Matias Carrasco (for the Spanish translation of the manual) - * Jamie Briggs (for finding a lot of socket leaks) - * Armijn Hemel (for being our very own PR manager) - * Jerome Etienne (for a thorough security analysis of tinc) - * Mark Glines (for his compression patch) +* Alexander Reil and Gemeinde Berg +* Alexander Ried +* Alexis Hildebrandt +* Allesandro Gatti +* Andreas van Cranenburgh +* Andrew Hahn +* Anthony G. Basile +* Armijn Hemel +* Armin Fisslthaler +* Aron Cowan +* Ashish Bajaj +* Baptiste Jonglez +* Borg +* Brandon Black +* Cheng LI +* Cris van Pelt +* Darius Jahandarie +* Dato Simó +* David Pflug +* Delf Eldkraft +* Dennis Joachimsthaler +* dnk +* Егор Палкин +* Élie Bouttier +* Enrique Zanardi +* Erik Tews +* Etienne Dechamps +* Florent Clairambault +* Florian Forster +* Florian Klink +* Florian Weik +* Flynn Marquardt +* Franz Pletz +* Gary Kessler and Claudia Gonzalez +* Grzegorz Dymarek +* Gusariev Oleksandr +* Hans Bayle +* Harvest +* Ivo van Dong +* Ivo Smits +* James Cook +* James MacLean +* Jamie Briggs +* Jan Å tembera +* Jason Harper +* Jason Livesay +* Jasper Krijgsman +* Jelle de Jong +* Jeroen Domburg +* Jeroen Ubbink +* Jerome Etienne +* Jo-Philipp Wich +* Jochen Voss +* Julien Muchembled +* Lavrans Laading +* Loïc Dachary +* Loïc Grenié +* Lubomír Bulej +* luckyhacky +* LunarShaddow +* Mads Kiilerich +* Marc A. Lehmann +* Mark Glines +* Mark Petryk +* Markus Goetz +* Martin Kihlgren +* Martin Schobert +* Martin Schürrer +* Martin Weinelt +* Matias Carrasco +* Max Rijevski +* Menno Smits +* Mesar Hameed +* Michael Taylor +* Michael Tokarev +* Michael Yonli +* Miles Nordin +* Nathan Stratton Treadway +* Murat Donmez +* Nick Hibma +* Nick Patavalis +* Paul Littlefield +* Philipp Babel +* Pierre Emeriaud +* Pierre-Olivier Mercier +* Rafael Wolf +* Rafael Sadowski +* RafaÅ‚ LeÅ›niak +* Rhosyn Celyn +* Robert van der Meulen +* Robert Waniek +* Rumko +* Ryan Miller +* Sam Bryan +* Samuel Thibault +* Saverio Proto +* Scott Lamb +* Steffan Karger +* Stig Fagrell +* Sven-Haegar Koch +* Teemu Kiviniemi +* Thomas Tsiakalakis +* Timothy Redaelli +* Tomasz Fortuna +* Tomislav ÄŒohar +* Tommy Arnkværn +* Tonnerre Lombard +* Ulrich Seifert +* Vil Brekin +* Vincent Laurent +* Vittorio Gambaletta +* Wendy Willard +* Wessel Dankers +* William A. Kennington III +* William McArthur +* Wouter van Heyst +* xentec +* 戴 鸣 -for their help, support and ideas. Thank you guys! +And everyone we forgot (if we did, please let us know). Thank you! -Ivo Timmermans -Guus Sliepen +--- +Ivo Timmermans, +Guus Sliepen. diff --git a/TODO b/TODO deleted file mode 100644 index c0f2ee3..0000000 --- a/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO LIST - -1.0: - -* A nice, secure and stable release diff --git a/acconfig.h b/acconfig.h deleted file mode 100644 index 41fdb99..0000000 --- a/acconfig.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Define to the name name of this package */ -#undef PACKAGE - -/* Define to the version of the package */ -#undef VERSION - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc - -/* Define to rpl_realloc if the replacement function should be used. */ -#undef realloc - -/* This is always defined. It enables GNU extensions on systems that - have them. */ -#if !defined(_GNU_SOURCE) -# undef _GNU_SOURCE -#endif - -#if !defined(__USE_BSD) -# undef __USE_BSD -#endif - - -/* Define to 1 if NLS is requested. */ -#undef ENABLE_NLS - -/* Define as 1 if you have catgets and don't want to use GNU gettext. */ -#undef HAVE_CATGETS - -/* Define as 1 if you have gettext and don't want to use GNU gettext. */ -#undef HAVE_GETTEXT - -/* Define if your locale.h file contains LC_MESSAGES. */ -#undef HAVE_LC_MESSAGES - -/* Define to 1 if you have the stpcpy function. */ -#undef HAVE_STPCPY - -/* For getopt */ -#if HAVE_STDLIB_H -# define getopt system_getopt -# include -# undef getopt -#endif - -/* Linux */ -#undef HAVE_LINUX - -/* FreeBSD */ -#undef HAVE_FREEBSD - -/* OpenBSD */ -#undef HAVE_OPENBSD - -/* Solaris */ -#undef HAVE_SOLARIS - -/* NetBSD */ -#undef HAVE_NETBSD - -/* Define to the location of the kernel sources */ -#undef CONFIG_TINC_KERNELDIR - -/* Define to 1 if tun/tap support is enabled and found */ -#undef HAVE_TUNTAP - -/* Define to the location of if_tun.h */ -#undef LINUX_IF_TUN_H - -/* Define to 1 if support for jumbograms is enabled */ -#undef ENABLE_JUMBOGRAMS - -/* Define to 1 if checkpoint tracing is enabled */ -#undef ENABLE_TRACING - -/* Define to enable use of old SSLeay_add_all_algorithms() function */ -#undef HAVE_SSLEAY_ADD_ALL_ALGORITHMS diff --git a/aclocal.m4 b/aclocal.m4 index 46a4f8c..a50e7c2 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,7 +1,7 @@ -# aclocal.m4 generated automatically by aclocal 1.5 +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. -# 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. @@ -11,176 +11,62 @@ # 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. +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# serial 5 +# Copyright (C) 2002-2020 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. -# 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 +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.16' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.16.2], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.16.2])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # -# 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 +# 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. # 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/../..'. +# $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 @@ -199,7 +85,7 @@ fi # # 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 +# 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, @@ -216,47 +102,63 @@ fi # 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` +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`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)]) +# AM_CONDITIONAL -*- Autoconf -*- -# 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])]) +# Copyright (C) 1997-2020 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. -# serial 4 -*- Autoconf -*- +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2020 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. - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# 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". +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # 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 @@ -269,11 +171,13 @@ 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=]) +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$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], @@ -281,49 +185,103 @@ AC_CACHE_CHECK([dependency style of $depcc], # 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'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir 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 + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub 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 + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # # 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 + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # 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. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # 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 ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; 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 && + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - am_cv_$1_dependencies_compiler_type=$depmode - break + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi fi done @@ -333,1076 +291,856 @@ else am_cv_$1_dependencies_compiler_type=none fi ]) -$1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type" -AC_SUBST([$1DEPMODE]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES +# 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) +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # 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]) +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' + am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -pushdef([subst], defn([AC_SUBST])) -subst(AMDEPBACKSLASH) -popdef([subst]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl ]) -# Generate code to set up dependency tracking. -# This macro should only be invoked once -- use via AC_REQUIRE. -# Usage: -# AM_OUTPUT_DEPENDENCY_COMMANDS +# Generate code to set up dependency tracking. -*- Autoconf -*- +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # -# 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" +# 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. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done -done -], [AMDEP_TRUE="$AMDEP_TRUE" -ac_aux_dir="$ac_aux_dir"])]) + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS -# 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 + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2020 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 macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O ]) -# serial 3 +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi -# 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]) +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) -# Like AC_CONFIG_HEADER, but automatically create stamp file. +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl -# serial 3 +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # 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 "/". +# that is generated. The stamp files are numbered to have different names. -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 - ;; +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac - am_indx=\`expr \$am_indx + 1\` -done]) -])]) # AM_CONFIG_HEADER +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# _AM_DIRNAME(PATH) +# Copyright (C) 2001-2020 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2020 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. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2020 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. + +# AM_MAKE_INCLUDE() # ----------------- -# 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 +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) -# aclocal-include.m4 -# -# This macro adds the name macrodir to the set of directories -# that `aclocal' searches for macros. +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# serial 1 +# Copyright (C) 1997-2020 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. -dnl AM_ACLOCAL_INCLUDE(macrodir) -AC_DEFUN([AM_ACLOCAL_INCLUDE], -[ - test -n "$ACLOCAL_FLAGS" && ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" +# 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)]) - for k in $1 ; do ACLOCAL="$ACLOCAL -I $k" ; done +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi ]) -#serial 1 +# Helper functions for option handling. -*- Autoconf -*- -dnl From Jim Meyering. -dnl Find a new-enough version of Perl. -dnl +# Copyright (C) 2001-2020 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. -AC_DEFUN(jm_PERL, -[ - dnl FIXME: don't hard-code 5.003 - dnl FIXME: should we cache the result? - AC_MSG_CHECKING([for perl5.003 or newer]) - if test "${PERL+set}" = set; then - # `PERL' is set in the user's environment. - candidate_perl_names="$PERL" - perl_specified=yes - else - candidate_perl_names='perl perl5' - perl_specified=no - fi +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - found=no - AC_SUBST(PERL) - PERL="$missing_dir/missing perl" - for perl in $candidate_perl_names; do - # Run test in a subshell; some versions of sh will print an error if - # an executable is not found, even if stderr is redirected. - if ( $perl -e 'require 5.003' ) > /dev/null 2>&1; then - PERL=$perl - found=yes +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2020 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. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no break fi done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) - AC_MSG_RESULT($found) - test $found = no && AC_MSG_WARN([ -*** You don't seem to have perl5.003 or newer installed. -*** Because of that, you may be unable to regenerate certain files -*** if you modify the sources from which they are derived.] ) -]) +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -#serial 1 -# This test replaces the one in autoconf. -# Currently this macro should have the same name as the autoconf macro -# because gettext's gettext.m4 (distributed in the automake package) -# still uses it. Otherwise, the use in gettext.m4 makes autoheader -# give these diagnostics: -# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX -# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX - -undefine([AC_ISC_POSIX]) - -AC_DEFUN([AC_ISC_POSIX], - [ - dnl This test replaces the obsolescent AC_ISC_POSIX kludge. - AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) - ] -) - -#serial 1 - -dnl From Jim Meyering. -dnl Determine whether malloc accepts 0 as its argument. -dnl If it doesn't, arrange to use the replacement function. -dnl -dnl If you use this macro in a package, you should -dnl add the following two lines to acconfig.h: -dnl /* Define to rpl_malloc if the replacement function should be used. */ -dnl #undef malloc -dnl - -AC_DEFUN(jm_FUNC_MALLOC, -[ - if test x = y; then - dnl This code is deliberately never run via ./configure. - dnl FIXME: this is a gross hack to make autoheader put an entry - dnl for this symbol in config.h.in. - AC_CHECK_FUNCS(DONE_WORKING_MALLOC_CHECK) - fi - dnl xmalloc.c requires that this symbol be defined so it doesn't - dnl mistakenly use a broken malloc -- as it might if this test were omitted. - ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK - AC_DEFINE_UNQUOTED($ac_kludge) - - AC_CACHE_CHECK([for working malloc], jm_cv_func_working_malloc, - [AC_TRY_RUN([ - char *malloc (); - int - main () - { - exit (malloc (0) ? 0 : 1); - } - ], - jm_cv_func_working_malloc=yes, - jm_cv_func_working_malloc=no, - dnl When crosscompiling, assume malloc is broken. - jm_cv_func_working_malloc=no) - ]) - if test $jm_cv_func_working_malloc = no; then - LIBOBJS="$LIBOBJS malloc.o" - AC_DEFINE_UNQUOTED(malloc, rpl_malloc) - fi -]) - -#serial 1 - -dnl From Jim Meyering. -dnl Determine whether realloc works when both arguments are 0. -dnl If it doesn't, arrange to use the replacement function. -dnl -dnl If you use this macro in a package, you should -dnl add the following two lines to acconfig.h: -dnl /* Define to rpl_realloc if the replacement function should be used. */ -dnl #undef realloc -dnl - -AC_DEFUN(jm_FUNC_REALLOC, -[ - if test x = y; then - dnl This code is deliberately never run via ./configure. - dnl FIXME: this is a gross hack to make autoheader put an entry - dnl for this symbol in config.h.in. - AC_CHECK_FUNCS(DONE_WORKING_REALLOC_CHECK) - fi - dnl xmalloc.c requires that this symbol be defined so it doesn't - dnl mistakenly use a broken realloc -- as it might if this test were omitted. - ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK - AC_DEFINE_UNQUOTED($ac_kludge) - - AC_CACHE_CHECK([for working realloc], jm_cv_func_working_realloc, - [AC_TRY_RUN([ - char *realloc (); - int - main () - { - exit (realloc (0, 0) ? 0 : 1); - } - ], - jm_cv_func_working_realloc=yes, - jm_cv_func_working_realloc=no, - dnl When crosscompiling, assume realloc is broken. - jm_cv_func_working_realloc=no) - ]) - if test $jm_cv_func_working_realloc = no; then - LIBOBJS="$LIBOBJS realloc.o" - AC_DEFINE_UNQUOTED(realloc, rpl_realloc) - fi -]) - -# Macro to add for using GNU gettext. -# Ulrich Drepper , 1995. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # -# This file can be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public -# License or the GNU Library General Public License but which still want -# to provide support for the GNU gettext functionality. -# Please note that the actual code of the GNU gettext library is covered -# by the GNU Library General Public License, and the rest of the GNU -# gettext package package is covered by the GNU General Public License. -# They are *not* in the public domain. +# 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. -# serial 10 +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) -dnl Usage: AM_WITH_NLS([TOOLSYMBOL], [NEEDSYMBOL], [LIBDIR]). -dnl If TOOLSYMBOL is specified and is 'use-libtool', then a libtool library -dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, -dnl depending on --{enable,disable}-{shared,static} and on the presence of -dnl AM-DISABLE-SHARED). Otherwise, a static library -dnl $(top_builddir)/intl/libintl.a will be created. -dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext -dnl implementations (in libc or libintl) without the ngettext() function -dnl will be ignored. -dnl LIBDIR is used to find the intl libraries. If empty, -dnl the value `$(top_builddir)/intl/' is used. -dnl -dnl The result of the configuration is one of three cases: -dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled -dnl and used. -dnl Catalog format: GNU --> install in $(datadir) -dnl Catalog extension: .mo after installation, .gmo in source tree -dnl 2) GNU gettext has been found in the system's C library. -dnl Catalog format: GNU --> install in $(datadir) -dnl Catalog extension: .mo after installation, .gmo in source tree -dnl 3) No internationalization, always use English msgid. -dnl Catalog format: none -dnl Catalog extension: none -dnl The use of .gmo is historical (it was needed to avoid overwriting the -dnl GNU format catalogs when building on a platform with an X/Open gettext), -dnl but we keep it in order not to force irrelevant filename changes on the -dnl maintainers. -dnl -AC_DEFUN([AM_WITH_NLS], - [AC_MSG_CHECKING([whether NLS is requested]) - dnl Default is enabled NLS - AC_ARG_ENABLE(nls, - [ --disable-nls do not use Native Language Support], - USE_NLS=$enableval, USE_NLS=yes) - AC_MSG_RESULT($USE_NLS) - AC_SUBST(USE_NLS) +# Check to make sure that the build environment is sane. -*- Autoconf -*- - BUILD_INCLUDED_LIBINTL=no - USE_INCLUDED_LIBINTL=no - INTLLIBS= - - dnl If we use NLS figure out what method - if test "$USE_NLS" = "yes"; then - AC_DEFINE(ENABLE_NLS, 1, - [Define to 1 if translation of program messages to the user's native language - is requested.]) - AC_MSG_CHECKING([whether included gettext is requested]) - AC_ARG_WITH(included-gettext, - [ --with-included-gettext use the GNU gettext library included here], - nls_cv_force_use_gnu_gettext=$withval, - nls_cv_force_use_gnu_gettext=no) - AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) - - nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" - if test "$nls_cv_force_use_gnu_gettext" != "yes"; then - dnl User does not insist on using GNU NLS library. Figure out what - dnl to use. If GNU gettext is available we use this. Else we have - dnl to fall back to GNU NLS library. - CATOBJEXT=NONE - - dnl Add a version number to the cache macros. - define(gt_cv_func_gnugettext_libc, [gt_cv_func_gnugettext]ifelse([$2], need-ngettext, 2, 1)[_libc]) - define(gt_cv_func_gnugettext_libintl, [gt_cv_func_gnugettext]ifelse([$2], need-ngettext, 2, 1)[_libintl]) - - AC_CHECK_HEADER(libintl.h, - [AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, - [AC_TRY_LINK([#include -extern int _nl_msg_cat_cntr;], - [bindtextdomain ("", ""); -return (int) gettext ("")]ifelse([$2], need-ngettext, [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr], - gt_cv_func_gnugettext_libc=yes, - gt_cv_func_gnugettext_libc=no)]) - - if test "$gt_cv_func_gnugettext_libc" != "yes"; then - AC_CACHE_CHECK([for GNU gettext in libintl], - gt_cv_func_gnugettext_libintl, - [gt_save_LIBS="$LIBS" - LIBS="$LIBS -lintl $LIBICONV" - AC_TRY_LINK([#include -extern int _nl_msg_cat_cntr;], - [bindtextdomain ("", ""); -return (int) gettext ("")]ifelse([$2], need-ngettext, [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr], - gt_cv_func_gnugettext_libintl=yes, - gt_cv_func_gnugettext_libintl=no) - LIBS="$gt_save_LIBS"]) - fi - - dnl If an already present or preinstalled GNU gettext() is found, - dnl use it. But if this macro is used in GNU gettext, and GNU - dnl gettext is already preinstalled in libintl, we update this - dnl libintl. (Cf. the install rule in intl/Makefile.in.) - if test "$gt_cv_func_gnugettext_libc" = "yes" \ - || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ - && test "$PACKAGE" != gettext; }; then - AC_DEFINE(HAVE_GETTEXT, 1, - [Define if the GNU gettext() function is already present or preinstalled.]) - - if test "$gt_cv_func_gnugettext_libintl" = "yes"; then - dnl If iconv() is in a separate libiconv library, then anyone - dnl linking with libintl{.a,.so} also needs to link with - dnl libiconv. - INTLLIBS="-lintl $LIBICONV" - fi - - gt_save_LIBS="$LIBS" - LIBS="$LIBS $INTLLIBS" - AC_CHECK_FUNCS(dcgettext) - LIBS="$gt_save_LIBS" - - dnl Search for GNU msgfmt in the PATH. - AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, - [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1], :) - AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) - - dnl Search for GNU xgettext in the PATH. - AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, - [$ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1], :) - - CATOBJEXT=.gmo - fi - ]) - - if test "$CATOBJEXT" = "NONE"; then - dnl GNU gettext is not found in the C library. - dnl Fall back on GNU gettext library. - nls_cv_use_gnu_gettext=yes - fi - fi - - if test "$nls_cv_use_gnu_gettext" = "yes"; then - dnl Mark actions used to generate GNU NLS library. - INTLOBJS="\$(GETTOBJS)" - AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, - [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1], :) - AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) - AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, - [$ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1], :) - AC_SUBST(MSGFMT) - BUILD_INCLUDED_LIBINTL=yes - USE_INCLUDED_LIBINTL=yes - CATOBJEXT=.gmo - INTLLIBS="ifelse([$3],[],\$(top_builddir)/intl,[$3])/libintl.ifelse([$1], use-libtool, [l], [])a $LIBICONV" - LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` - fi - - dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. - dnl Test whether we really found GNU msgfmt. - if test "$GMSGFMT" != ":"; then - dnl If it is no GNU msgfmt we define it as : so that the - dnl Makefiles still can work. - if $GMSGFMT --statistics /dev/null >/dev/null 2>&1; then - : ; - else - AC_MSG_RESULT( - [found msgfmt program is not GNU msgfmt; ignore it]) - GMSGFMT=":" - fi - fi - - dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. - dnl Test whether we really found GNU xgettext. - if test "$XGETTEXT" != ":"; then - dnl If it is no GNU xgettext we define it as : so that the - dnl Makefiles still can work. - if $XGETTEXT --omit-header /dev/null >/dev/null 2>&1; then - : ; - else - AC_MSG_RESULT( - [found xgettext program is not GNU xgettext; ignore it]) - XGETTEXT=":" - fi - fi - - dnl We need to process the po/ directory. - POSUB=po - fi - AC_OUTPUT_COMMANDS( - [for ac_file in $CONFIG_FILES; do - # Support "outfile[:infile[:infile...]]" - case "$ac_file" in - *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - esac - # PO directories have a Makefile.in generated from Makefile.in.in. - case "$ac_file" in */Makefile.in) - # Adjust a relative srcdir. - ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" - ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` - # In autoconf-2.13 it is called $ac_given_srcdir. - # In autoconf-2.50 it is called $srcdir. - test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" - case "$ac_given_srcdir" in - .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; - /*) top_srcdir="$ac_given_srcdir" ;; - *) top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then - rm -f "$ac_dir/POTFILES" - test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" - sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," -e "\$s/\(.*\) \\\\/\1/" < "$ac_given_srcdir/$ac_dir/POTFILES.in" > "$ac_dir/POTFILES" - test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" - sed -e "/POTFILES =/r $ac_dir/POTFILES" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" - fi - ;; - esac - done]) - - - dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL - dnl to 'yes' because some of the testsuite requires it. - if test "$PACKAGE" = gettext; then - BUILD_INCLUDED_LIBINTL=yes - fi - - dnl intl/plural.c is generated from intl/plural.y. It requires bison, - dnl because plural.y uses bison specific features. It requires at least - dnl bison-1.26 because earlier versions generate a plural.c that doesn't - dnl compile. - dnl bison is only needed for the maintainer (who touches plural.y). But in - dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put - dnl the rule in general Makefile. Now, some people carelessly touch the - dnl files or have a broken "make" program, hence the plural.c rule will - dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not - dnl present or too old. - AC_CHECK_PROGS([INTLBISON], [bison]) - if test -z "$INTLBISON"; then - ac_verc_fail=yes - else - dnl Found it, now check the version. - AC_MSG_CHECKING([version of bison]) -changequote(<<,>>)dnl - ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` - case $ac_prog_version in - '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; - 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) -changequote([,])dnl - ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; - *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; - esac - AC_MSG_RESULT([$ac_prog_version]) - fi - if test $ac_verc_fail = yes; then - INTLBISON=: - fi - - dnl These rules are solely for the distribution goal. While doing this - dnl we only have to keep exactly one list of the available catalogs - dnl in configure.in. - for lang in $ALL_LINGUAS; do - GMOFILES="$GMOFILES $lang.gmo" - POFILES="$POFILES $lang.po" - done - - dnl Make all variables we use known to autoconf. - AC_SUBST(BUILD_INCLUDED_LIBINTL) - AC_SUBST(USE_INCLUDED_LIBINTL) - AC_SUBST(CATALOGS) - AC_SUBST(CATOBJEXT) - AC_SUBST(GMOFILES) - AC_SUBST(INTLLIBS) - AC_SUBST(INTLOBJS) - AC_SUBST(POFILES) - AC_SUBST(POSUB) - - dnl For backward compatibility. Some configure.ins may be using this. - nls_cv_header_intl= - nls_cv_header_libgt= - - dnl For backward compatibility. Some Makefiles may be using this. - DATADIRNAME=share - AC_SUBST(DATADIRNAME) - - dnl For backward compatibility. Some Makefiles may be using this. - INSTOBJEXT=.mo - AC_SUBST(INSTOBJEXT) - - dnl For backward compatibility. Some Makefiles may be using this. - GENCAT=gencat - AC_SUBST(GENCAT) - ]) - -dnl Usage: Just like AM_WITH_NLS, which see. -AC_DEFUN([AM_GNU_GETTEXT], - [AC_REQUIRE([AC_PROG_MAKE_SET])dnl - AC_REQUIRE([AC_PROG_CC])dnl - AC_REQUIRE([AC_CANONICAL_HOST])dnl - AC_REQUIRE([AC_PROG_RANLIB])dnl - AC_REQUIRE([AC_ISC_POSIX])dnl - AC_REQUIRE([AC_HEADER_STDC])dnl - AC_REQUIRE([AC_C_CONST])dnl - AC_REQUIRE([AC_C_INLINE])dnl - AC_REQUIRE([AC_TYPE_OFF_T])dnl - AC_REQUIRE([AC_TYPE_SIZE_T])dnl - AC_REQUIRE([AC_FUNC_ALLOCA])dnl - AC_REQUIRE([AC_FUNC_MMAP])dnl - AC_REQUIRE([jm_GLIBC21])dnl - - AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ -stdlib.h string.h unistd.h sys/param.h]) - AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getcwd getegid geteuid \ -getgid getuid mempcpy munmap putenv setenv setlocale stpcpy strchr strcasecmp \ -strdup strtoul tsearch __argz_count __argz_stringify __argz_next]) - - AM_ICONV - AM_LANGINFO_CODESET - AM_LC_MESSAGES - AM_WITH_NLS([$1],[$2],[$3]) - - if test "x$CATOBJEXT" != "x"; then - if test "x$ALL_LINGUAS" = "x"; then - LINGUAS= - else - AC_MSG_CHECKING(for catalogs to be installed) - NEW_LINGUAS= - for presentlang in $ALL_LINGUAS; do - useit=no - for desiredlang in ${LINGUAS-$ALL_LINGUAS}; do - # Use the presentlang catalog if desiredlang is - # a. equal to presentlang, or - # b. a variant of presentlang (because in this case, - # presentlang can be used as a fallback for messages - # which are not translated in the desiredlang catalog). - case "$desiredlang" in - "$presentlang"*) useit=yes;; - esac - done - if test $useit = yes; then - NEW_LINGUAS="$NEW_LINGUAS $presentlang" - fi - done - LINGUAS=$NEW_LINGUAS - AC_MSG_RESULT($LINGUAS) - fi - - dnl Construct list of names of catalog files to be constructed. - if test -n "$LINGUAS"; then - for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done - fi - fi - - dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly - dnl find the mkinstalldirs script in another subdir but $(top_srcdir). - dnl Try to locate is. - MKINSTALLDIRS= - if test -n "$ac_aux_dir"; then - MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" - fi - if test -z "$MKINSTALLDIRS"; then - MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" - fi - AC_SUBST(MKINSTALLDIRS) - - dnl Enable libtool support if the surrounding package wishes it. - INTL_LIBTOOL_SUFFIX_PREFIX=ifelse([$1], use-libtool, [l], []) - AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) - ]) - -# Search path for a program which passes the given test. -# Ulrich Drepper , 1996. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # -# This file can be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public -# License or the GNU Library General Public License but which still want -# to provide support for the GNU gettext functionality. -# Please note that the actual code of the GNU gettext library is covered -# by the GNU Library General Public License, and the rest of the GNU -# gettext package package is covered by the GNU General Public License. -# They are *not* in the public domain. +# 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. -# serial 2 +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac -dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, -dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) -AC_DEFUN([AM_PATH_PROG_WITH_TEST], -[# Extract the first word of "$2", so it can be a program name with args. -set dummy $2; ac_word=[$]2 -AC_MSG_CHECKING([for $ac_word]) -AC_CACHE_VAL(ac_cv_path_$1, -[case "[$]$1" in - /*) - ac_cv_path_$1="[$]$1" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in ifelse([$5], , $PATH, [$5]); do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if [$3]; then - ac_cv_path_$1="$ac_dir/$ac_word" - break +# 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 ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + 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 + 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 + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + 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]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2020 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. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2020 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# 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 +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2020 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2020 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. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done - IFS="$ac_save_ifs" -dnl If no 4th arg is given, leave the cache variable unset, -dnl so AC_PATH_PROGS will keep looking. -ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" -])dnl - ;; -esac])dnl -$1="$ac_cv_path_$1" -if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then - AC_MSG_RESULT([$]$1) -else - AC_MSG_RESULT(no) -fi -AC_SUBST($1)dnl -]) + rm -rf conftest.dir -#serial 2 + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) -# Test for the GNU C Library, version 2.1 or newer. -# From Bruno Haible. - -AC_DEFUN([jm_GLIBC21], - [ - AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, - ac_cv_gnu_library_2_1, - [AC_EGREP_CPP([Lucky GNU user], - [ -#include -#ifdef __GNU_LIBRARY__ - #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) - Lucky GNU user - #endif -#endif - ], - ac_cv_gnu_library_2_1=yes, - ac_cv_gnu_library_2_1=no) - ] - ) - AC_SUBST(GLIBC21) - GLIBC21="$ac_cv_gnu_library_2_1" - ] -) - -#serial AM2 - -dnl From Bruno Haible. - -AC_DEFUN([AM_ICONV], -[ - dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and - dnl those with the standalone portable GNU libiconv installed). - - AC_ARG_WITH([libiconv-prefix], -[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [ - for dir in `echo "$withval" | tr : ' '`; do - if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi - if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi - done - ]) - - AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ - am_cv_func_iconv="no, consider installing GNU libiconv" - am_cv_lib_iconv=no - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_func_iconv=yes) - if test "$am_cv_func_iconv" != yes; then - am_save_LIBS="$LIBS" - LIBS="$LIBS -liconv" - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_lib_iconv=yes - am_cv_func_iconv=yes) - LIBS="$am_save_LIBS" - fi - ]) - if test "$am_cv_func_iconv" = yes; then - AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) - AC_MSG_CHECKING([for iconv declaration]) - AC_CACHE_VAL(am_cv_proto_iconv, [ - AC_TRY_COMPILE([ -#include -#include -extern -#ifdef __cplusplus -"C" -#endif -#if defined(__STDC__) || defined(__cplusplus) -size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); -#else -size_t iconv(); -#endif -], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") - am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) - am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` - AC_MSG_RESULT([$]{ac_t:- - }[$]am_cv_proto_iconv) - AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, - [Define as const if the declaration of iconv() needs const.]) - fi - LIBICONV= - if test "$am_cv_lib_iconv" = yes; then - LIBICONV="-liconv" - fi - AC_SUBST(LIBICONV) -]) - -#serial AM1 - -dnl From Bruno Haible. - -AC_DEFUN([AM_LANGINFO_CODESET], -[ - AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, - [AC_TRY_LINK([#include ], - [char* cs = nl_langinfo(CODESET);], - am_cv_langinfo_codeset=yes, - am_cv_langinfo_codeset=no) - ]) - if test $am_cv_langinfo_codeset = yes; then - AC_DEFINE(HAVE_LANGINFO_CODESET, 1, - [Define if you have and nl_langinfo(CODESET).]) - fi -]) - -# Check whether LC_MESSAGES is available in . -# Ulrich Drepper , 1995. -# -# This file can be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public -# License or the GNU Library General Public License but which still want -# to provide support for the GNU gettext functionality. -# Please note that the actual code of the GNU gettext library is covered -# by the GNU Library General Public License, and the rest of the GNU -# gettext package package is covered by the GNU General Public License. -# They are *not* in the public domain. - -# serial 2 - -AC_DEFUN([AM_LC_MESSAGES], - [if test $ac_cv_header_locale_h = yes; then - AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, - [AC_TRY_LINK([#include ], [return LC_MESSAGES], - am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) - if test $am_cv_val_LC_MESSAGES = yes; then - AC_DEFINE(HAVE_LC_MESSAGES, 1, - [Define if your file defines LC_MESSAGES.]) - fi - fi]) - -dnl Check to find out whether the running kernel has support for TUN/TAP - -AC_DEFUN(tinc_TUNTAP, -[ -AC_ARG_WITH(kernel, - [ --with-kernel=dir give the directory with kernel sources] - [ (default: /usr/src/linux)], - kerneldir="$withval", - kerneldir="/usr/src/linux" -) - -AC_CACHE_CHECK([for linux/if_tun.h], tinc_cv_linux_if_tun_h, -[ - AC_TRY_COMPILE([#include "$kerneldir/include/linux/if_tun.h"], - [int a = IFF_TAP;], - if_tun_h="\"$kerneldir/include/linux/if_tun.h\"", - [AC_TRY_COMPILE([#include ], - [int a = IFF_TAP;], - if_tun_h="default", - if_tun_h="no" - )] - ) - - if test $if_tun_h = no; then - tinc_cv_linux_if_tun_h=none - else - tinc_cv_linux_if_tun_h="$if_tun_h" - fi -]) - -if test $tinc_cv_linux_if_tun_h != none; then - AC_DEFINE(HAVE_TUNTAP) - if test $tinc_cv_linux_if_tun_h != default; then - AC_DEFINE_UNQUOTED(LINUX_IF_TUN_H, $tinc_cv_linux_if_tun_h) - fi -fi -AC_SUBST(LINUX_IF_TUN_H) -AC_SUBST(HAVE_TUNTAP) -]) - -dnl Check to find the OpenSSL headers/libraries - -AC_DEFUN(tinc_OPENSSL, -[ - tinc_ac_save_CPPFLAGS="$CPPFLAGS" - - AC_ARG_WITH(openssl-include, - [ --with-openssl-include=DIR OpenSSL headers directory (without trailing /openssl)], - [openssl_include="$withval" - CFLAGS="$CFLAGS -I$withval" - CPPFLAGS="$CPPFLAGS -I$withval"] - ) - - AC_ARG_WITH(openssl-lib, - [ --with-openssl-lib=DIR OpenSSL library directory], - [openssl_lib="$withval" - LIBS="$LIBS -L$withval"] - ) - - AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h, - [], - [AC_MSG_ERROR("OpenSSL header files not found."); break] - ) - - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - AC_CHECK_LIB(crypto, SHA1_version, - [LIBS="$LIBS -lcrypto"], - [AC_MSG_ERROR("OpenSSL libraries not found.")] - ) - - AC_CHECK_FUNCS(RAND_pseudo_bytes) - - AC_CHECK_FUNC(OpenSSL_add_all_algorithms, - [], - AC_CHECK_FUNC(SSLeay_add_all_algorithms, - [AC_DEFINE(HAVE_SSLEAY_ADD_ALL_ALGORITHMS)], - [AC_MSG_ERROR("Missing required OpenSSL functionality!")] - ) - ) - - AC_CHECK_FUNC(dlopen, - [], - AC_CHECK_LIB(dl, dlopen, - [LIBS="$LIBS -ldl"], - [AC_MSG_ERROR("OpenSSL depends on libdl.")] - ) - ) -]) - -dnl Check to find the zlib headers/libraries - -AC_DEFUN(tinc_ZLIB, -[ - tinc_ac_save_CPPFLAGS="$CPPFLAGS" - - AC_ARG_WITH(zlib-include, - [ --with-zlib-include=DIR zlib headers directory], - [zlib_include="$withval" - CFLAGS="$CFLAGS -I$withval" - CPPFLAGS="$CPPFLAGS -I$withval"] - ) - - AC_ARG_WITH(zlib-lib, - [ --with-zlib-lib=DIR zlib library directory], - [zlib_lib="$withval" - LIBS="$LIBS -L$withval"] - ) - - AC_CHECK_HEADERS(zlib.h, - [], - [AC_MSG_ERROR("zlib header files not found."); break] - ) - - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - AC_CHECK_LIB(z, compress2, - [LIBS="$LIBS -lz"], - [AC_MSG_ERROR("zlib libraries not found.")] - ) -]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR +m4_include([m4/attribute.m4]) +m4_include([m4/ax_append_flag.m4]) +m4_include([m4/ax_cflags_warn_all.m4]) +m4_include([m4/ax_check_compile_flag.m4]) +m4_include([m4/ax_check_link_flag.m4]) +m4_include([m4/ax_require_defined.m4]) +m4_include([m4/lzo.m4]) +m4_include([m4/openssl.m4]) +m4_include([m4/zlib.m4]) diff --git a/compile b/compile new file mode 100755 index 0000000..23fcba0 --- /dev/null +++ b/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN* | MSYS*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/* | msys/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess index ed2e03b..f50dcdb 100755 --- a/config.guess +++ b/config.guess @@ -1,13 +1,12 @@ #! /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. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2002-03-20' +timestamp='2018-02-24' # 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 +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -16,24 +15,22 @@ timestamp='2002-03-20' # 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. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . -# Originally written by Per Bothner . -# Please send patches to . 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,.*/,,'` @@ -42,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -53,8 +50,7 @@ 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. +Copyright 1992-2018 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." @@ -66,11 +62,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -88,30 +84,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -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. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# 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 ; +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; 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' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -124,12 +132,40 @@ 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 +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +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*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -139,21 +175,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # 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 + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-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 + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -163,145 +211,153 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 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 ;; + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <$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 ;; + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit 0 ;; + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -309,25 +365,51 @@ EOF else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval "$set_cc_for_build" + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -335,26 +417,26 @@ EOF ;; 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 ;; + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -364,41 +446,44 @@ EOF # 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 ;; + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -407,89 +492,95 @@ EOF #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + 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); + 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); + 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 ;; + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + # 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 ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -500,119 +591,143 @@ EOF 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 + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; - *:AIX:*:[45]) + exit ;; + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + 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` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; 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 + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + 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 + 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 + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + 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); - } + 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 + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + if [ "$HP_ARCH" = hppa2.0w ] + then + eval "$set_cc_for_build" + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -637,160 +752,158 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; 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 ;; + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; 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 ;; + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; 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 ;; + echo "$UNAME_MACHINE"-pc-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -800,493 +913,539 @@ EOF 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 ;; + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; 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 - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el #else - #ifdef __INTEL_COMPILER - LIBC=gnu + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} #else - LIBC=gnuaout + CPU= #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 + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # 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$//'` + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + 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} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 - exit 0 ;; + exit ;; paragon:*:*:*) echo i860-intel-osf1 - exit 0 ;; + exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + 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 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; 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) + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; 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 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; 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 ;; + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + 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 - echo i586-unisys-sysv4 - exit 0 ;; + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos - exit 0 ;; + exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; - NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + 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 ;; + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *: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 ;; + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +echo "$0: unable to guess system type" >&2 -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 </dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. 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 + ;; +esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1305,16 +1464,16 @@ hostinfo = `(hostinfo) 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} +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) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config.h.in b/config.h.in index b004d30..cc68348 100644 --- a/config.h.in +++ b/config.h.in @@ -1,310 +1,442 @@ -/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */ +/* config.h.in. Generated from configure.ac by autoheader. */ -/* Define if using alloca.c. */ -#undef C_ALLOCA +/* Support for jumbograms (packets up to 9000 bytes) */ +#undef ENABLE_JUMBOGRAMS -/* Define to empty if the keyword does not work. */ -#undef const +/* Support for tunemu */ +#undef ENABLE_TUNEMU -/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. - This function is required for alloca.c support on those systems. */ -#undef CRAY_STACKSEG_END +/* Support for UML */ +#undef ENABLE_UML -/* Define if you have alloca, as a function or macro. */ -#undef HAVE_ALLOCA +/* Support for VDE */ +#undef ENABLE_VDE -/* Define if you have and it should be used (not on Ultrix). */ -#undef HAVE_ALLOCA_H +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H -/* Define if you have a working `mmap' system call. */ -#undef HAVE_MMAP +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_NAMESER_H -/* Define as __inline if that's what the C compiler calls it. */ -#undef inline +/* Define to 1 if you have the `asprintf' function. */ +#undef HAVE_ASPRINTF -/* Define to `long' if doesn't define. */ -#undef off_t +/* Define to 1 if you have the `BN_GENCB_new' function. */ +#undef HAVE_BN_GENCB_NEW -/* Define to `int' if doesn't define. */ -#undef pid_t +/* Unknown BSD variant */ +#undef HAVE_BSD -/* Define as the return type of signal handlers (int or void). */ -#undef RETSIGTYPE +/* Cygwin */ +#undef HAVE_CYGWIN -/* Define to `unsigned' if doesn't define. */ -#undef size_t +/* Define to 1 if you have the `daemon' function. */ +#undef HAVE_DAEMON -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at run-time. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown - */ -#undef STACK_DIRECTION +/* Darwin (MacOS/X) */ +#undef HAVE_DARWIN -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS +/* Define to 1 if you have the declaration of `EVP_aes_256_cfb', and to 0 if + you don't. */ +#undef HAVE_DECL_EVP_AES_256_CFB -/* Define if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME +/* Define to 1 if you have the declaration of `freeaddrinfo', and to 0 if you + don't. */ +#undef HAVE_DECL_FREEADDRINFO -/* Define if your declares struct tm. */ -#undef TM_IN_SYS_TIME +/* Define to 1 if you have the declaration of `gai_strerror', and to 0 if you + don't. */ +#undef HAVE_DECL_GAI_STRERROR -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc +/* Define to 1 if you have the declaration of `getaddrinfo', and to 0 if you + don't. */ +#undef HAVE_DECL_GETADDRINFO -/* Define to rpl_realloc if the replacement function should be used. */ -#undef realloc +/* Define to 1 if you have the declaration of `getnameinfo', and to 0 if you + don't. */ +#undef HAVE_DECL_GETNAMEINFO -/* This is always defined. It enables GNU extensions on systems that - have them. */ -#if !defined(_GNU_SOURCE) -# undef _GNU_SOURCE -#endif +/* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms', + and to 0 if you don't. */ +#undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS -/* Linux */ -#undef HAVE_LINUX +/* Define to 1 if you have the declaration of `res_init', and to 0 if you + don't. */ +#undef HAVE_DECL_RES_INIT + +/* Define to 1 if you have the `devname' function. */ +#undef HAVE_DEVNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + +/* DragonFly */ +#undef HAVE_DRAGONFLY + +/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ +#undef HAVE_EVP_CIPHER_CTX_NEW + +/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ +#undef HAVE_EVP_ENCRYPTINIT_EX + +/* Define to 1 if you have the `fchmod' function. */ +#undef HAVE_FCHMOD + +/* Define to 1 if you have the `fdevname' function. */ +#undef HAVE_FDEVNAME + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK /* FreeBSD */ #undef HAVE_FREEBSD -/* OpenBSD */ -#undef HAVE_OPENBSD +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H -/* Solaris */ -#undef HAVE_SOLARIS +/* getopt_long() */ +#undef HAVE_GETOPT_LONG + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBVDEPLUG_DYN_H + +/* Linux */ +#undef HAVE_LINUX + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_IF_TUN_H + +/* enable lzo compression support */ +#undef HAVE_LZO + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZO1X_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZO2_LZO1X_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LZO_LZO1X_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* MinGW */ +#undef HAVE_MINGW + +/* Define to 1 if you have the `mlockall' function. */ +#undef HAVE_MLOCKALL /* NetBSD */ #undef HAVE_NETBSD -/* Define to 1 if tun/tap support is enabled and found */ -#undef HAVE_TUNTAP +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H -/* Define to the location of if_tun.h */ -#undef LINUX_IF_TUN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_ICMP6_H -/* Define to 1 if support for jumbograms is enabled */ -#undef ENABLE_JUMBOGRAMS +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H -/* Define to 1 if checkpoint tracing is enabled */ -#undef ENABLE_TRACING +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN6_H -/* Define to enable use of old SSLeay_add_all_algorithms() function */ -#undef HAVE_SSLEAY_ADD_ALL_ALGORITHMS +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H -/* Define if you have the DONE_WORKING_MALLOC_CHECK function. */ -#undef HAVE_DONE_WORKING_MALLOC_CHECK +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_SYSTM_H -/* Define if you have the DONE_WORKING_REALLOC_CHECK function. */ -#undef HAVE_DONE_WORKING_REALLOC_CHECK +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP6_H -/* Define if you have the RAND_pseudo_bytes function. */ -#undef HAVE_RAND_PSEUDO_BYTES +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_H -/* Define if you have the __argz_count function. */ -#undef HAVE___ARGZ_COUNT +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_ICMP_H -/* Define if you have the __argz_next function. */ -#undef HAVE___ARGZ_NEXT +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H -/* Define if you have the __argz_stringify function. */ -#undef HAVE___ARGZ_STRINGIFY +/* Define to 1 if you have the header file. */ +#undef HAVE_NETPACKET_PACKET_H -/* Define if you have the asprintf function. */ -#undef HAVE_ASPRINTF +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_ETHERNET_H -/* Define if you have the daemon function. */ -#undef HAVE_DAEMON +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_ARP_H -/* Define if you have the dcgettext function. */ -#undef HAVE_DCGETTEXT +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H -/* Define if you have the fcloseall function. */ -#undef HAVE_FCLOSEALL +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_TAP_H -/* Define if you have the feof_unlocked function. */ -#undef HAVE_FEOF_UNLOCKED +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_TUN_H -/* Define if you have the fgets_unlocked function. */ -#undef HAVE_FGETS_UNLOCKED +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_TYPES_H -/* Define if you have the flock function. */ -#undef HAVE_FLOCK +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_UTUN_H -/* Define if you have the ftime function. */ -#undef HAVE_FTIME +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_TAP_IF_TAP_H -/* Define if you have the get_current_dir_name function. */ -#undef HAVE_GET_CURRENT_DIR_NAME +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_TUN_IF_TUN_H -/* Define if you have the getcwd function. */ -#undef HAVE_GETCWD +/* OpenBSD */ +#undef HAVE_OPENBSD -/* Define if you have the getegid function. */ -#undef HAVE_GETEGID +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H -/* Define if you have the geteuid function. */ -#undef HAVE_GETEUID - -/* Define if you have the getgid function. */ -#undef HAVE_GETGID - -/* Define if you have the getpagesize function. */ -#undef HAVE_GETPAGESIZE - -/* Define if you have the getuid function. */ -#undef HAVE_GETUID - -/* Define if you have the mempcpy function. */ -#undef HAVE_MEMPCPY - -/* Define if you have the munmap function. */ -#undef HAVE_MUNMAP - -/* Define if you have the putenv function. */ -#undef HAVE_PUTENV - -/* Define if you have the select function. */ -#undef HAVE_SELECT - -/* Define if you have the setenv function. */ -#undef HAVE_SETENV - -/* Define if you have the setlocale function. */ -#undef HAVE_SETLOCALE - -/* Define if you have the socket function. */ -#undef HAVE_SOCKET - -/* Define if you have the stpcpy function. */ -#undef HAVE_STPCPY - -/* Define if you have the strcasecmp function. */ -#undef HAVE_STRCASECMP - -/* Define if you have the strchr function. */ -#undef HAVE_STRCHR - -/* Define if you have the strdup function. */ -#undef HAVE_STRDUP - -/* Define if you have the strerror function. */ -#undef HAVE_STRERROR - -/* Define if you have the strsignal function. */ -#undef HAVE_STRSIGNAL - -/* Define if you have the strtol function. */ -#undef HAVE_STRTOL - -/* Define if you have the strtoul function. */ -#undef HAVE_STRTOUL - -/* Define if you have the tsearch function. */ -#undef HAVE_TSEARCH - -/* Define if you have the unsetenv function. */ -#undef HAVE_UNSETENV - -/* Define if you have the header file. */ -#undef HAVE_ARGZ_H - -/* Define if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define if you have the header file. */ -#undef HAVE_LOCALE_H - -/* Define if you have the header file. */ -#undef HAVE_MALLOC_H - -/* Define if you have the header file. */ -#undef HAVE_NL_TYPES_H - -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_ERR_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_EVP_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_PEM_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_RAND_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_RSA_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SHA_H -/* Define if you have the header file. */ -#undef HAVE_STDDEF_H +/* Define to 1 if you have the `pselect' function. */ +#undef HAVE_PSELECT -/* Define if you have the header file. */ +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define to 1 if you have the `RAND_bytes' function. */ +#undef HAVE_RAND_BYTES + +/* Define to 1 if you have the header file. */ +#undef HAVE_RESOLV_H + +/* Define to 1 if you have the `RSA_set0_key' function. */ +#undef HAVE_RSA_SET0_KEY + +/* Define to 1 if the system has the type `socklen_t'. */ +#undef HAVE_SOCKLEN_T + +/* Solaris/SunOS */ +#undef HAVE_SOLARIS + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H -/* Define if you have the header file. */ -#undef HAVE_STRING_H - -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H -/* Define if you have the header file. */ -#undef HAVE_SYS_FILE_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H -/* Define if you have the header file. */ -#undef HAVE_SYS_IOCTL_H +/* Define to 1 if you have the `strsignal' function. */ +#undef HAVE_STRSIGNAL -/* Define if you have the header file. */ -#undef HAVE_SYS_PARAM_H +/* Define to 1 if the system has the type `struct addrinfo'. */ +#undef HAVE_STRUCT_ADDRINFO -/* Define if you have the header file. */ -#undef HAVE_SYS_TIME_H +/* Define to 1 if the system has the type `struct arphdr'. */ +#undef HAVE_STRUCT_ARPHDR -/* Define if you have the header file. */ +/* Define to 1 if the system has the type `struct ether_arp'. */ +#undef HAVE_STRUCT_ETHER_ARP + +/* Define to 1 if the system has the type `struct ether_header'. */ +#undef HAVE_STRUCT_ETHER_HEADER + +/* Define to 1 if the system has the type `struct icmp'. */ +#undef HAVE_STRUCT_ICMP + +/* Define to 1 if the system has the type `struct icmp6_hdr'. */ +#undef HAVE_STRUCT_ICMP6_HDR + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#undef HAVE_STRUCT_IN6_ADDR + +/* Define to 1 if the system has the type `struct in_addr'. */ +#undef HAVE_STRUCT_IN_ADDR + +/* Define to 1 if the system has the type `struct ip'. */ +#undef HAVE_STRUCT_IP + +/* Define to 1 if the system has the type `struct ip6_hdr'. */ +#undef HAVE_STRUCT_IP6_HDR + +/* Define to 1 if the system has the type `struct nd_neighbor_solicit'. */ +#undef HAVE_STRUCT_ND_NEIGHBOR_SOLICIT + +/* Define to 1 if the system has the type `struct nd_opt_hdr'. */ +#undef HAVE_STRUCT_ND_OPT_HDR + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6 + +/* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H -/* Define if you have the header file. */ +/* Define to 1 if you have the `system' function. */ +#undef HAVE_SYSTEM + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define if you have the header file. */ +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the `vsyslog' function. */ +#undef HAVE_VSYSLOG + +/* have zlib compression support */ +#undef HAVE_ZLIB + +/* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H -/* Define if you have the nsl library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define if you have the socket library (-lsocket). */ -#undef HAVE_LIBSOCKET +/* Location of lzo1x.h */ +#undef LZO1X_H /* Name of package */ #undef PACKAGE +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + /* Version number of package */ #undef VERSION -/* Define if you have the iconv() function. */ -#undef HAVE_ICONV +/* Compile with support for Windows 2000 */ +#undef WITH_WINDOWS2000 -/* Define as const if the declaration of iconv() needs const. */ -#undef ICONV_CONST +/* Define to 1 if on MINIX. */ +#undef _MINIX -/* Define if you have and nl_langinfo(CODESET). */ -#undef HAVE_LANGINFO_CODESET +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE -/* Define if your file defines LC_MESSAGES. */ -#undef HAVE_LC_MESSAGES +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE -/* Define to 1 if translation of program messages to the user's native language - is requested. */ -#undef ENABLE_NLS +/* Enable BSD extensions */ +#undef __USE_BSD -/* Define if the GNU gettext() function is already present or preinstalled. */ -#undef HAVE_GETTEXT +/* Defined if the __malloc__ attribute is not supported. */ +#undef __malloc__ +/* Define to `int' if does not define. */ +#undef pid_t diff --git a/config.sub b/config.sub index f365797..1d8e98b 100755 --- a/config.sub +++ b/config.sub @@ -1,42 +1,40 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2002-03-07' +timestamp='2018-02-22' -# 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 +# 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 3 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. +# 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. - +# along with this program; if not, see . +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. + +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + # 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. @@ -55,12 +53,11 @@ timestamp='2002-03-07' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -70,8 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright 1992-2018 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." @@ -83,11 +79,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -98,8 +94,8 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 - exit 0;; + echo "$1" + exit ;; * ) break ;; @@ -116,16 +112,24 @@ 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/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -144,10 +148,13 @@ case $os in -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) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -162,54 +169,65 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + 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/'` + 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/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + 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/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -226,42 +244,114 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | 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 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | openrisc | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | 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) + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' @@ -272,54 +362,102 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | m32r-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ | 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-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | 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-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -332,6 +470,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -346,6 +487,12 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -369,6 +516,13 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -377,10 +531,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -405,12 +584,27 @@ case $basic_machine in basic_machine=j90-cray os=-unicos ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; crds | unos) basic_machine=m68k-crds ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; @@ -433,14 +627,30 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -530,9 +740,6 @@ case $basic_machine in 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 @@ -544,28 +751,27 @@ case $basic_machine in 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/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -583,8 +789,16 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; - m88k-omron*) - basic_machine=m88k-omron + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux ;; magnum | m3230) basic_machine=mips-mips @@ -594,10 +808,21 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -606,14 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + 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 + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -623,14 +844,29 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -659,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -695,16 +931,31 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; - or32 | or32-*) + openrisc | openrisc-*) basic_machine=or32-unknown - os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson @@ -722,57 +973,78 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; + pentium4) + basic_machine=i786-pc + ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + 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) + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -781,6 +1053,14 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -801,14 +1081,27 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms + sh5el) + basic_machine=sh5le-unknown ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -826,6 +1119,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -866,7 +1162,7 @@ case $basic_machine in sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; - sv1) + sv1) basic_machine=sv1-cray os=-unicos ;; @@ -874,10 +1170,6 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; - t3d) - basic_machine=alpha-cray - os=-unicos - ;; t3e) basic_machine=alphaev5-cray os=-unicos @@ -886,9 +1178,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -903,6 +1195,10 @@ case $basic_machine in tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -924,8 +1220,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -946,21 +1242,23 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt + x64) + basic_machine=x86_64-pc ;; - xps | xps100) + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -980,32 +1278,25 @@ case $basic_machine in romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1020,15 +1311,11 @@ case $basic_machine in 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 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1036,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1050,47 +1337,60 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # 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* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -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* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1102,37 +1402,39 @@ case $os in ;; esac ;; - -nto*) - os=-nto-qnx + -nto-qnx*) ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1145,6 +1447,9 @@ case $os in -atheos*) os=-atheos ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; @@ -1154,8 +1459,8 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) - os=-nextstep2 + -ns2) + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1167,13 +1472,16 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1188,21 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint ;; - -xenix) - os=-xenix + -zvmoe) + os=-zvmoe ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) ;; -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 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1219,6 +1544,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1228,11 +1559,29 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1246,13 +1595,13 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; @@ -1268,12 +1617,18 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; @@ -1307,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1322,22 +1677,19 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1376,7 +1728,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1406,10 +1758,16 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) @@ -1428,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os -exit 0 +echo "$basic_machine$os" +exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure b/configure index 2eed879..2f7cd24 100755 --- a/configure +++ b/configure @@ -1,50 +1,788 @@ #! /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. +# Generated by GNU Autoconf 2.69 for tinc 1.0.36. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -# Defaults: -ac_help= +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# ac_default_prefix=/usr/local -# 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_help="$ac_help - --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib" -ac_help="$ac_help - --disable-nls do not use Native Language Support" -ac_help="$ac_help - --with-included-gettext use the GNU gettext library included here" -ac_help="$ac_help - --with-kernel=dir give the directory with kernel sources - (default: /usr/src/linux)" -ac_help="$ac_help - --with-openssl-include=DIR OpenSSL headers directory (without trailing /openssl)" -ac_help="$ac_help - --with-openssl-lib=DIR OpenSSL library directory" -ac_help="$ac_help - --with-zlib-include=DIR zlib headers directory" -ac_help="$ac_help - --with-zlib-lib=DIR zlib library directory" -ac_help="$ac_help - --enable-jumbograms enable support for jumbograms (packets up to 9000 bytes)" -ac_help="$ac_help - --enable-tracing enable checkpoint tracing (debugging only)" +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='tinc' +PACKAGE_TARNAME='tinc' +PACKAGE_VERSION='1.0.36' +PACKAGE_STRING='tinc 1.0.36' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="src/tincd.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +GETOPT_FALSE +GETOPT_TRUE +WITH_SYSTEMD_FALSE +WITH_SYSTEMD_TRUE +TUNEMU_FALSE +TUNEMU_TRUE +VDE_FALSE +VDE_TRUE +UML_FALSE +UML_TRUE +CYGWIN_FALSE +CYGWIN_TRUE +MINGW_FALSE +MINGW_TRUE +SOLARIS_FALSE +SOLARIS_TRUE +BSD_FALSE +BSD_TRUE +LINUX_FALSE +LINUX_TRUE +systemd_path +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL +am__quote' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_uml +enable_vde +enable_tunemu +with_windows2000 +with_systemd +enable_hardening +enable_zlib +with_zlib +with_zlib_include +with_zlib_lib +enable_lzo +with_lzo +with_lzo_include +with_lzo_lib +with_openssl +with_openssl_include +with_openssl_lib +enable_jumbograms +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + # Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. -build=NONE -cache_file=./config.cache +cache_file=/dev/null exec_prefix=NONE -host=NONE no_create= -nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE @@ -53,94 +791,133 @@ program_transform_name=s,x,x, silent= site= srcdir= -target=NONE verbose= x_includes=NONE x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' +datarootdir='${prefix}/share' +datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' +runstatedir='${localstatedir}/run' 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 +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' ac_prev= +ac_dashdash= for ac_option do - # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" + 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= ;; + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. - case "$ac_option" in + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; + bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) - ac_prev=build ;; + ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; + build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; + cache_file=$ac_optarg ;; - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + ac_useropt=`expr "x$ac_option" : 'x-*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" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # 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 ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "enable_${ac_feature}='$ac_optarg'" ;; + eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ @@ -149,116 +926,77 @@ do -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; + 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 ;; + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; -host | --host | --hos | --ho) - ac_prev=host ;; + ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; + includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; + infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; + 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" ;; + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) + | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; + 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-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ @@ -272,26 +1010,26 @@ EOF -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; + oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; + 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_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_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ @@ -308,17 +1046,36 @@ EOF | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; + sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ @@ -329,58 +1086,67 @@ EOF | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; + sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; + site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; + 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" ;; + sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; + ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; + target_alias=$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 ;; + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # 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 ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "with_${ac_package}='$ac_optarg'" ;; + eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` + ac_useropt=`expr "x$ac_option" : 'x-*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" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. @@ -391,182 +1157,1202 @@ EOF 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_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" ;; + x_libraries=$ac_optarg ;; - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + *) - 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" + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" 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" ;; +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done -# 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 +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias -# 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 +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" -# 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=src/tincd.c # 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=. + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + 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 +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done -# 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 +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures tinc 1.0.36 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/tinc] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --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 + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF 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" + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of tinc 1.0.36:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-uml enable support for User Mode Linux + --enable-vde enable support for Virtual Distributed Ethernet + --enable-tunemu enable support for the tunemu driver + --disable-hardening disable compiler and linker hardening flags + --disable-zlib disable zlib compression support + --disable-lzo disable lzo compression support + --enable-jumbograms enable support for jumbograms (packets up to 9000 + bytes) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-windows2000 compile with support for Windows 2000. This disables + support for tunneling over existing IPv6 networks. + --with-systemd[=DIR] install systemd service files [to DIR if specified] + --with-zlib=DIR zlib base directory, or: + --with-zlib-include=DIR zlib headers directory + --with-zlib-lib=DIR zlib library directory + --with-lzo=DIR lzo base directory, or: + --with-lzo-include=DIR lzo headers directory + --with-lzo-lib=DIR lzo library directory + --with-openssl=DIR LibreSSL/OpenSSL base directory, or: + --with-openssl-include=DIR + LibreSSL/OpenSSL headers directory (without trailing + /openssl) + --with-openssl-lib=DIR LibreSSL/OpenSSL library directory + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +tinc configure 1.0.36 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by tinc $as_me 1.0.36, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then - 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= + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac fi else - ac_n= ac_c='\c' ac_t= + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file fi +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +am__api_version='1.16' ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then +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 + elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break fi done if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 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. +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -# 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 @@ -575,204 +2361,677 @@ am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs # 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" +# OS/2's system install, which has a completely different semantic # ./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:584: checking for a BSD compatible install" >&5 +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 else - IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" - for ac_dir in $PATH; do + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. # 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 +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /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 + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && - grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : else - ac_cv_path_install="$ac_dir/$ac_prog -c" - break 2 + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi fi fi done - ;; - esac + done + ;; +esac + done - IFS="$ac_save_IFS" +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then - INSTALL="$ac_cv_path_install" + 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 + # As a last resort, use the slow shell script. Don't cache a + # value 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" + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh fi fi -echo "$ac_t""$INSTALL" 1>&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:637: 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# 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 + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + 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 + 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". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done 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; } + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! fi + +rm -f conftest.file + test "$program_prefix" != NONE && - program_transform_name="s,^,${program_prefix},; $program_transform_name" + 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" + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# sed with no file args requires a program. -test "$program_transform_name" = "" && program_transform_name="s,x,x," +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= - am_backtick='`' - echo "configure: warning: ${am_backtick}missing' script is too old or missing" 1>&2 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -for ac_prog in mawk gawk nawk awk +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH do -# Extract the first word of "$ac_prog", so it can be a program name with args. + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk 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:708: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&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 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - IFS="$ac_save_ifs" +IFS=$as_save_IFS + fi fi -AWK="$ac_cv_prog_AWK" +AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - echo "$ac_t""$AWK" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } else - echo "$ac_t""no" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -test -n "$AWK" && break + + test -n "$AWK" && break done -echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:738: 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 else - cat > conftestmake <<\EOF + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh 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 + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make fi -rm -f conftestmake -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$ac_t""yes" 1>&6 +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } SET_MAKE= else - echo "$ac_t""no" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&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" - : +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='tinc' + VERSION='1.0.36' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +ac_config_headers="$ac_config_headers config.h" + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +# Enable GNU extensions. +# Define this here, not in acconfig's @TOP@ section, since definitions +# in the latter don't make it into the configure-time tests. +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } + +# Check whether --enable-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='\' + am__nodep='_no' fi - - -if test "x$enable_dependency_tracking" != xno; then + if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else @@ -781,303 +3040,686 @@ else 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=tinc -VERSION=1.0pre7 -cat >> confdefs.h <> confdefs.h <> confdefs.h <<\EOF -#define _GNU_SOURCE __USE_BSD -EOF - - -ALL_LINGUAS="nl" - -# 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:877: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else - 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 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - IFS="$ac_save_ifs" +IFS=$as_save_IFS + fi fi -CC="$ac_cv_prog_CC" +CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$ac_t""no" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" fi if test -z "$CC"; then - # 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:907: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else - 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 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - IFS="$ac_save_ifs" +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift - if test $# -gt 0; then + if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift - set dummy "$ac_dir/$ac_word" "$@" - shift - ac_cv_prog_CC="$@" + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi -CC="$ac_cv_prog_CC" +CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$ac_t""no" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&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:958: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else - 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 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - IFS="$ac_save_ifs" +IFS=$as_save_IFS + fi fi -CC="$ac_cv_prog_CC" +CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$ac_t""no" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - ;; - esac + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 fi - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:990: 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 + test -n "$ac_ct_CC" && break +done -cat > conftest.$ac_ext << EOF - -#line 1001 "configure" -#include "confdefs.h" - -main(){return(0);} -EOF -if { (eval echo configure:1006: \"$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 + if test "x$ac_ct_CC" = x; then + CC="" else - ac_cv_prog_cc_cross=yes + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC fi -else - 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:1032: 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:1037: 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 + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + else - cat > conftest.c <&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me #endif -EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1046: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes else - ac_cv_prog_gcc=no + ac_compiler_gnu=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + fi - -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi - -ac_test_CFLAGS="${CFLAGS+set}" -ac_save_CFLAGS="$CFLAGS" -CFLAGS= -echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1065: 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 +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else - ac_cv_prog_cc_g=no -fi -rm -f conftest* + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -fi +int +main () +{ -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" + CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" @@ -1091,100 +3733,264 @@ else CFLAGS= fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; -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:1104: 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 +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg fi -# 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 +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$ac_t""$_am_result" 1>&6 -rm -f confinc confmf +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= -echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6 -echo "configure:1138: 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&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'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir 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 + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub 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 + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # # 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 + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # 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. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # 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 ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; 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 && + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - am_cv_CC_dependencies_compiler_type=$depmode - break + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi fi done @@ -1195,517 +4001,328 @@ else fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type -echo "$ac_t""$am_cv_CC_dependencies_compiler_type" 1>&6 -CCDEPMODE="depmode=$am_cv_CC_dependencies_compiler_type" + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi -echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1205: checking how to run the C preprocessor" >&5 + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then -if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&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 < -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1226: \"$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 < -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1243: \"$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 < -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1260: \"$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 - -if test $ac_cv_prog_gcc = yes; then - echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 -echo "configure:1286: checking whether ${CC-cc} needs -traditional" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_pattern="Autoconf.*'x'" - cat > conftest.$ac_ext < -Autoconf TIOCGETP -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "$ac_pattern" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_prog_gcc_traditional=yes -else - rm -rf conftest* - ac_cv_prog_gcc_traditional=no -fi -rm -f conftest* - - - if test $ac_cv_prog_gcc_traditional = no; then - cat > conftest.$ac_ext < -Autoconf TCGETA -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "$ac_pattern" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_prog_gcc_traditional=yes -fi -rm -f conftest* - - fi -fi - -echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 - if test $ac_cv_prog_gcc_traditional = yes; then - CC="$CC -traditional" - fi -fi - -for ac_prog in mawk gawk nawk awk + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes do -# 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:1336: 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 + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext -test -n "$AWK" && break done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi -# 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:1377: 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 + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP 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" - + ac_cv_prog_CPP=$CPP 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : -# 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 ln -s works""... $ac_c" 1>&6 -echo "configure:1430: 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 + # Broken: fails on valid input. +continue 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 +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue else - echo "$ac_t""no" 1>&6 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi -echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:1451: 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 +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu - echo $ac_n "checking for perl5.003 or newer""... $ac_c" 1>&6 -echo "configure:1479: checking for perl5.003 or newer" >&5 - if test "${PERL+set}" = set; then - # `PERL' is set in the user's environment. - candidate_perl_names="$PERL" - perl_specified=yes - else - candidate_perl_names='perl perl5' - perl_specified=no - fi - - found=no - - PERL="$missing_dir/missing perl" - for perl in $candidate_perl_names; do - # Run test in a subshell; some versions of sh will print an error if - # an executable is not found, even if stderr is redirected. - if ( $perl -e 'require 5.003' ) > /dev/null 2>&1; then - PERL=$perl - found=yes - break +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break done - - echo "$ac_t""$found" 1>&6 - test $found = no && echo "configure: warning: -*** You don't seem to have perl5.003 or newer installed. -*** Because of that, you may be unable to regenerate certain files -*** if you modify the sources from which they are derived. " 1>&2 - - - - - echo $ac_n "checking for strerror in -lcposix""... $ac_c" 1>&6 -echo "configure:1512: checking for strerror in -lcposix" >&5 -ac_lib_var=`echo cposix'_'strerror | 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="-lcposix $LIBS" -cat > conftest.$ac_ext <&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 -lcposix" -else - echo "$ac_t""no" 1>&6 -fi - - - - - - -# 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:1562: 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 ;; + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; 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 - - -case $host_os in - *linux*) - cat >> confdefs.h <<\EOF -#define HAVE_LINUX 1 -EOF - - rm -f src/device.c; ln -sf linux/device.c src/device.c - ;; - *freebsd*) - cat >> confdefs.h <<\EOF -#define HAVE_FREEBSD 1 -EOF - - rm -f src/device.c; ln -sf freebsd/device.c src/device.c - ;; - *solaris*) - cat >> confdefs.h <<\EOF -#define HAVE_SOLARIS 1 -EOF - - rm -f src/device.c; ln -sf solaris/device.c src/device.c - ;; - *openbsd*) - cat >> confdefs.h <<\EOF -#define HAVE_OPENBSD 1 -EOF - - rm -f src/device.c; ln -sf openbsd/device.c src/device.c - ;; - *netbsd*) - cat >> confdefs.h <<\EOF -#define HAVE_NETBSD 1 -EOF - - rm -f src/device.c; ln -sf netbsd/device.c src/device.c - ;; -esac - -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" + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi -fi -rm -f confcache - - - -echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1671: 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 <&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ #include #include #include #include -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1684: \"$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* + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : 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* +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. -cat > conftest.$ac_ext <conftest.$ac_ext +/* end confdefs.h. */ #include -EOF + +_ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "memchr" >/dev/null 2>&1; then - : + $EGREP "memchr" >/dev/null 2>&1; then : + else - rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* @@ -1714,16 +4331,15 @@ 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 <conftest.$ac_ext +/* end confdefs.h. */ #include -EOF + +_ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "free" >/dev/null 2>&1; then - : + $EGREP "free" >/dev/null 2>&1; then : + else - rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* @@ -1732,3509 +4348,3918 @@ 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 + if test "$cross_compiling" = yes; then : : else - cat > conftest.$ac_ext <conftest.$ac_ext +/* end confdefs.h. */ #include -#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int main () { int i; for (i = 0; i < 256; i++) -if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); -exit (0); } - -EOF -if { (eval echo configure:1751: \"$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 limits.h sys/ioctl.h syslog.h unistd.h \ -sys/time.h malloc.h strings.h sys/file.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1779: 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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1789: \"$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 <&6 -fi -done - - -echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:1817: checking for working const" >&5 -if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <j = 5; -} -{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; -} - -; return 0; } -EOF -if { (eval echo configure:1871: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - ac_cv_c_const=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - ac_cv_c_const=no -fi -rm -f conftest* -fi - -echo "$ac_t""$ac_cv_c_const" 1>&6 -if test $ac_cv_c_const = no; then - cat >> confdefs.h <<\EOF -#define const -EOF - -fi - -echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:1892: checking for pid_t" >&5 -if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -#if STDC_HEADERS -#include -#include -#endif -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_pid_t=yes -else - rm -rf conftest* - ac_cv_type_pid_t=no -fi -rm -f conftest* - -fi -echo "$ac_t""$ac_cv_type_pid_t" 1>&6 -if test $ac_cv_type_pid_t = no; then - cat >> confdefs.h <<\EOF -#define pid_t int -EOF - -fi - -echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1925: 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 < -#if STDC_HEADERS -#include -#include -#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:1958: 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 < -#include -#include -int main() { -struct tm *tp; -; return 0; } -EOF -if { (eval echo configure:1972: \"$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:1993: 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 < -#include -int main() { -struct tm *tp; tp->tm_sec; -; return 0; } -EOF -if { (eval echo configure:2006: \"$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 for 8-bit clean memcmp""... $ac_c" 1>&6 -echo "configure:2028: checking for 8-bit clean memcmp" >&5 -if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_func_memcmp_clean=no -else - cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_func_memcmp_clean=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_func_memcmp_clean=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 -test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" - -# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works -# for constant arguments. Useless! -echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:2066: checking for working alloca.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int main() { -char *p = alloca(2 * sizeof(int)); -; return 0; } -EOF -if { (eval echo configure:2078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - ac_cv_header_alloca_h=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - ac_cv_header_alloca_h=no -fi -rm -f conftest* -fi - -echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 -if test $ac_cv_header_alloca_h = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_ALLOCA_H 1 -EOF - -fi - -echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2099: checking for alloca" >&5 -if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -# define alloca _alloca -# else -# if HAVE_ALLOCA_H -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -# endif -# endif -# endif -# endif -#endif - -int main() { -char *p = (char *) alloca(1); -; return 0; } -EOF -if { (eval echo configure:2132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - ac_cv_func_alloca_works=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - ac_cv_func_alloca_works=no -fi -rm -f conftest* -fi - -echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 -if test $ac_cv_func_alloca_works = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_ALLOCA 1 -EOF - -fi - -if test $ac_cv_func_alloca_works = no; then - # The SVR3 libPW and SVR4 libucb both contain incompatible functions - # that cause trouble. Some versions do not even contain alloca or - # contain a buggy version. If you still want to use their alloca, - # use ar to extract alloca.o from them instead of compiling alloca.c. - ALLOCA=alloca.${ac_objext} - cat >> confdefs.h <<\EOF -#define C_ALLOCA 1 -EOF - - -echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2164: checking whether alloca needs Cray hooks" >&5 -if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <&5 | - egrep "webecray" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_os_cray=yes -else - rm -rf conftest* - ac_cv_os_cray=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_os_cray" 1>&6 -if test $ac_cv_os_cray = yes; then -for ac_func in _getb67 GETB67 getb67; do - echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2194: 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 < -/* 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 $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:2222: \"$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 - cat >> confdefs.h <&6 -fi - -done -fi - -echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2249: checking stack direction for C alloca" >&5 -if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_c_stack_direction=0 -else - cat > conftest.$ac_ext < addr) ? 1 : -1; -} +int main () { - exit (find_stack_direction() < 0); + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; } -EOF -if { (eval echo configure:2276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_c_stack_direction=1 +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_c_stack_direction=-1 + ac_cv_header_stdc=no fi -rm -fr conftest* +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then -echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 -cat >> confdefs.h <>confdefs.h fi -echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:2298: 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 < -#include -#ifdef signal -#undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); -#endif +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF -int main() { -int i; -; return 0; } -EOF -if { (eval echo configure:2320: \"$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 <&6 -echo "configure:2342: 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 < -/* 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 $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:2370: \"$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 <&6 -fi done - if test x = y; then - for ac_func in DONE_WORKING_MALLOC_CHECK -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2399: 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 + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes else - cat > conftest.$ac_ext < -/* 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 $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:2427: \"$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* + MINIX= 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 <&6 -fi -done - fi - ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK - cat >> confdefs.h <>confdefs.h - echo $ac_n "checking for working malloc""... $ac_c" 1>&6 -echo "configure:2459: checking for working malloc" >&5 -if eval "test \"`echo '$''{'jm_cv_func_working_malloc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - jm_cv_func_working_malloc=no -else - cat > conftest.$ac_ext <>confdefs.h - char *malloc (); - int - main () - { - exit (malloc (0) ? 0 : 1); - } - -EOF -if { (eval echo configure:2478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - jm_cv_func_working_malloc=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - jm_cv_func_working_malloc=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$jm_cv_func_working_malloc" 1>&6 - if test $jm_cv_func_working_malloc = no; then - LIBOBJS="$LIBOBJS malloc.o" - cat >> confdefs.h <>confdefs.h fi - if test x = y; then - for ac_func in DONE_WORKING_REALLOC_CHECK -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2507: 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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 else - cat > conftest.$ac_ext < -/* 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 $ac_func(); + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -int main() { +# define __EXTENSIONS__ 1 + $ac_includes_default +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:2535: \"$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" + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_$ac_func=no" + ac_cv_safe_to_define___extensions__=no fi -rm -f conftest* +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h -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 <>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + +$as_echo "#define __USE_BSD 1" >>confdefs.h + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 else - echo "$ac_t""no" 1>&6 -fi -done - - fi - ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK - cat >> confdefs.h <&6 -echo "configure:2567: checking for working realloc" >&5 -if eval "test \"`echo '$''{'jm_cv_func_working_realloc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - jm_cv_func_working_realloc=no -else - cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - jm_cv_func_working_realloc=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - jm_cv_func_working_realloc=no -fi -rm -fr conftest* -fi - - -fi - -echo "$ac_t""$jm_cv_func_working_realloc" 1>&6 - if test $jm_cv_func_working_realloc = no; then - LIBOBJS="$LIBOBJS realloc.o" - cat >> confdefs.h <&6 -echo "configure:2614: 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 - -echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:2642: checking for inline" >&5 -if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - ac_cv_c_inline=$ac_kw; break -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 -fi -rm -f conftest* -done - -fi - -echo "$ac_t""$ac_cv_c_inline" 1>&6 -case "$ac_cv_c_inline" in - inline | yes) ;; - no) cat >> confdefs.h <<\EOF -#define inline -EOF - ;; - *) cat >> confdefs.h <&6 -echo "configure:2682: checking for off_t" >&5 -if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -#if STDC_HEADERS + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include #include -#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; #endif -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_off_t=yes -else - rm -rf conftest* - ac_cv_type_off_t=no -fi -rm -f conftest* - -fi -echo "$ac_t""$ac_cv_type_off_t" 1>&6 -if test $ac_cv_type_off_t = no; then - cat >> confdefs.h <<\EOF -#define off_t long -EOF - -fi - -for ac_hdr in unistd.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2718: 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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2728: \"$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 <&6 -fi -done - -for ac_func in getpagesize -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2757: 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 < -/* 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 $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 +#if BIG_OK #else -$ac_func(); + your preprocessor is broken; #endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; -; return 0; } -EOF -if { (eval echo configure:2785: \"$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 +struct incomplete_array +{ + int datasize; + double data[]; +}; -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 <&6 -fi -done +struct named_init { + int number; + const wchar_t *name; + double average; +}; -echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:2810: checking for working mmap" >&5 -if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_func_mmap_fixed_mapped=no -else - cat > conftest.$ac_ext < -#include -#include +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); -/* This mess was copied from the GNU getpagesize.h. */ -#ifndef HAVE_GETPAGESIZE -# ifdef HAVE_UNISTD_H -# include -# endif + const char *str; + int number; + float fnumber; -/* Assume that all systems that can run configure have sys/param.h. */ -# ifndef HAVE_SYS_PARAM_H -# define HAVE_SYS_PARAM_H 1 -# endif - -# ifdef _SC_PAGESIZE -# define getpagesize() sysconf(_SC_PAGESIZE) -# else /* no _SC_PAGESIZE */ -# ifdef HAVE_SYS_PARAM_H -# include -# ifdef EXEC_PAGESIZE -# define getpagesize() EXEC_PAGESIZE -# else /* no EXEC_PAGESIZE */ -# ifdef NBPG -# define getpagesize() NBPG * CLSIZE -# ifndef CLSIZE -# define CLSIZE 1 -# endif /* no CLSIZE */ -# else /* no NBPG */ -# ifdef NBPC -# define getpagesize() NBPC -# else /* no NBPC */ -# ifdef PAGESIZE -# define getpagesize() PAGESIZE -# endif /* PAGESIZE */ -# endif /* no NBPC */ -# endif /* no NBPG */ -# endif /* no EXEC_PAGESIZE */ -# else /* no HAVE_SYS_PARAM_H */ -# define getpagesize() 8192 /* punt totally */ -# endif /* no HAVE_SYS_PARAM_H */ -# endif /* no _SC_PAGESIZE */ - -#endif /* no HAVE_GETPAGESIZE */ - -#ifdef __cplusplus -extern "C" { void *malloc(unsigned); } -#else -char *malloc(); -#endif + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} int -main() +main () { - char *data, *data2, *data3; - int i, pagesize; - int fd; - pagesize = getpagesize(); + // Check bool. + _Bool success = false; - /* - * First, make a file with some known garbage in it. - */ - data = malloc(pagesize); - if (!data) - exit(1); - for (i = 0; i < pagesize; ++i) - *(data + i) = rand(); - umask(0); - fd = creat("conftestmmap", 0600); - if (fd < 0) - exit(1); - if (write(fd, data, pagesize) != pagesize) - exit(1); - close(fd); + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; - /* - * Next, try to mmap the file at a fixed address which - * already has something else allocated at it. If we can, - * also make sure that we see the same garbage. - */ - fd = open("conftestmmap", O_RDWR); - if (fd < 0) - exit(1); - data2 = malloc(2 * pagesize); - if (!data2) - exit(1); - data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); - if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED, fd, 0L)) - exit(1); - for (i = 0; i < pagesize; ++i) - if (*(data + i) != *(data2 + i)) - exit(1); + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); - /* - * Finally, make sure that changes to the mapped area - * do not percolate back to the file as seen by read(). - * (This is a bug on some variants of i386 svr4.0.) - */ - for (i = 0; i < pagesize; ++i) - *(data2 + i) = *(data2 + i) + 1; - data3 = malloc(pagesize); - if (!data3) - exit(1); - if (read(fd, data3, pagesize) != pagesize) - exit(1); - for (i = 0; i < pagesize; ++i) - if (*(data + i) != *(data3 + i)) - exit(1); - close(fd); - unlink("conftestmmap"); - exit(0); + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; } - -EOF -if { (eval echo configure:2958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_func_mmap_fixed_mapped=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_func_mmap_fixed_mapped=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 -if test $ac_cv_func_mmap_fixed_mapped = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_MMAP 1 -EOF - -fi - - - echo $ac_n "checking whether we are using the GNU C Library 2.1 or newer""... $ac_c" 1>&6 -echo "configure:2982: checking whether we are using the GNU C Library 2.1 or newer" >&5 -if eval "test \"`echo '$''{'ac_cv_gnu_library_2_1'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -#ifdef __GNU_LIBRARY__ - #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) - Lucky GNU user - #endif -#endif - -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "Lucky GNU user" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_gnu_library_2_1=yes -else - rm -rf conftest* - ac_cv_gnu_library_2_1=no -fi -rm -f conftest* - - - -fi - -echo "$ac_t""$ac_cv_gnu_library_2_1" 1>&6 - - GLIBC21="$ac_cv_gnu_library_2_1" - - - - for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ -stdlib.h string.h unistd.h sys/param.h +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3023: 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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3033: \"$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 <&6 + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break done +rm -f conftest.$ac_ext +CC=$ac_save_CC - for ac_func in feof_unlocked fgets_unlocked getcwd getegid geteuid \ -getgid getuid mempcpy munmap putenv setenv setlocale stpcpy strchr strcasecmp \ -strdup strtoul tsearch __argz_count __argz_stringify __argz_next -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3064: 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 +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 else - cat > conftest.$ac_ext < -/* 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 $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 + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include #else -$ac_func(); +# include #endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : -; return 0; } -EOF -if { (eval echo configure:3092: \"$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* + # Broken: fails on valid input. +continue fi +rm -f conftest.err conftest.i conftest.$ac_ext -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 <conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue else - echo "$ac_t""no" 1>&6 + # Passes both tests. +ac_preproc_ok=: +break fi +rm -f conftest.err conftest.i conftest.$ac_ext + done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi - - - - # Check whether --with-libiconv-prefix or --without-libiconv-prefix was given. -if test "${with_libiconv_prefix+set}" = set; then - withval="$with_libiconv_prefix" - - for dir in `echo "$withval" | tr : ' '`; do - if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi - if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi done - + ac_cv_prog_CPP=$CPP + fi - - - echo $ac_n "checking for iconv""... $ac_c" 1>&6 -echo "configure:3132: checking for iconv" >&5 -if eval "test \"`echo '$''{'am_cv_func_iconv'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + CPP=$ac_cv_prog_CPP else - - am_cv_func_iconv="no, consider installing GNU libiconv" - am_cv_lib_iconv=no - cat > conftest.$ac_ext < -#include -int main() { -iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd); -; return 0; } -EOF -if { (eval echo configure:3150: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - am_cv_func_iconv=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 + ac_cv_prog_CPP=$CPP fi -rm -f conftest* - if test "$am_cv_func_iconv" != yes; then - am_save_LIBS="$LIBS" - LIBS="$LIBS -liconv" - cat > conftest.$ac_ext < -#include -int main() { -iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd); -; return 0; } -EOF -if { (eval echo configure:3172: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - am_cv_lib_iconv=yes - am_cv_func_iconv=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 -fi -rm -f conftest* - LIBS="$am_save_LIBS" - fi - -fi - -echo "$ac_t""$am_cv_func_iconv" 1>&6 - if test "$am_cv_func_iconv" = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_ICONV 1 -EOF - - echo $ac_n "checking for iconv declaration""... $ac_c" 1>&6 -echo "configure:3193: checking for iconv declaration" >&5 - if eval "test \"`echo '$''{'am_cv_proto_iconv'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - cat > conftest.$ac_ext < -#include -extern -#ifdef __cplusplus -"C" -#endif -#if defined(__STDC__) || defined(__cplusplus) -size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); -#else -size_t iconv(); -#endif - -int main() { - -; return 0; } -EOF -if { (eval echo configure:3218: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - am_cv_proto_iconv_arg1="" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - am_cv_proto_iconv_arg1="const" -fi -rm -f conftest* - am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" -fi - - am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` - echo "$ac_t""${ac_t:- - }$am_cv_proto_iconv" 1>&6 - cat >> confdefs.h <&6 -echo "configure:3247: checking for nl_langinfo and CODESET" >&5 -if eval "test \"`echo '$''{'am_cv_langinfo_codeset'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int main() { -char* cs = nl_langinfo(CODESET); -; return 0; } -EOF -if { (eval echo configure:3259: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - am_cv_langinfo_codeset=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - am_cv_langinfo_codeset=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$am_cv_langinfo_codeset" 1>&6 - if test $am_cv_langinfo_codeset = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_LANGINFO_CODESET 1 -EOF - - fi - - if test $ac_cv_header_locale_h = yes; then - echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 -echo "configure:3282: checking for LC_MESSAGES" >&5 -if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int main() { -return LC_MESSAGES -; return 0; } -EOF -if { (eval echo configure:3294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - am_cv_val_LC_MESSAGES=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - am_cv_val_LC_MESSAGES=no -fi -rm -f conftest* -fi - -echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 - if test $am_cv_val_LC_MESSAGES = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_LC_MESSAGES 1 -EOF - - fi - fi - echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 -echo "configure:3315: checking whether NLS is requested" >&5 - # Check whether --enable-nls or --disable-nls was given. -if test "${enable_nls+set}" = set; then - enableval="$enable_nls" - USE_NLS=$enableval -else - USE_NLS=yes -fi - - echo "$ac_t""$USE_NLS" 1>&6 - - - BUILD_INCLUDED_LIBINTL=no - USE_INCLUDED_LIBINTL=no - INTLLIBS= - - if test "$USE_NLS" = "yes"; then - cat >> confdefs.h <<\EOF -#define ENABLE_NLS 1 -EOF - - echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 -echo "configure:3337: checking whether included gettext is requested" >&5 - # Check whether --with-included-gettext or --without-included-gettext was given. -if test "${with_included_gettext+set}" = set; then - withval="$with_included_gettext" - nls_cv_force_use_gnu_gettext=$withval -else - nls_cv_force_use_gnu_gettext=no -fi - - echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 - - nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" - if test "$nls_cv_force_use_gnu_gettext" != "yes"; then - CATOBJEXT=NONE - - - - - ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 -echo "configure:3357: checking for libintl.h" >&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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3367: \"$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 - echo $ac_n "checking for GNU gettext in libc""... $ac_c" 1>&6 -echo "configure:3384: checking for GNU gettext in libc" >&5 -if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -extern int _nl_msg_cat_cntr; -int main() { -bindtextdomain ("", ""); -return (int) gettext ("") + _nl_msg_cat_cntr -; return 0; } -EOF -if { (eval echo configure:3398: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - gt_cv_func_gnugettext1_libc=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - gt_cv_func_gnugettext1_libc=no -fi -rm -f conftest* -fi - -echo "$ac_t""$gt_cv_func_gnugettext1_libc" 1>&6 - - if test "$gt_cv_func_gnugettext1_libc" != "yes"; then - echo $ac_n "checking for GNU gettext in libintl""... $ac_c" 1>&6 -echo "configure:3414: checking for GNU gettext in libintl" >&5 -if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libintl'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - gt_save_LIBS="$LIBS" - LIBS="$LIBS -lintl $LIBICONV" - cat > conftest.$ac_ext < -extern int _nl_msg_cat_cntr; -int main() { -bindtextdomain ("", ""); -return (int) gettext ("") + _nl_msg_cat_cntr -; return 0; } -EOF -if { (eval echo configure:3430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - gt_cv_func_gnugettext1_libintl=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - gt_cv_func_gnugettext1_libintl=no -fi -rm -f conftest* - LIBS="$gt_save_LIBS" -fi - -echo "$ac_t""$gt_cv_func_gnugettext1_libintl" 1>&6 - fi - - if test "$gt_cv_func_gnugettext1_libc" = "yes" \ - || { test "$gt_cv_func_gnugettext1_libintl" = "yes" \ - && test "$PACKAGE" != gettext; }; then - cat >> confdefs.h <<\EOF -#define HAVE_GETTEXT 1 -EOF - - - if test "$gt_cv_func_gnugettext1_libintl" = "yes"; then - INTLLIBS="-lintl $LIBICONV" - fi - - gt_save_LIBS="$LIBS" - LIBS="$LIBS $INTLLIBS" - for ac_func in dcgettext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3463: 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 < -/* 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 $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 + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include #else -$ac_func(); +# include #endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : -; return 0; } -EOF -if { (eval echo configure:3491: \"$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" + # Broken: fails on valid input. +continue fi -rm -f conftest* +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi -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 </dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 else - echo "$ac_t""no" 1>&6 + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +case $host_os in + *linux*) + linux=true + +$as_echo "#define HAVE_LINUX 1" >>confdefs.h + + ;; + *freebsd*) + bsd=true + +$as_echo "#define HAVE_FREEBSD 1" >>confdefs.h + + ;; + *darwin*) + bsd=true + +$as_echo "#define HAVE_DARWIN 1" >>confdefs.h + + ;; + *solaris*) + solaris=true + +$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h + + ;; + *openbsd*) + bsd=true + +$as_echo "#define HAVE_OPENBSD 1" >>confdefs.h + + ;; + *netbsd*) + bsd=true + +$as_echo "#define HAVE_NETBSD 1" >>confdefs.h + + ;; + *dragonfly*) + bsd=true + +$as_echo "#define HAVE_DRAGONFLY 1" >>confdefs.h + + ;; + *bsd*) + bsd=true + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Unknown BSD variant" >&5 +$as_echo "$as_me: WARNING: \"Unknown BSD variant" >&2;} + +$as_echo "#define HAVE_BSD 1" >>confdefs.h + + ;; + *cygwin*) + cygwin=true + +$as_echo "#define HAVE_CYGWIN 1" >>confdefs.h + + ;; + *mingw*) + mingw=true + +$as_echo "#define HAVE_MINGW 1" >>confdefs.h + + LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32" + ;; + *) + as_fn_error $? "\"Unknown operating system.\"" "$LINENO" 5 + ;; +esac + +# Check whether --enable-uml was given. +if test "${enable_uml+set}" = set; then : + enableval=$enable_uml; if test "x$enable_uml" = "xyes"; then : + +$as_echo "#define ENABLE_UML 1" >>confdefs.h + + uml=true + +else + uml=false +fi + +else + uml=false + +fi + + +# Check whether --enable-vde was given. +if test "${enable_vde+set}" = set; then : + enableval=$enable_vde; if test "x$enable_vde" = "xyes"; then : + for ac_header in libvdeplug_dyn.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libvdeplug_dyn.h" "ac_cv_header_libvdeplug_dyn_h" "$ac_includes_default" +if test "x$ac_cv_header_libvdeplug_dyn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBVDEPLUG_DYN_H 1 +_ACEOF + +else + as_fn_error $? "VDE plug header files not found." "$LINENO" 5; break +fi + done - LIBS="$gt_save_LIBS" - # Extract the first word of "msgfmt", so it can be a program name with args. -set dummy msgfmt; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3520: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +$as_echo "#define ENABLE_VDE 1" >>confdefs.h + + vde=true + else - case "$MSGFMT" in - /*) - ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if $ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1; then - ac_cv_path_MSGFMT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" - ;; -esac -fi -MSGFMT="$ac_cv_path_MSGFMT" -if test "$MSGFMT" != ":"; then - echo "$ac_t""$MSGFMT" 1>&6 -else - echo "$ac_t""no" 1>&6 + vde=false fi - # Extract the first word of "gmsgfmt", so it can be a program name with args. -set dummy gmsgfmt; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3554: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 else - case "$GMSGFMT" in - /*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. - ;; - ?:/*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. - ;; - *) - 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_path_GMSGFMT="$ac_dir/$ac_word" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" - ;; -esac -fi -GMSGFMT="$ac_cv_path_GMSGFMT" -if test -n "$GMSGFMT"; then - echo "$ac_t""$GMSGFMT" 1>&6 -else - echo "$ac_t""no" 1>&6 + vde=false + fi - # Extract the first word of "xgettext", so it can be a program name with args. -set dummy xgettext; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3591: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +# Check whether --enable-tunemu was given. +if test "${enable_tunemu+set}" = set; then : + enableval=$enable_tunemu; if test "x$enable_tunemu" = "xyes"; then : + +$as_echo "#define ENABLE_TUNEMU 1" >>confdefs.h + + tunemu=true + else - case "$XGETTEXT" in - /*) - ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if $ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1; then - ac_cv_path_XGETTEXT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" - ;; -esac + tunemu=false fi -XGETTEXT="$ac_cv_path_XGETTEXT" -if test "$XGETTEXT" != ":"; then - echo "$ac_t""$XGETTEXT" 1>&6 + else - echo "$ac_t""no" 1>&6 + tunemu=false + fi - CATOBJEXT=.gmo - fi - -else - echo "$ac_t""no" 1>&6 + +# Check whether --with-windows2000 was given. +if test "${with_windows2000+set}" = set; then : + withval=$with_windows2000; if test "x$with_windows2000" = "xyes"; then : + +$as_echo "#define WITH_WINDOWS2000 1" >>confdefs.h + fi - if test "$CATOBJEXT" = "NONE"; then - nls_cv_use_gnu_gettext=yes - fi - fi - - if test "$nls_cv_use_gnu_gettext" = "yes"; then - INTLOBJS="\$(GETTOBJS)" - # Extract the first word of "msgfmt", so it can be a program name with args. -set dummy msgfmt; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3641: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - case "$MSGFMT" in - /*) - ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if $ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1; then - ac_cv_path_MSGFMT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" - ;; -esac -fi -MSGFMT="$ac_cv_path_MSGFMT" -if test "$MSGFMT" != ":"; then - echo "$ac_t""$MSGFMT" 1>&6 -else - echo "$ac_t""no" 1>&6 fi - # Extract the first word of "gmsgfmt", so it can be a program name with args. -set dummy gmsgfmt; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3675: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + + +# Check whether --with-systemd was given. +if test "${with_systemd+set}" = set; then : + withval=$with_systemd; systemd=true; systemd_path="$with_systemd" else - case "$GMSGFMT" in - /*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. - ;; - ?:/*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. - ;; - *) - 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_path_GMSGFMT="$ac_dir/$ac_word" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" - ;; -esac -fi -GMSGFMT="$ac_cv_path_GMSGFMT" -if test -n "$GMSGFMT"; then - echo "$ac_t""$GMSGFMT" 1>&6 -else - echo "$ac_t""no" 1>&6 + systemd=false + fi - # Extract the first word of "xgettext", so it can be a program name with args. -set dummy xgettext; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3711: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + +if test "x$with_systemd" = "xyes"; then : + systemd_path="\${libdir}/systemd/system" else - case "$XGETTEXT" in - /*) - ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if $ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1; then - ac_cv_path_XGETTEXT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" - ;; -esac -fi -XGETTEXT="$ac_cv_path_XGETTEXT" -if test "$XGETTEXT" != ":"; then - echo "$ac_t""$XGETTEXT" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - - BUILD_INCLUDED_LIBINTL=yes - USE_INCLUDED_LIBINTL=yes - CATOBJEXT=.gmo - INTLLIBS="\$(top_builddir)/intl/libintl.a $LIBICONV" - LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` - fi - - if test "$GMSGFMT" != ":"; then - if $GMSGFMT --statistics /dev/null >/dev/null 2>&1; then - : ; - else - echo "$ac_t""found msgfmt program is not GNU msgfmt; ignore it" 1>&6 - GMSGFMT=":" - fi - fi - - if test "$XGETTEXT" != ":"; then - if $XGETTEXT --omit-header /dev/null >/dev/null 2>&1; then - : ; - else - echo "$ac_t""found xgettext program is not GNU xgettext; ignore it" 1>&6 - XGETTEXT=":" - fi - fi - - POSUB=po - fi - - - - if test "$PACKAGE" = gettext; then - BUILD_INCLUDED_LIBINTL=yes - fi - - for ac_prog in bison -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:3782: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_INTLBISON'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$INTLBISON"; then - ac_cv_prog_INTLBISON="$INTLBISON" # 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_INTLBISON="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" + if test "x$with_systemd" = "xno"; then : + systemd=false fi fi -INTLBISON="$ac_cv_prog_INTLBISON" -if test -n "$INTLBISON"; then - echo "$ac_t""$INTLBISON" 1>&6 + +systemd_path=$systemd_path + + + if test "$linux" = true; then + LINUX_TRUE= + LINUX_FALSE='#' else - echo "$ac_t""no" 1>&6 + LINUX_TRUE='#' + LINUX_FALSE= fi -test -n "$INTLBISON" && break -done + if test "$bsd" = true; then + BSD_TRUE= + BSD_FALSE='#' +else + BSD_TRUE='#' + BSD_FALSE= +fi - if test -z "$INTLBISON"; then - ac_verc_fail=yes - else - echo $ac_n "checking version of bison""... $ac_c" 1>&6 -echo "configure:3815: checking version of bison" >&5 - ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` - case $ac_prog_version in - '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; - 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) - ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; - *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + if test "$solaris" = true; then + SOLARIS_TRUE= + SOLARIS_FALSE='#' +else + SOLARIS_TRUE='#' + SOLARIS_FALSE= +fi + + if test "$mingw" = true; then + MINGW_TRUE= + MINGW_FALSE='#' +else + MINGW_TRUE='#' + MINGW_FALSE= +fi + + if test "$cygwin" = true; then + CYGWIN_TRUE= + CYGWIN_FALSE='#' +else + CYGWIN_TRUE='#' + CYGWIN_FALSE= +fi + + if test "$uml" = true; then + UML_TRUE= + UML_FALSE='#' +else + UML_TRUE='#' + UML_FALSE= +fi + + if test "$vde" = true; then + VDE_TRUE= + VDE_FALSE='#' +else + VDE_TRUE='#' + VDE_FALSE= +fi + + if test "$tunemu" = true; then + TUNEMU_TRUE= + TUNEMU_FALSE='#' +else + TUNEMU_TRUE='#' + TUNEMU_FALSE= +fi + + if test "$systemd" = true; then + WITH_SYSTEMD_TRUE= + WITH_SYSTEMD_FALSE='#' +else + WITH_SYSTEMD_TRUE='#' + WITH_SYSTEMD_FALSE= +fi + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac - echo "$ac_t""$ac_prog_version" 1>&6 + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi fi - if test $ac_verc_fail = yes; then - INTLBISON=: - fi - - for lang in $ALL_LINGUAS; do - GMOFILES="$GMOFILES $lang.gmo" - POFILES="$POFILES $lang.po" - done - - - - - - - - - - - - nls_cv_header_intl= - nls_cv_header_libgt= - - DATADIRNAME=share - - - INSTOBJEXT=.mo - - - GENCAT=gencat - - - - if test "x$CATOBJEXT" != "x"; then - if test "x$ALL_LINGUAS" = "x"; then - LINGUAS= - else - echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 -echo "configure:3862: checking for catalogs to be installed" >&5 - NEW_LINGUAS= - for presentlang in $ALL_LINGUAS; do - useit=no - for desiredlang in ${LINGUAS-$ALL_LINGUAS}; do - # Use the presentlang catalog if desiredlang is - # a. equal to presentlang, or - # b. a variant of presentlang (because in this case, - # presentlang can be used as a fallback for messages - # which are not translated in the desiredlang catalog). - case "$desiredlang" in - "$presentlang"*) useit=yes;; - esac - done - if test $useit = yes; then - NEW_LINGUAS="$NEW_LINGUAS $presentlang" - fi - done - LINGUAS=$NEW_LINGUAS - echo "$ac_t""$LINGUAS" 1>&6 - fi - - if test -n "$LINGUAS"; then - for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done - fi - fi - - MKINSTALLDIRS= - if test -n "$ac_aux_dir"; then - MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" - fi - if test -z "$MKINSTALLDIRS"; then - MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" - fi - - - INTL_LIBTOOL_SUFFIX_PREFIX= - - - - - -echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:3905: checking for socket" >&5 -if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* 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 socket(); - -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_socket) || defined (__stub___socket) -choke me -#else -socket(); -#endif - -; return 0; } -EOF -if { (eval echo configure:3933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_socket=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_socket=no" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi fi -rm -f conftest* +rm -f confcache + +if test -d /sw/include ; then + CPPFLAGS="$CPPFLAGS -I/sw/include" +fi +if test -d /sw/lib ; then + LIBS="$LIBS -L/sw/lib" fi -if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then - echo "$ac_t""yes" 1>&6 + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CFLAGS for maximum warnings" >&5 +$as_echo_n "checking CFLAGS for maximum warnings... " >&6; } +if ${ac_cv_cflags_warn_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_cflags_warn_all="no, unknown" +ac_save_CFLAGS="$CFLAGS" +for ac_arg in "-warn all % -warn all" "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" # +do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +CFLAGS="$ac_save_CFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags_warn_all" >&5 +$as_echo "$ac_cv_cflags_warn_all" >&6; } + + +case ".$ac_cv_cflags_warn_all" in + .ok|.ok,*) ;; + .|.no|.no,*) ;; + *) if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" $ac_cv_cflags_warn_all "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$ac_cv_cflags_warn_all"; } >&5 + (: CFLAGS already contains $ac_cv_cflags_warn_all) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_warn_all\""; } >&5 + (: CFLAGS="$CFLAGS $ac_cv_cflags_warn_all") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS $ac_cv_cflags_warn_all" + ;; + esac +else + CFLAGS="$ac_cv_cflags_warn_all" +fi + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Check whether --enable-hardening was given. +if test "${enable_hardening+set}" = set; then : + enableval=$enable_hardening; +fi + +if test "x$enable_hardening" != "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -DFORTIFY_SOURCE=2" >&5 +$as_echo_n "checking whether C compiler accepts -DFORTIFY_SOURCE=2... " >&6; } +if ${ax_cv_check_cflags___DFORTIFY_SOURCE_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -DFORTIFY_SOURCE=2" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___DFORTIFY_SOURCE_2=yes +else + ax_cv_check_cflags___DFORTIFY_SOURCE_2=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___DFORTIFY_SOURCE_2" >&5 +$as_echo "$ax_cv_check_cflags___DFORTIFY_SOURCE_2" >&6; } +if test x"$ax_cv_check_cflags___DFORTIFY_SOURCE_2" = xyes; then : + CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2" +else : -else - echo "$ac_t""no" 1>&6 +fi - echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 -echo "configure:3952: checking for connect in -lsocket" >&5 -ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fwrapv" >&5 +$as_echo_n "checking whether C compiler accepts -fwrapv... " >&6; } +if ${ax_cv_check_cflags___fwrapv+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_save_LIBS="$LIBS" + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fwrapv" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fwrapv=yes +else + ax_cv_check_cflags___fwrapv=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fwrapv" >&5 +$as_echo "$ax_cv_check_cflags___fwrapv" >&6; } +if test x"$ax_cv_check_cflags___fwrapv" = xyes; then : + CPPFLAGS="$CPPFLAGS -fwrapv" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-strict-overflow" >&5 +$as_echo_n "checking whether C compiler accepts -fno-strict-overflow... " >&6; } +if ${ax_cv_check_cflags___fno_strict_overflow+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fno-strict-overflow" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fno_strict_overflow=yes +else + ax_cv_check_cflags___fno_strict_overflow=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_strict_overflow" >&5 +$as_echo "$ax_cv_check_cflags___fno_strict_overflow" >&6; } +if test x"$ax_cv_check_cflags___fno_strict_overflow" = xyes; then : + CPPFLAGS="$CPPFLAGS -fno-strict-overflow" +else + : +fi + +fi + + case $host_os in + *mingw*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--dynamicbase" >&5 +$as_echo_n "checking whether the linker accepts -Wl,--dynamicbase... " >&6; } +if ${ax_cv_check_ldflags___Wl___dynamicbase+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--dynamicbase" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl___dynamicbase=yes +else + ax_cv_check_ldflags___Wl___dynamicbase=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___dynamicbase" >&5 +$as_echo "$ax_cv_check_ldflags___Wl___dynamicbase" >&6; } +if test x"$ax_cv_check_ldflags___Wl___dynamicbase" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,--dynamicbase" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--nxcompat" >&5 +$as_echo_n "checking whether the linker accepts -Wl,--nxcompat... " >&6; } +if ${ax_cv_check_ldflags___Wl___nxcompat+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--nxcompat" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl___nxcompat=yes +else + ax_cv_check_ldflags___Wl___nxcompat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___nxcompat" >&5 +$as_echo "$ax_cv_check_ldflags___Wl___nxcompat" >&6; } +if test x"$ax_cv_check_ldflags___Wl___nxcompat" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,--nxcompat" +else + : +fi + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fPIE" >&5 +$as_echo_n "checking whether C compiler accepts -fPIE... " >&6; } +if ${ax_cv_check_cflags___fPIE+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fPIE" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fPIE=yes +else + ax_cv_check_cflags___fPIE=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fPIE" >&5 +$as_echo "$ax_cv_check_cflags___fPIE" >&6; } +if test x"$ax_cv_check_cflags___fPIE" = xyes; then : + CPPFLAGS="$CPPFLAGS -fPIE" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -pie" >&5 +$as_echo_n "checking whether the linker accepts -pie... " >&6; } +if ${ax_cv_check_ldflags___pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___pie=yes +else + ax_cv_check_ldflags___pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___pie" >&5 +$as_echo "$ax_cv_check_ldflags___pie" >&6; } +if test x"$ax_cv_check_ldflags___pie" = xyes; then : + LDFLAGS="$LDFLAGS -pie" +else + : +fi + + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,relro" >&5 +$as_echo_n "checking whether the linker accepts -Wl,-z,relro... " >&6; } +if ${ax_cv_check_ldflags___Wl__z_relro+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-z,relro" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl__z_relro=yes +else + ax_cv_check_ldflags___Wl__z_relro=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_relro" >&5 +$as_echo "$ax_cv_check_ldflags___Wl__z_relro" >&6; } +if test x"$ax_cv_check_ldflags___Wl__z_relro" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,-z,relro" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,now" >&5 +$as_echo_n "checking whether the linker accepts -Wl,-z,now... " >&6; } +if ${ax_cv_check_ldflags___Wl__z_now+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-z,now" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl__z_now=yes +else + ax_cv_check_ldflags___Wl__z_now=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_now" >&5 +$as_echo "$ax_cv_check_ldflags___Wl__z_now" >&6; } +if test x"$ax_cv_check_ldflags___Wl__z_now" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,-z,now" +else + : +fi + + + +fi; + + + +for ac_header in syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working __malloc__ attribute" >&5 +$as_echo_n "checking for working __malloc__ attribute... " >&6; } +if ${tinc_cv_attribute___malloc__+:} false; then : + $as_echo_n "(cached) " >&6 +else + + tempcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wall -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void *test(void) __attribute__ ((__malloc__)); + void *test(void) { return (void *)0; } + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tinc_cv_attribute___malloc__=yes +else + tinc_cv_attribute___malloc__=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$tempcflags" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tinc_cv_attribute___malloc__" >&5 +$as_echo "$tinc_cv_attribute___malloc__" >&6; } + + if test ${tinc_cv_attribute___malloc__} = no; then + +$as_echo "#define __malloc__ /**/" >>confdefs.h + + fi + + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SOCKLEN_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ether_header" "ac_cv_type_struct_ether_header" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_ether_header" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ETHER_HEADER 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct arphdr" "ac_cv_type_struct_arphdr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_arphdr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ARPHDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ether_arp" "ac_cv_type_struct_ether_arp" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_ether_arp" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ETHER_ARP 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct in_addr" "ac_cv_type_struct_in_addr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_in_addr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN_ADDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_addrinfo" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ADDRINFO 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ip" "ac_cv_type_struct_ip" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_ip" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IP 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct icmp" "ac_cv_type_struct_icmp" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_icmp" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ICMP 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_in6_addr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN6_ADDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ip6_hdr" "ac_cv_type_struct_ip6_hdr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_ip6_hdr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IP6_HDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct icmp6_hdr" "ac_cv_type_struct_icmp6_hdr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_icmp6_hdr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ICMP6_HDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct nd_neighbor_solicit" "ac_cv_type_struct_nd_neighbor_solicit" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_nd_neighbor_solicit" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ND_NEIGHBOR_SOLICIT 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct nd_opt_hdr" "ac_cv_type_struct_nd_opt_hdr" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_type_struct_nd_opt_hdr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ND_OPT_HDR 1 +_ACEOF + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_signal=int +else + ac_cv_type_signal=void +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +for ac_func in asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" +if test "x$ac_cv_func_getopt_long" = xyes; then : + getopt=true; +$as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h + +else + getopt=false +fi + + if test "$getopt" = true; then + GETOPT_TRUE= + GETOPT_FALSE='#' +else + GETOPT_TRUE='#' + GETOPT_FALSE= +fi + + + +ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" +if test "x$ac_cv_func_socket" = xyes; then : + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if ${ac_cv_lib_socket_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext +/* end confdefs.h. */ -int main() { -connect() -; return 0; } -EOF -if { (eval echo configure:3971: \"$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" +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_connect=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ac_cv_lib_socket_connect=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_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 socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF LIBS="-lsocket $LIBS" -else - echo "$ac_t""no" 1>&6 fi fi -echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:4002: checking for gethostbyname" >&5 -if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + else - cat > conftest.$ac_ext < -/* 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 gethostbyname(); -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_gethostbyname) || defined (__stub___gethostbyname) -choke me -#else -gethostbyname(); -#endif - -; return 0; } -EOF -if { (eval echo configure:4030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_gethostbyname=yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_gethostbyname=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then - echo "$ac_t""yes" 1>&6 - : -else - echo "$ac_t""no" 1>&6 - - echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:4049: checking for gethostbyname in -lnsl" >&5 -ac_lib_var=`echo nsl'_'gethostbyname | 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" + ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext +/* end confdefs.h. */ -int main() { -gethostbyname() -; return 0; } -EOF -if { (eval echo configure:4068: \"$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" +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ac_cv_lib_nsl_gethostbyname=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_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 nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF LIBS="-lnsl $LIBS" +fi + + +fi + + +ac_fn_c_check_decl "$LINENO" "freeaddrinfo" "ac_cv_have_decl_freeaddrinfo" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_have_decl_freeaddrinfo" = xyes; then : + ac_have_decl=1 else - echo "$ac_t""no" 1>&6 + ac_have_decl=0 fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FREEADDRINFO $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "gai_strerror" "ac_cv_have_decl_gai_strerror" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_have_decl_gai_strerror" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GAI_STRERROR $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_have_decl_getaddrinfo" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETADDRINFO $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "getnameinfo" "ac_cv_have_decl_getnameinfo" "#include \"$srcdir/src/have.h\" + +" +if test "x$ac_cv_have_decl_getnameinfo" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETNAMEINFO $ac_have_decl +_ACEOF + + +ac_fn_c_check_decl "$LINENO" "res_init" "ac_cv_have_decl_res_init" " + #include + #include + +" +if test "x$ac_cv_have_decl_res_init" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_RES_INIT $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_init in -lresolv" >&5 +$as_echo_n "checking for res_init in -lresolv... " >&6; } +if ${ac_cv_lib_resolv_res_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char res_init (); +int +main () +{ +return res_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_resolv_res_init=yes +else + ac_cv_lib_resolv_res_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_init" >&5 +$as_echo "$ac_cv_lib_resolv_res_init" >&6; } +if test "x$ac_cv_lib_resolv_res_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBRESOLV 1 +_ACEOF + + LIBS="-lresolv $LIBS" + +fi fi -cat > confcache <<\EOF +cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. # -# 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. +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. # -EOF +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. +# So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. -(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 +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else - echo "not updating unwritable cache $cache_file" + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache -# Check whether --with-kernel or --without-kernel was given. -if test "${with_kernel+set}" = set; then - withval="$with_kernel" - kerneldir="$withval" + # Check whether --enable-zlib was given. +if test "${enable_zlib+set}" = set; then : + enableval=$enable_zlib; +fi + + if test "x$enable_zlib" != "xno"; then : + + +$as_echo "#define HAVE_ZLIB 1" >>confdefs.h + + +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; zlib="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + +fi + + + +# Check whether --with-zlib-include was given. +if test "${with_zlib_include+set}" = set; then : + withval=$with_zlib_include; zlib_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval" + +fi + + + +# Check whether --with-zlib-lib was given. +if test "${with_zlib_lib+set}" = set; then : + withval=$with_zlib_lib; zlib_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval" + +fi + + + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + else - kerneldir="/usr/src/linux" + as_fn_error $? "\"zlib header files not found.\"" "$LINENO" 5; break fi - -echo $ac_n "checking for linux/if_tun.h""... $ac_c" 1>&6 -echo "configure:4159: checking for linux/if_tun.h" >&5 -if eval "test \"`echo '$''{'tinc_cv_linux_if_tun_h'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - if_tun_h="\"$kerneldir/include/linux/if_tun.h\"" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - cat > conftest.$ac_ext < -int main() { -int a = IFF_TAP; -; return 0; } -EOF -if { (eval echo configure:4187: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - if_tun_h="default" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - if_tun_h="no" - -fi -rm -f conftest* - -fi -rm -f conftest* - - if test $if_tun_h = no; then - tinc_cv_linux_if_tun_h=none - else - tinc_cv_linux_if_tun_h="$if_tun_h" - fi - -fi - -echo "$ac_t""$tinc_cv_linux_if_tun_h" 1>&6 - -if test $tinc_cv_linux_if_tun_h != none; then - cat >> confdefs.h <<\EOF -#define HAVE_TUNTAP 1 -EOF - - if test $tinc_cv_linux_if_tun_h != default; then - cat >> confdefs.h <&6 -echo "configure:4253: 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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4263: \"$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 <&6 -{ echo "configure: error: "OpenSSL header files not found."" 1>&2; exit 1; }; break - -fi done - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - echo $ac_n "checking for SHA1_version in -lcrypto""... $ac_c" 1>&6 -echo "configure:4295: checking for SHA1_version in -lcrypto" >&5 -ac_lib_var=`echo crypto'_'SHA1_version | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress2 in -lz" >&5 +$as_echo_n "checking for compress2 in -lz... " >&6; } +if ${ac_cv_lib_z_compress2+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_save_LIBS="$LIBS" -LIBS="-lcrypto $LIBS" -cat > conftest.$ac_ext <&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 -lcrypto" -else - echo "$ac_t""no" 1>&6 -{ echo "configure: error: "OpenSSL libraries not found."" 1>&2; exit 1; } - -fi - - - for ac_func in RAND_pseudo_bytes -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4340: 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 < -/* 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 $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:4368: \"$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 <&6 -fi -done - - - echo $ac_n "checking for OpenSSL_add_all_algorithms""... $ac_c" 1>&6 -echo "configure:4394: checking for OpenSSL_add_all_algorithms" >&5 -if eval "test \"`echo '$''{'ac_cv_func_OpenSSL_add_all_algorithms'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* 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 OpenSSL_add_all_algorithms(); - -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_OpenSSL_add_all_algorithms) || defined (__stub___OpenSSL_add_all_algorithms) -choke me -#else -OpenSSL_add_all_algorithms(); -#endif - -; return 0; } -EOF -if { (eval echo configure:4422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_OpenSSL_add_all_algorithms=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_OpenSSL_add_all_algorithms=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'OpenSSL_add_all_algorithms`\" = yes"; then - echo "$ac_t""yes" 1>&6 - : -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for SSLeay_add_all_algorithms""... $ac_c" 1>&6 -echo "configure:4440: checking for SSLeay_add_all_algorithms" >&5 -if eval "test \"`echo '$''{'ac_cv_func_SSLeay_add_all_algorithms'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* 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 SSLeay_add_all_algorithms(); - -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_SSLeay_add_all_algorithms) || defined (__stub___SSLeay_add_all_algorithms) -choke me -#else -SSLeay_add_all_algorithms(); -#endif - -; return 0; } -EOF -if { (eval echo configure:4468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_SSLeay_add_all_algorithms=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_SSLeay_add_all_algorithms=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'SSLeay_add_all_algorithms`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_SSLEAY_ADD_ALL_ALGORITHMS 1 -EOF - -else - echo "$ac_t""no" 1>&6 -{ echo "configure: error: "Missing required OpenSSL functionality!"" 1>&2; exit 1; } - -fi - - -fi - - - echo $ac_n "checking for dlopen""... $ac_c" 1>&6 -echo "configure:4497: 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 < -/* 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:4525: \"$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 - : -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:4543: 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 <&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 -ldl" -else - echo "$ac_t""no" 1>&6 -{ echo "configure: error: "OpenSSL depends on libdl."" 1>&2; exit 1; } - -fi - - -fi - - - - tinc_ac_save_CPPFLAGS="$CPPFLAGS" - - # Check whether --with-zlib-include or --without-zlib-include was given. -if test "${with_zlib_include+set}" = set; then - withval="$with_zlib_include" - zlib_include="$withval" - CFLAGS="$CFLAGS -I$withval" - CPPFLAGS="$CPPFLAGS -I$withval" - -fi - - - # Check whether --with-zlib-lib or --without-zlib-lib was given. -if test "${with_zlib_lib+set}" = set; then - withval="$with_zlib_lib" - zlib_lib="$withval" - LIBS="$LIBS -L$withval" - -fi - - - for ac_hdr in zlib.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4614: 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 -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4624: \"$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 <&6 -{ echo "configure: error: "zlib header files not found."" 1>&2; exit 1; }; break - -fi -done - - - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - echo $ac_n "checking for compress2 in -lz""... $ac_c" 1>&6 -echo "configure:4656: checking for compress2 in -lz" >&5 -ac_lib_var=`echo z'_'compress2 | 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" + ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext +/* end confdefs.h. */ -int main() { -compress2() -; return 0; } -EOF -if { (eval echo configure:4675: \"$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" +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char compress2 (); +int +main () +{ +return compress2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_compress2=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ac_cv_lib_z_compress2=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress2" >&5 +$as_echo "$ac_cv_lib_z_compress2" >&6; } +if test "x$ac_cv_lib_z_compress2" = xyes; then : LIBS="$LIBS -lz" else - echo "$ac_t""no" 1>&6 -{ echo "configure: error: "zlib libraries not found."" 1>&2; exit 1; } - -fi - - - -# Check whether --enable-jumbograms or --disable-jumbograms was given. -if test "${enable_jumbograms+set}" = set; then - enableval="$enable_jumbograms" - cat >> confdefs.h <<\EOF -#define ENABLE_JUMBOGRAMS 1 -EOF - + as_fn_error $? "\"zlib libraries not found.\"" "$LINENO" 5 fi -# Check whether --enable-tracing or --disable-tracing was given. -if test "${enable_tracing+set}" = set; then - enableval="$enable_tracing" - cat >> confdefs.h <<\EOF -#define ENABLE_TRACING 1 -EOF - +fi + + + # Check whether --enable-lzo was given. +if test "${enable_lzo+set}" = set; then : + enableval=$enable_lzo; +fi + + if test "x$enable_lzo" != "xno"; then : + + +$as_echo "#define HAVE_LZO 1" >>confdefs.h + + +# Check whether --with-lzo was given. +if test "${with_lzo+set}" = set; then : + withval=$with_lzo; lzo="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" fi +# Check whether --with-lzo-include was given. +if test "${with_lzo_include+set}" = set; then : + withval=$with_lzo_include; lzo_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval" -trap '' 1 2 15 -cat > confcache <<\EOF +fi + + + +# Check whether --with-lzo-lib was given. +if test "${with_lzo_lib+set}" = set; then : + withval=$with_lzo_lib; lzo_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval" + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzo1x_1_compress in -llzo2" >&5 +$as_echo_n "checking for lzo1x_1_compress in -llzo2... " >&6; } +if ${ac_cv_lib_lzo2_lzo1x_1_compress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzo1x_1_compress (); +int +main () +{ +return lzo1x_1_compress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzo2_lzo1x_1_compress=yes +else + ac_cv_lib_lzo2_lzo1x_1_compress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_lzo1x_1_compress" >&5 +$as_echo "$ac_cv_lib_lzo2_lzo1x_1_compress" >&6; } +if test "x$ac_cv_lib_lzo2_lzo1x_1_compress" = xyes; then : + LIBS="$LIBS -llzo2" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzo1x_1_compress in -llzo" >&5 +$as_echo_n "checking for lzo1x_1_compress in -llzo... " >&6; } +if ${ac_cv_lib_lzo_lzo1x_1_compress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzo1x_1_compress (); +int +main () +{ +return lzo1x_1_compress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzo_lzo1x_1_compress=yes +else + ac_cv_lib_lzo_lzo1x_1_compress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo_lzo1x_1_compress" >&5 +$as_echo "$ac_cv_lib_lzo_lzo1x_1_compress" >&6; } +if test "x$ac_cv_lib_lzo_lzo1x_1_compress" = xyes; then : + LIBS="$LIBS -llzo" +else + as_fn_error $? "\"lzo libraries not found.\"" "$LINENO" 5; break + +fi + + +fi + + + for ac_header in lzo/lzo1x.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzo/lzo1x.h" "ac_cv_header_lzo_lzo1x_h" "$ac_includes_default" +if test "x$ac_cv_header_lzo_lzo1x_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZO_LZO1X_H 1 +_ACEOF + +$as_echo "#define LZO1X_H " >>confdefs.h + +else + for ac_header in lzo2/lzo1x.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzo2/lzo1x.h" "ac_cv_header_lzo2_lzo1x_h" "$ac_includes_default" +if test "x$ac_cv_header_lzo2_lzo1x_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZO2_LZO1X_H 1 +_ACEOF + +$as_echo "#define LZO1X_H " >>confdefs.h + +else + for ac_header in lzo1x.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzo1x.h" "ac_cv_header_lzo1x_h" "$ac_includes_default" +if test "x$ac_cv_header_lzo1x_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZO1X_H 1 +_ACEOF + +$as_echo "#define LZO1X_H " >>confdefs.h + +else + as_fn_error $? "\"lzo header files not found.\"" "$LINENO" 5; break + +fi + +done + + +fi + +done + + +fi + +done + + +fi + + + case $host_os in + *mingw*) + ;; + *) + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + LIBS="$LIBS -ldl" +else + as_fn_error $? "LibreSSL/OpenSSL depends on libdl." "$LINENO" 5; break + +fi + + +fi + + ;; + esac + + +# Check whether --with-openssl was given. +if test "${with_openssl+set}" = set; then : + withval=$with_openssl; openssl="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + +fi + + + +# Check whether --with-openssl-include was given. +if test "${with_openssl_include+set}" = set; then : + withval=$with_openssl_include; openssl_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval" + +fi + + + +# Check whether --with-openssl-lib was given. +if test "${with_openssl_lib+set}" = set; then : + withval=$with_openssl_lib; openssl_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval" + +fi + + + for ac_header in openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + as_fn_error $? "LibreSSL/OpenSSL header files not found." "$LINENO" 5; break + +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_EncryptInit_ex in -lcrypto" >&5 +$as_echo_n "checking for EVP_EncryptInit_ex in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_EVP_EncryptInit_ex+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char EVP_EncryptInit_ex (); +int +main () +{ +return EVP_EncryptInit_ex (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_EVP_EncryptInit_ex=yes +else + ac_cv_lib_crypto_EVP_EncryptInit_ex=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_EncryptInit_ex" >&5 +$as_echo "$ac_cv_lib_crypto_EVP_EncryptInit_ex" >&6; } +if test "x$ac_cv_lib_crypto_EVP_EncryptInit_ex" = xyes; then : + LIBS="-lcrypto $LIBS" +else + as_fn_error $? "LibreSSL/OpenSSL libraries not found." "$LINENO" 5 + +fi + + + for ac_func in RAND_bytes EVP_EncryptInit_ex EVP_CIPHER_CTX_new +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break +fi +done + + + ac_fn_c_check_decl "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_have_decl_OpenSSL_add_all_algorithms" "#include + +" +if test "x$ac_cv_have_decl_OpenSSL_add_all_algorithms" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break +fi +ac_fn_c_check_decl "$LINENO" "EVP_aes_256_cfb" "ac_cv_have_decl_EVP_aes_256_cfb" "#include + +" +if test "x$ac_cv_have_decl_EVP_aes_256_cfb" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_EVP_AES_256_CFB $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break +fi + + + for ac_func in BN_GENCB_new RSA_set0_key +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +# Check whether --enable-jumbograms was given. +if test "${enable_jumbograms+set}" = set; then : + enableval=$enable_jumbograms; if test "x$enable_jumbograms" = "xyes"; then : + +$as_echo "#define ENABLE_JUMBOGRAMS 1" >>confdefs.h + +fi + + +fi + + +if test "x$runstatedir" = "x"; then + runstatedir='${localstatedir}/run' + +fi + +ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile systemd/Makefile" + + +cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. # -# 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. +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. # -EOF +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. +# So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. -(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 +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else - echo "not updating unwritable cache $cache_file" + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache -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} +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS <&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then + as_fn_error $? "conditional \"LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BSD_TRUE}" && test -z "${BSD_FALSE}"; then + as_fn_error $? "conditional \"BSD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SOLARIS_TRUE}" && test -z "${SOLARIS_FALSE}"; then + as_fn_error $? "conditional \"SOLARIS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MINGW_TRUE}" && test -z "${MINGW_FALSE}"; then + as_fn_error $? "conditional \"MINGW\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CYGWIN_TRUE}" && test -z "${CYGWIN_FALSE}"; then + as_fn_error $? "conditional \"CYGWIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${UML_TRUE}" && test -z "${UML_FALSE}"; then + as_fn_error $? "conditional \"UML\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${VDE_TRUE}" && test -z "${VDE_FALSE}"; then + as_fn_error $? "conditional \"VDE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${TUNEMU_TRUE}" && test -z "${TUNEMU_FALSE}"; then + as_fn_error $? "conditional \"TUNEMU\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_SYSTEMD_TRUE}" && test -z "${WITH_SYSTEMD_FALSE}"; then + as_fn_error $? "conditional \"WITH_SYSTEMD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GETOPT_TRUE}" && test -z "${GETOPT_FALSE}"; then + as_fn_error $? "conditional \"GETOPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. # Run this file to recreate the current configuration. -# 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. +# 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 +debug=false +ac_cs_recheck=false +ac_cs_silent=false -ac_given_srcdir=$srcdir -ac_given_INSTALL="$INSTALL" +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -trap 'rm -fr `echo "Makefile -src/Makefile -doc/Makefile -doc/es/Makefile -intl/Makefile -lib/Makefile -m4/Makefile -po/Makefile.in - config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS < 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%@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%@CPP@%$CPP%g -s%@LN_S@%$LN_S%g -s%@PERL@%$PERL%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%@LIBOBJS@%$LIBOBJS%g -s%@ALLOCA@%$ALLOCA%g -s%@RANLIB@%$RANLIB%g -s%@GLIBC21@%$GLIBC21%g -s%@LIBICONV@%$LIBICONV%g -s%@USE_NLS@%$USE_NLS%g -s%@MSGFMT@%$MSGFMT%g -s%@GMSGFMT@%$GMSGFMT%g -s%@XGETTEXT@%$XGETTEXT%g -s%@INTLBISON@%$INTLBISON%g -s%@BUILD_INCLUDED_LIBINTL@%$BUILD_INCLUDED_LIBINTL%g -s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g -s%@CATALOGS@%$CATALOGS%g -s%@CATOBJEXT@%$CATOBJEXT%g -s%@GMOFILES@%$GMOFILES%g -s%@INTLLIBS@%$INTLLIBS%g -s%@INTLOBJS@%$INTLOBJS%g -s%@POFILES@%$POFILES%g -s%@POSUB@%$POSUB%g -s%@DATADIRNAME@%$DATADIRNAME%g -s%@INSTOBJEXT@%$INSTOBJEXT%g -s%@GENCAT@%$GENCAT%g -s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g -s%@INTL_LIBTOOL_SUFFIX_PREFIX@%$INTL_LIBTOOL_SUFFIX_PREFIX%g -s%@LINUX_IF_TUN_H@%$LINUX_IF_TUN_H%g -s%@HAVE_TUNTAP@%$HAVE_TUNTAP%g -s%@INCLUDES@%$INCLUDES%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 +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac fi -EOF -cat >> $CONFIG_STATUS <> $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'` +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' else - ac_dir_suffix= ac_dots= + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' fi - - 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 <> $CONFIG_STATUS <<\EOF + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' 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 +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi - 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 +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" -# 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 : +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH do - 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 <> $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 + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done -rm -f conftest.vals +PS1='$ ' +PS2='> ' +PS4='+ ' -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 +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi -fi; done + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error -EOF -cat >> $CONFIG_STATUS < "\$am_dir"stamp-h\$am_indx + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by tinc $as_me 1.0.36, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +tinc config.status 1.0.36 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift ;; esac - am_indx=\`expr \$am_indx + 1\` -done -AMDEP_TRUE="$AMDEP_TRUE" -ac_aux_dir="$ac_aux_dir" + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; -EOF -cat >> $CONFIG_STATUS <<\EOF -test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; -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 + shift done -for ac_file in $CONFIG_FILES; do - # Support "outfile[:infile[:infile...]]" - case "$ac_file" in - *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - esac - # PO directories have a Makefile.in generated from Makefile.in.in. - case "$ac_file" in */Makefile.in) - # Adjust a relative srcdir. - ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" - ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` - # In autoconf-2.13 it is called $ac_given_srcdir. - # In autoconf-2.50 it is called $srcdir. - test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" - case "$ac_given_srcdir" in - .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; - /*) top_srcdir="$ac_given_srcdir" ;; - *) top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then - rm -f "$ac_dir/POTFILES" - test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" - sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," -e "\$s/\(.*\) \\\\/\1/" < "$ac_given_srcdir/$ac_dir/POTFILES.in" > "$ac_dir/POTFILES" - test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" - sed -e "/POTFILES =/r $ac_dir/POTFILES" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" - fi - ;; - esac - done +ac_configure_extra_args= -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 +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "systemd/Makefile") CONFIG_FILES="$CONFIG_FILES systemd/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? + done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk +} + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..ca2948a --- /dev/null +++ b/configure.ac @@ -0,0 +1,247 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.61) +AC_INIT([tinc], [1.0.36]) +AC_CONFIG_SRCDIR([src/tincd.c]) +AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) +AM_SILENT_RULES([yes]) + +# Enable GNU extensions. +# Define this here, not in acconfig's @TOP@ section, since definitions +# in the latter don't make it into the configure-time tests. +AC_GNU_SOURCE +AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions]) + +dnl Checks for programs. +AC_PROG_CC_C99 +AC_PROG_CPP +AC_PROG_INSTALL + +AM_PROG_CC_C_O + +dnl Check and set OS + +AC_CANONICAL_HOST + +case $host_os in + *linux*) + linux=true + AC_DEFINE(HAVE_LINUX, 1, [Linux]) + ;; + *freebsd*) + bsd=true + AC_DEFINE(HAVE_FREEBSD, 1, [FreeBSD]) + ;; + *darwin*) + bsd=true + AC_DEFINE(HAVE_DARWIN, 1, [Darwin (MacOS/X)]) + ;; + *solaris*) + solaris=true + AC_DEFINE(HAVE_SOLARIS, 1, [Solaris/SunOS]) + ;; + *openbsd*) + bsd=true + AC_DEFINE(HAVE_OPENBSD, 1, [OpenBSD]) + ;; + *netbsd*) + bsd=true + AC_DEFINE(HAVE_NETBSD, 1, [NetBSD]) + ;; + *dragonfly*) + bsd=true + AC_DEFINE(HAVE_DRAGONFLY, 1, [DragonFly]) + ;; + *bsd*) + bsd=true + AC_MSG_WARN("Unknown BSD variant, tinc might not compile or work!") + AC_DEFINE(HAVE_BSD, 1, [Unknown BSD variant]) + ;; + *cygwin*) + cygwin=true + AC_DEFINE(HAVE_CYGWIN, 1, [Cygwin]) + ;; + *mingw*) + mingw=true + AC_DEFINE(HAVE_MINGW, 1, [MinGW]) + LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32" + ;; + *) + AC_MSG_ERROR("Unknown operating system.") + ;; +esac + +AC_ARG_ENABLE(uml, + AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]), + [ AS_IF([test "x$enable_uml" = "xyes"], + [ AC_DEFINE(ENABLE_UML, 1, [Support for UML]) + uml=true + ], + [uml=false]) + ], + [uml=false] +) + +AC_ARG_ENABLE(vde, + AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]), + [ AS_IF([test "x$enable_vde" = "xyes"], + [ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break]) + AC_DEFINE(ENABLE_VDE, 1, [Support for VDE]) + vde=true + ], + [vde=false]) + ], + [vde=false] +) + +AC_ARG_ENABLE(tunemu, + AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]), + [ AS_IF([test "x$enable_tunemu" = "xyes"], + [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu]) + tunemu=true + ], + [tunemu=false]) + ], + [tunemu=false] +) + +AC_ARG_WITH(windows2000, + AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]), + [ AS_IF([test "x$with_windows2000" = "xyes"], + [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]) + ] +) + +AC_ARG_WITH(systemd, + AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]), + [ systemd=true; systemd_path="$with_systemd" ], + [ systemd=false ] +) + +AS_IF([test "x$with_systemd" = "xyes"], [systemd_path="\${libdir}/systemd/system"], + [AS_IF([test "x$with_systemd" = "xno"], [systemd=false])]) + +AC_SUBST(systemd_path, $systemd_path) + +AM_CONDITIONAL(LINUX, test "$linux" = true) +AM_CONDITIONAL(BSD, test "$bsd" = true) +AM_CONDITIONAL(SOLARIS, test "$solaris" = true) +AM_CONDITIONAL(MINGW, test "$mingw" = true) +AM_CONDITIONAL(CYGWIN, test "$cygwin" = true) +AM_CONDITIONAL(UML, test "$uml" = true) +AM_CONDITIONAL(VDE, test "$vde" = true) +AM_CONDITIONAL(TUNEMU, test "$tunemu" = true) +AM_CONDITIONAL(WITH_SYSTEMD, test "$systemd" = true) + +AC_CACHE_SAVE + +if test -d /sw/include ; then + CPPFLAGS="$CPPFLAGS -I/sw/include" +fi +if test -d /sw/lib ; then + LIBS="$LIBS -L/sw/lib" +fi + +dnl Compiler hardening flags +dnl No -fstack-protector-all because it doesn't work on all platforms or architectures. + +AX_CFLAGS_WARN_ALL(CFLAGS) + +AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [disable compiler and linker hardening flags])) +AS_IF([test "x$enable_hardening" != "xno"], + [AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"]) + AX_CHECK_COMPILE_FLAG([-fwrapv], [CPPFLAGS="$CPPFLAGS -fwrapv"], + AX_CHECK_COMPILE_FLAG([-fno-strict-overflow], [CPPFLAGS="$CPPFLAGS -fno-strict-overflow"])) + case $host_os in + *mingw*) + AX_CHECK_LINK_FLAG([-Wl,--dynamicbase], [LDFLAGS="$LDFLAGS -Wl,--dynamicbase"]) + AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [LDFLAGS="$LDFLAGS -Wl,--nxcompat"]) + ;; + *) + AX_CHECK_COMPILE_FLAG([-fPIE], [CPPFLAGS="$CPPFLAGS -fPIE"]) + AX_CHECK_LINK_FLAG([-pie], [LDFLAGS="$LDFLAGS -pie"]) + ;; + esac + AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"]) + AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"]) + ] +); + +dnl Checks for libraries. + +dnl Checks for header files. +dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies. + +AC_CHECK_HEADERS([syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.h]) +AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h], + [], [], [#include "$srcdir/src/have.h"] +) +AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h], + [], [], [#include "$srcdir/src/have.h"] +) +AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h], + [], [], [#include "$srcdir/src/have.h"] +) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_PID_T + +tinc_ATTRIBUTE(__malloc__) + +AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , , + [#include "$srcdir/src/have.h"] +) + +dnl Checks for library functions. +AC_TYPE_SIGNAL +AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname], + [], [], [#include "$srcdir/src/have.h"] +) + +AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false]) +AM_CONDITIONAL(GETOPT, test "$getopt" = true) + +dnl Support for SunOS + +AC_CHECK_FUNC(socket, [], [ + AC_CHECK_LIB(socket, connect) +]) +AC_CHECK_FUNC(gethostbyname, [], [ + AC_CHECK_LIB(nsl, gethostbyname) +]) + +AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo], + [], [], [#include "$srcdir/src/have.h"] +) + +AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [ + #include + #include +]) + +AC_CACHE_SAVE + +dnl These are defined in files in m4/ + +tinc_ZLIB +tinc_LZO +tinc_OPENSSL + +dnl Check if support for jumbograms is requested +AC_ARG_ENABLE(jumbograms, + AS_HELP_STRING([--enable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]), + [ AS_IF([test "x$enable_jumbograms" = "xyes"], + [ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ]) + ] +) + +dnl Ensure runstatedir is set if we are using a version of autoconf that does not support it +if test "x$runstatedir" = "x"; then + AC_SUBST([runstatedir], ['${localstatedir}/run']) +fi + +AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile systemd/Makefile]) + +AC_OUTPUT diff --git a/configure.in b/configure.in deleted file mode 100644 index 6114a08..0000000 --- a/configure.in +++ /dev/null @@ -1,125 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. - -dnl $Id: configure.in,v 1.13.2.43.2.1 2002/04/09 11:51:16 guus Exp $ - -AC_INIT(src/tincd.c) -AM_INIT_AUTOMAKE(tinc, 1.0pre7) -AM_CONFIG_HEADER(config.h) - -dnl Include the macros from the m4/ directory -AM_ACLOCAL_INCLUDE(m4) - -# Enable GNU extensions. -# Define this here, not in acconfig's @TOP@ section, since definitions -# in the latter don't make it into the configure-time tests. -AC_DEFINE([_GNU_SOURCE], [__USE_BSD]) - -ALL_LINGUAS="nl" - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_GCC_TRADITIONAL -AC_PROG_AWK -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_MAKE_SET -jm_PERL - - -AC_ISC_POSIX - -dnl Check and set OS - -AC_CANONICAL_HOST - -case $host_os in - *linux*) - AC_DEFINE(HAVE_LINUX) - [ rm -f src/device.c; ln -sf linux/device.c src/device.c ] - ;; - *freebsd*) - AC_DEFINE(HAVE_FREEBSD) - [ rm -f src/device.c; ln -sf freebsd/device.c src/device.c ] - ;; - *solaris*) - AC_DEFINE(HAVE_SOLARIS) - [ rm -f src/device.c; ln -sf solaris/device.c src/device.c ] - ;; - *openbsd*) - AC_DEFINE(HAVE_OPENBSD) - [ rm -f src/device.c; ln -sf openbsd/device.c src/device.c ] - ;; - *netbsd*) - AC_DEFINE(HAVE_NETBSD) - [ rm -f src/device.c; ln -sf netbsd/device.c src/device.c ] - ;; -esac - -AC_CACHE_SAVE - -dnl Checks for libraries. - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h limits.h sys/ioctl.h syslog.h unistd.h \ -sys/time.h malloc.h strings.h sys/file.h]) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_HEADER_TIME -AC_STRUCT_TM - -dnl Checks for library functions. -AC_FUNC_MEMCMP -AC_FUNC_ALLOCA -AC_TYPE_SIGNAL -AC_CHECK_FUNCS([ftime socket select strtol strerror flock unsetenv \ -asprintf putenv strdup fcloseall daemon strsignal get_current_dir_name]) -jm_FUNC_MALLOC -jm_FUNC_REALLOC - -AM_GNU_GETTEXT - - -dnl Support for SunOS - -AC_CHECK_FUNC(socket, [], [ - AC_CHECK_LIB(socket, connect) -]) -AC_CHECK_FUNC(gethostbyname, [], [ - AC_CHECK_LIB(nsl, gethostbyname) -]) - -AC_CACHE_SAVE - -dnl These are defined in files in m4/ -tinc_TUNTAP -tinc_OPENSSL -tinc_ZLIB - -dnl Check if support for jumbograms is requested -AC_ARG_ENABLE(jumbograms, - [ --enable-jumbograms enable support for jumbograms (packets up to 9000 bytes)], - [ AC_DEFINE(ENABLE_JUMBOGRAMS) ] -) - -dnl Check if checkpoint tracing has to be enabled -AC_ARG_ENABLE(tracing, - [ --enable-tracing enable checkpoint tracing (debugging only)], - [ AC_DEFINE(ENABLE_TRACING) ] -) - -AC_SUBST(INCLUDES) - -AC_OUTPUT(Makefile -src/Makefile -doc/Makefile -doc/es/Makefile -intl/Makefile -lib/Makefile -m4/Makefile -po/Makefile.in -) diff --git a/debian/Makefile b/debian/Makefile deleted file mode 100644 index 948aa39..0000000 --- a/debian/Makefile +++ /dev/null @@ -1,202 +0,0 @@ -# Generated automatically from Makefile.in by configure. -# Makefile.in generated automatically by automake 1.4 from Makefile.am - -# Copyright (C) 1994, 1995-8, 1999 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 = /usr -exec_prefix = ${prefix} - -bindir = ${exec_prefix}/bin -sbindir = ${exec_prefix}/sbin -libexecdir = ${exec_prefix}/libexec -datadir = ${prefix}/share -sysconfdir = /etc -sharedstatedir = ${prefix}/com -localstatedir = /var -libdir = ${exec_prefix}/lib -infodir = ${prefix}/share/info -mandir = ${prefix}/share/man -includedir = ${prefix}/include -oldincludedir = /usr/include - -DESTDIR = - -pkgdatadir = $(datadir)/tinc -pkglibdir = $(libdir)/tinc -pkgincludedir = $(includedir)/tinc - -top_builddir = .. - -ACLOCAL = aclocal -I m4 -AUTOCONF = autoconf -AUTOMAKE = automake -AUTOHEADER = autoheader - -INSTALL = /usr/bin/install -c -INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = ${INSTALL} -m 644 -INSTALL_SCRIPT = ${INSTALL_PROGRAM} -transform = s,x,x, - -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = i586-pc-linux-gnu -host_triplet = i586-pc-linux-gnu -AS = @AS@ -AWK = mawk -CATALOGS = es.gmo nl.gmo -CATOBJEXT = .gmo -CC = gcc -CPP = gcc -E -DATADIRNAME = share -DLLTOOL = @DLLTOOL@ -GENCAT = -GMOFILES = es.gmo nl.gmo -GMSGFMT = /usr/bin/msgfmt -GT_NO = -GT_YES = #YES# -HAVE_TUNTAP = -INCLUDE_LOCALE_H = #include -INSTOBJEXT = .mo -INTLDEPS = -INTLLIBS = -INTLOBJS = -LIBTOOL = @LIBTOOL@ -LINUX_IF_TUN_H = -LN_S = ln -s -MAKEINFO = makeinfo -MKINSTALLDIRS = ./mkinstalldirs -MSGFMT = /usr/bin/msgfmt -OBJDUMP = @OBJDUMP@ -PACKAGE = tinc -PERL = perl -POFILES = es.po nl.po -POSUB = po -RANLIB = ranlib -USE_INCLUDED_LIBINTL = no -USE_NLS = yes -VERSION = 1.0-cvs -l = - -EXTRA_DIST = README.Debian changelog conffiles control copyright dirs docs info init.d postinst rules doc-base.tinc - -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = ../config.h -CONFIG_CLEAN_FILES = -DIST_COMMON = Makefile.am Makefile.in - - -DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) - -TAR = tar -GZIP_ENV = --best -all: all-redirect -.SUFFIXES: -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps debian/Makefile - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -tags: TAGS -TAGS: - - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) - -subdir = debian - -distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ - d=$(srcdir); \ - if test -d $$d/$$file; then \ - cp -pr $$d/$$file $(distdir)/$$file; \ - else \ - test -f $(distdir)/$$file \ - || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ - || cp -p $$d/$$file $(distdir)/$$file || :; \ - fi; \ - done -info-am: -info: info-am -dvi-am: -dvi: dvi-am -check-am: all-am -check: check-am -installcheck-am: -installcheck: installcheck-am -install-exec-am: -install-exec: install-exec-am - -install-data-am: -install-data: install-data-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -install: install-am -uninstall-am: -uninstall: uninstall-am -all-am: Makefile -all-redirect: all-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install -installdirs: - - -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log stamp-h stamp-h[0-9]* - -maintainer-clean-generic: -mostlyclean-am: mostlyclean-generic - -mostlyclean: mostlyclean-am - -clean-am: clean-generic mostlyclean-am - -clean: clean-am - -distclean-am: distclean-generic clean-am - -rm -f libtool - -distclean: distclean-am - -maintainer-clean-am: maintainer-clean-generic distclean-am - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - -maintainer-clean: maintainer-clean-am - -.PHONY: tags distdir info-am info dvi-am dvi check check-am \ -installcheck-am installcheck install-exec-am install-exec \ -install-data-am install-data install-am install uninstall-am uninstall \ -all-redirect all-am all installdirs mostlyclean-generic \ -distclean-generic clean-generic maintainer-clean-generic clean \ -mostlyclean distclean maintainer-clean - - -# 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/debian/Makefile.am b/debian/Makefile.am deleted file mode 100644 index 6bb365b..0000000 --- a/debian/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST = README.Debian changelog conffiles control copyright dirs \ - docs info init.d postinst rules doc-base.tinc diff --git a/debian/Makefile.in b/debian/Makefile.in deleted file mode 100644 index b5008fa..0000000 --- a/debian/Makefile.in +++ /dev/null @@ -1,202 +0,0 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am - -# Copyright (C) 1994, 1995-8, 1999 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 = @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 - -DESTDIR = - -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@ $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -transform = @program_transform_name@ - -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = @host_alias@ -host_triplet = @host@ -AS = @AS@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DLLTOOL = @DLLTOOL@ -GENCAT = @GENCAT@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GT_NO = @GT_NO@ -GT_YES = @GT_YES@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ -INSTOBJEXT = @INSTOBJEXT@ -INTLDEPS = @INTLDEPS@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -LIBTOOL = @LIBTOOL@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MAKEINFO = @MAKEINFO@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJDUMP = @OBJDUMP@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -l = @l@ - -EXTRA_DIST = README.Debian changelog conffiles control copyright dirs docs info init.d postinst rules doc-base.tinc - -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = ../config.h -CONFIG_CLEAN_FILES = -DIST_COMMON = Makefile.am Makefile.in - - -DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) - -TAR = tar -GZIP_ENV = --best -all: all-redirect -.SUFFIXES: -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps debian/Makefile - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -tags: TAGS -TAGS: - - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) - -subdir = debian - -distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ - d=$(srcdir); \ - if test -d $$d/$$file; then \ - cp -pr $$d/$$file $(distdir)/$$file; \ - else \ - test -f $(distdir)/$$file \ - || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ - || cp -p $$d/$$file $(distdir)/$$file || :; \ - fi; \ - done -info-am: -info: info-am -dvi-am: -dvi: dvi-am -check-am: all-am -check: check-am -installcheck-am: -installcheck: installcheck-am -install-exec-am: -install-exec: install-exec-am - -install-data-am: -install-data: install-data-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -install: install-am -uninstall-am: -uninstall: uninstall-am -all-am: Makefile -all-redirect: all-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install -installdirs: - - -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log stamp-h stamp-h[0-9]* - -maintainer-clean-generic: -mostlyclean-am: mostlyclean-generic - -mostlyclean: mostlyclean-am - -clean-am: clean-generic mostlyclean-am - -clean: clean-am - -distclean-am: distclean-generic clean-am - -rm -f libtool - -distclean: distclean-am - -maintainer-clean-am: maintainer-clean-generic distclean-am - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - -maintainer-clean: maintainer-clean-am - -.PHONY: tags distdir info-am info dvi-am dvi check check-am \ -installcheck-am installcheck install-exec-am install-exec \ -install-data-am install-data install-am install uninstall-am uninstall \ -all-redirect all-am all installdirs mostlyclean-generic \ -distclean-generic clean-generic maintainer-clean-generic clean \ -mostlyclean distclean maintainer-clean - - -# 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/debian/NEWS b/debian/NEWS new file mode 100644 index 0000000..b3eb367 --- /dev/null +++ b/debian/NEWS @@ -0,0 +1,14 @@ +tinc (1.0.27-1) unstable; urgency=medium + + This package now provides native systemd service files, allowing multiple + instances of tinc to be managed. Existing networks listed in + /etc/tinc/nets.boot will be converted to service instances once during this + upgrade. Afterwards, you can enable and disable networks using: + + systemctl enable tinc@ + systemctl disable tinc@ + + If you do not have systemd installed, the SysV init script will continue to + work as usual. For more information, see README.Debian. + + -- Guus Sliepen Sun, 10 Apr 2016 01:33:55 +0200 diff --git a/debian/README.Debian b/debian/README.Debian index 5a4c224..d911295 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -1,10 +1,80 @@ tinc for Debian ----------------------- +--------------- The manual for tinc is also available as info pages, type `info tinc' to read it. -The system startup script for tinc, /etc/init.d/tinc, uses the file -/etc/tinc/nets.boot to find out which networks have to be started. +There are several ways in which tinc may be automatically started at boot: - -- Ivo Timmermans , Wed, 31 May 2000, 19:56:05 +0200 +Systemd +------- + +Since 1.0.27-1, the tinc package comes with native systemd service files. +To enable and start a net, call: + +systemctl enable tinc@ +systemctl start tinc@ + +This will cause a tincd to be started which uses the configuration from +/etc/tinc/, and also makes sure that it will be started next time your +system boots. + +Apart from controlling individual instances, you can also start/stop/reload all +enabled instances simultaneously by omitting @, for example: + +systemctl reload tinc + +Note that when you have systemd installed on your system, the file +/etc/tinc/nets.boot will not be used anymore to automatically start tinc +daemons. If the variable EXTRA is defined in /etc/default/tinc, it will be +passed on to tinc. The variable LIMITS is however not used. + +The service files that come with this package start tinc unconditionally. +However, tinc does support socket activation. If you wish to write a socket +unit for tinc, use the ListenStream option to specify on which port(s) and +address(es) tinc should listen. + +SysVinit +-------- + +The system startup script for tinc, /etc/init.d/tinc, uses the file +/etc/tinc/nets.boot to find out which networks have to be started. Use one +netname per line. Lines starting with a # are ignored. + +/etc/network/interfaces +----------------------- + +You can create a stanza in /etc/network/interfaces, and add a line with +"tinc-net ". This will cause a tincd to be started which uses the +configuration from /etc/tinc/. You can use an inet static (with +address and netmask options) or inet dhcp stanza, in which case the ifup will +configure the VPN interface and you do not need to have a tinc-up script. + +The following options are also recognized and map directly to the corresponding +command line options for tincd: + +tinc-config +tinc-debug +tinc-mlock yes +tinc-logfile +tinc-pidfile +tinc-chroot yes +tinc-user + +An example stanza: + +iface vpn inet static + address 192.168.2.42 + netmask 255.255.0.0 + tinc-net myvpn + tinc-debug 1 + tinc-mlock yes + tinc-user nobody + tinc-pidfile /tmp/tinc.pid + +This will start a tinc daemon that reads its configuration from +/etc/tinc/myvpn, logs at debug level 1, locks itself in RAM, runs as user +nobody, and creates a network interface called "vpn". Ifup then sets the +address and netmask on that interface. + + -- Guus Sliepen , Sun, 10 April 2016, 01:38:08 +0200 diff --git a/debian/changelog b/debian/changelog index fbb00c9..04508d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,502 @@ +tinc (1.0.36-2) unstable; urgency=medium + + * Disable support for libvdeplug. Closes: #973233 + + -- Guus Sliepen Sun, 22 Nov 2020 10:40:27 +0100 + +tinc (1.0.36-1) unstable; urgency=medium + + * New upstream version 1.0.36 + * Add Vcs tags to debian/control. + * Bump Standards-Version. + + -- Guus Sliepen Mon, 26 Aug 2019 14:17:21 +0200 + +tinc (1.0.35-2) unstable; urgency=medium + + * Bump Standards-Version and Build-Depend on debhelper-compat (= 12). + * Remove calls to dh_installinit and dh_systemd_start from debian/rules, + compat level 12 does the right thing by default. + * Ensure we clean up doc/tinc.info. + + -- Guus Sliepen Mon, 28 Jan 2019 21:54:45 +0100 + +tinc (1.0.35-1) unstable; urgency=medium + + * New upstream release. + - Includes fixes for CVE-2018-16737, CVE-2018-16738, CVE-2018-16758. + + -- Guus Sliepen Mon, 08 Oct 2018 16:09:06 +0200 + +tinc (1.0.34-1) unstable; urgency=medium + + [ Guus Sliepen ] + * New upstream release. + - Fixes a potential segmentation fault when connecting to an IPv6 + peer via a proxy. Closes: #887401 + * Add support for the $EXTRA variable in /etc/default/tinc when using + systemd. Closes: #887116 + + [ Benda Xu ] + * Prevent possible incorrect IPv6 checksums due to function inlining. + Closes: #891400 + + -- Guus Sliepen Tue, 12 Jun 2018 23:00:49 +0200 + +tinc (1.0.33-1) unstable; urgency=medium + + * New upstream release. + * Test for /etc/default/tinc before trying to source it. Closes: #777262 + * Use --runstatedir=/run. + + -- Guus Sliepen Sat, 04 Nov 2017 16:22:06 +0100 + +tinc (1.0.32-1) unstable; urgency=medium + + * New upstream release. + * Add a note to new nets.boot files that it is not used with systemd. + Closes: #841052 + * In the post-down script, read the pid file only once. Closes: #832784 + * Explicitly use /bin/sleep from coreutils. Closes: #772379 + * Bump Standards-Version. + + -- Guus Sliepen Tue, 05 Sep 2017 20:23:36 +0200 + +tinc (1.0.31-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version. + * Bump debian/compat. + * Add missing Depends: lsb-base. + + -- Guus Sliepen Sun, 15 Jan 2017 16:20:40 +0100 + +tinc (1.0.29-2) unstable; urgency=medium + + * Rebuild with libssl-dev from unstable. + + -- Guus Sliepen Thu, 27 Oct 2016 13:09:46 +0200 + +tinc (1.0.29-1) unstable; urgency=medium + + * New upstream release. + * Bump debian/compat. + + -- Guus Sliepen Mon, 10 Oct 2016 22:30:25 +0200 + +tinc (1.0.28-1) unstable; urgency=medium + + * New upstream release. + - Fixes FTBFS on kfreebsd. + * Systemd service files are now provided by upstream. + + -- Guus Sliepen Sun, 10 Apr 2016 15:44:28 +0200 + +tinc (1.0.27-2) unstable; urgency=medium + + * Fix tinc@.service. + + -- Guus Sliepen Sun, 10 Apr 2016 12:45:33 +0200 + +tinc (1.0.27-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version. + * Add native systemd unit files. + * Automatically convert networks listed in nets.boot to systemd service + instances on upgrade. + + -- Guus Sliepen Sun, 10 Apr 2016 01:39:16 +0200 + +tinc (1.0.26-1) unstable; urgency=medium + + * New upstream release. + * Use the contents, not the presence, of the pidfile to check that tincd is + shut down properly. Closes: #774682 + * Bump Standards-Version. + + -- Guus Sliepen Sun, 05 Jul 2015 17:23:08 +0200 + +tinc (1.0.24-2) unstable; urgency=medium + + * Improve the init script: stopping tinc now waits for the process to + terminate. If that doesn't happen in 5 seconds, it will send the TERM + signal again (which helps if tinc is waiting for a script to finish + executing). It now also detects whether the process mentioned in the PID + file is actually running, and if not it will exit early and without + warnings. Closes: #748107 + + -- Guus Sliepen Wed, 14 May 2014 21:44:16 +0200 + +tinc (1.0.24-1) unstable; urgency=medium + + [ Guus Sliepen ] + * New upstream release + * Add a debian/watch file. + * Bump Standards-Version. + + [ Gian Piero Carrubba ] + * Allow resource limits to be set in /etc/default/tinc. + Closes: #690685, #704702 + + -- Guus Sliepen Sun, 11 May 2014 21:17:13 +0200 + +tinc (1.0.23-2) unstable; urgency=low + + * Use if-statements instead of && in shell scripts. Closes: #731279 + The && operator does not clear the error status, and if the next statement + in a shell script does not change the error status it would cause the + script to prematurely exit. Thanks to Peter Reinholdtsen for spotting it. + * Use absolute path to tincd in the if-post-down script. + + -- Guus Sliepen Thu, 05 Dec 2013 09:41:13 +0000 + +tinc (1.0.23-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Sat, 19 Oct 2013 21:06:05 +0200 + +tinc (1.0.22-1) unstable; urgency=low + + * New upstream release. + - Handles whitespace between command line flags and optional arguments. + Closes: #710267 + * Bump Standards-Version. + * Source /lib/lsb/init-functions in the init.d script. + * Don't use texi2html anymore, use automake's install-html target which uses + makeinfo. + + -- Guus Sliepen Wed, 14 Aug 2013 15:34:29 +0200 + +tinc (1.0.21-1) unstable; urgency=low + + * New upstream release. + - Includes fix for CVE-2013-1428. + + -- Guus Sliepen Sun, 05 May 2013 10:42:33 +0200 + +tinc (1.0.19-3) unstable; urgency=high + + * Drop packets forwarded via TCP if they are too big (CVE-2013-1428). + + -- Guus Sliepen Fri, 12 Apr 2013 22:52:10 +0200 + +tinc (1.0.19-2) unstable; urgency=low + + * Fix behaviour of tinc-pidfile. Closes: #679130 + * Enable parallel building in debian/rules. + + -- Guus Sliepen Tue, 26 Jun 2012 18:28:34 +0200 + +tinc (1.0.19-1) unstable; urgency=low + + * New upstream release. + * Bump debian/compat so tinc gets built with hardening flags. + * Allow tinc-pidfile in /etc/network/interfaces. + + -- Guus Sliepen Mon, 25 Jun 2012 20:29:22 +0200 + +tinc (1.0.18-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Sun, 25 Mar 2012 18:52:15 +0200 + +tinc (1.0.17-1) unstable; urgency=low + + * New upstream release. + * Enable support for UML and VDE. + + -- Guus Sliepen Sat, 10 Mar 2012 14:50:00 +0100 + +tinc (1.0.16-1) unstable; urgency=low + + * New upstream release. + * Mention alarm option in /etc/init.d/tinc's usage information. + Closes: #631761 + + -- Guus Sliepen Sat, 23 Jul 2011 14:37:56 +0200 + +tinc (1.0.15-1) unstable; urgency=low + + * New upstream release. + * Send SIGALRM to running tinc daemons whenever an interface is brought up + with the ifupdown framework. Based on a patch from Joachim Breitner. + Closes: #629880 + * Allow tinc daemons to be started using ifupdown. + + -- Guus Sliepen Fri, 24 Jun 2011 18:21:51 +0200 + +tinc (1.0.14-1) unstable; urgency=low + + * New upstream release. + * Bump Standards-Version. + + -- Guus Sliepen Mon, 09 May 2011 00:25:37 +0200 + +tinc (1.0.13-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Tue, 13 Apr 2010 12:06:36 +0200 + +tinc (1.0.12-2) unstable; urgency=low + + * Remove debconf questions. Closes: #572116 + Apparently debconf may not be used to ask a question at install time and + use the answer at upgrade time. Instead of kludging around this + restriction, no questions are asked anymore, and tinc will now always be + restarted when upgrading. + * Wait up to 5 seconds for tinc daemon to stop before restarting it. + + -- Guus Sliepen Tue, 02 Mar 2010 14:01:36 +0100 + +tinc (1.0.12-1) unstable; urgency=low + + * New upstream release. + * Bump Standards-Version. + * Migrate from CDBS to debhelper. + * Convert source package to 3.0 (quilt) format. + * Remove useless tinc.modules. + * Use init.d script from Michael Tokarev, allowing per-network arguments to + tincd. + * Remove update-rc.d calls from postinst and postrm. + * Let the init.d script depend on $remote_fs. + + -- Guus Sliepen Thu, 04 Feb 2010 00:56:45 +0100 + +tinc (1.0.11-1) unstable; urgency=low + + * New upstream release. + * Cope with texi2html arbitrarily changing its output directory. + Closes: #552927 + * Do not stop tinc when configuring a new version, just restart after + the upgrade. + + -- Guus Sliepen Sun, 01 Nov 2009 20:37:16 +0100 + +tinc (1.0.10-1) unstable; urgency=low + + * New upstream release. + * Include Russian debconf translation. Closes: #548759 + + -- Guus Sliepen Sun, 18 Oct 2009 16:31:49 +0200 + +tinc (1.0.9-1) unstable; urgency=low + + * New upstream release. + - Binds IPv6 sockets only to IPv6. Closes: #440150 + * Update copyright file. Closes: #482566 + + -- Guus Sliepen Fri, 26 Dec 2008 13:25:05 +0100 + +tinc (1.0.8-2) unstable; urgency=low + + * Include Portugese debconf translation. Closes: #434191 + + -- Guus Sliepen Tue, 14 Aug 2007 13:50:27 +0200 + +tinc (1.0.8-1) unstable; urgency=low + + * New upstream release. Closes: #173987 + * Include german debconf translation. Closes: #412351 + * Build-Depend on texinfo. Closes: #424209 + + -- Guus Sliepen Wed, 16 May 2007 17:59:16 +0200 + +tinc (1.0.7-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Fri, 5 Jan 2007 15:55:42 +0100 + +tinc (1.0.6-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Mon, 18 Dec 2006 15:41:03 +0100 + +tinc (1.0.5-1) unstable; urgency=low + + * New upstream release. Closes: #391610 + * Add an LSB section to the init script. + + -- Guus Sliepen Tue, 14 Nov 2006 16:32:20 +0100 + +tinc (1.0.4-4) unstable; urgency=low + + * Include swedish debconf translation. Closes: #332963 + * Remove nets.boot on purge. Closes: #333303 + + -- Guus Sliepen Mon, 17 Oct 2005 12:34:32 +0200 + +tinc (1.0.4-3) unstable; urgency=low + + * Depend on debconf | debconf-2.0. + * Include vietnamese debconf translation. Closes: #322305 + * Include japanese debconf translation. Closes: #319591 + + -- Guus Sliepen Thu, 29 Sep 2005 11:15:34 +0200 + +tinc (1.0.4-2) unstable; urgency=low + + * Compensate for change in texinfo's output directory. Closes: #318562 + * Include Czech translation of the debconf questions. Closes: #312982 + + -- Guus Sliepen Sat, 16 Jul 2005 11:42:04 +0200 + +tinc (1.0.4-1) unstable; urgency=low + + * New upstream release. Closes: #294819 + * Update french translation of debconf template. Closes: #293371, #296148 + * Allow dashes in nets.boot. Closes: #296281 + + -- Guus Sliepen Wed, 4 May 2005 21:56:22 +0200 + +tinc (1.0.3-4) unstable; urgency=low + + * Call debconf early in postinst so it won't get confused by output + from other commands in the postinst script. Closes: #292920 + * If MAKEDEV doesn't know about net/tun, fall back to tun. + + -- Guus Sliepen Mon, 31 Jan 2005 13:27:16 +0100 + +tinc (1.0.3-3) unstable; urgency=low + + * Fix clean rule in debian/rules. + + -- Guus Sliepen Thu, 27 Jan 2005 23:16:59 +0000 + +tinc (1.0.3-2) unstable; urgency=low + + * Don't check for /dev/tap* in postinst if we don't create them anyway. + * MAKEDEV expects net/tun instead of tun. + * Don't ask if /dev/net/tun should be created, just do it. + Closes: #259489, #292450 + * Move $EXTRA from init.d/tinc to /etc/default/tinc. Closes: #281366 + + -- Guus Sliepen Thu, 27 Jan 2005 14:10:02 +0100 + +tinc (1.0.3-1) unstable; urgency=low + + * New upstream release. + * Adopting the package from Ivo. + * Use invoke-rc.d, and tell user to do so as well. Closes: #223276 + * Let force-reload do the same thing as reload. Closes: #230180 + + -- Guus Sliepen Fri, 1 Oct 2004 21:04:14 +0200 + +tinc (1.0.2-2) unstable; urgency=low + + * debian/control: Oops, really make that automake1.7. + + -- Ivo Timmermans Sat, 8 Nov 2003 21:53:04 +0100 + +tinc (1.0.2-1) unstable; urgency=low + + * New upstream release: + * Fix broken replies to CHAL_RESP. (Closes: #217646) + * debian/control: Updated automake build dependency to automake1.7. + (Closes: #219360) + + -- Ivo Timmermans Sat, 8 Nov 2003 19:56:04 +0100 + +tinc (1.0.1-2) unstable; urgency=low + + * debian/dirs: Removed, moved contents to tinc.dirs. + (Closes: #208591) + * debian/docs: Renamed to tinc.docs. + * debian/rules: Install the contents of doc/sample-config.tar.gz in + /usr/share/doc/tinc/examples instead of /etc/tinc. + * debian/Makefile*: Removed. + + -- Ivo Timmermans Wed, 10 Sep 2003 12:19:32 +0200 + +tinc (1.0.1-1) unstable; urgency=low + + * New upstream release. + * debian/patches/001_openbsd_device.c.patch: Removed. + + -- Ivo Timmermans Thu, 14 Aug 2003 17:03:28 +0200 + +tinc (1.0release-1) unstable; urgency=low + + * New upstream version. (Closes: #204639) + * Fixes switching back to normal logging mode when killing with + SIGINT twice. (Closes: #175633) + * Uses one SSL context struct for each connection, speeding up + encrypting/decrypting data; don't throw away out of sequence + packets. (Closes: #188874) + * Fixes handling of broadcast messages. (Closes: #175632) + * debian/rules: Use cdbs. + * debian/control: Build-Depend on cdbs, liblzo-dev. + * debian/patches/001_openbsd_device.c.patch: Sync openbsd/device.c to + latest CVS version. + + -- Ivo Timmermans Sun, 10 Aug 2003 16:13:29 +0200 + +tinc (1.0pre8-6) unstable; urgency=low + + * debian/po/fr.po: Added French debconf translation. (Closes: #201803) + + -- Ivo Timmermans Fri, 18 Jul 2003 10:03:20 +0200 + +tinc (1.0pre8-5) unstable; urgency=low + + * debian/*: Change to po-debconf, thanks to From: Michel Grentzinger + for the patch: + - change debhelper dependency to 4.1.16 (according to man + po-debconf), + - manually add nl translation in old tinc.templates (master), + - run debconf-gettextize debian/tinc.templates, + - move old templates files (debian/tinc.templates.*), + - change construction "If you say no" to "If you refuse", + * debian/rules: Call po2debconf. + * debian/rules: Don't copy COPYING.README to the package. + * debian/control: Update Standards-Version. + * debian/conffiles: Removed. + * debian/postinst: No longer use mknod directly, use MAKEDEV. + + -- Ivo Timmermans Tue, 15 Jul 2003 20:13:47 +0200 + +tinc (1.0pre8-4) unstable; urgency=low + + * src/net.h, src/net_packet.c, src/net_setup.c: Apply fix from CVS + for OpenSSL-related memory leaks. (Closes: #189432) + + -- Ivo Timmermans Mon, 5 May 2003 15:00:29 +0200 + +tinc (1.0pre8-3) unstable; urgency=low + + * m4/openssl.m4: Updated to CVS version. (Closes: #184400) + + -- Ivo Timmermans Thu, 13 Mar 2003 17:24:42 +0100 + +tinc (1.0pre8-2) unstable; urgency=low + + * debian/postinst: Create /dev/net/tun if it doesn't exist. + * debian/tinc.modules: Add alias for /dev/net/tun. + * debian/rules: Install tinc.modules. + * These things together: (Closes: #151967, #153156) + + -- Ivo Timmermans Wed, 13 Nov 2002 22:45:38 +0100 + +tinc (1.0pre8-1) unstable; urgency=low + + * New upstream version. + * debian/rules: + - DEB_BUILD_OPTIONS support. + - Enable --enable-tracing by default. + + -- Ivo Timmermans Tue, 17 Sep 2002 13:50:44 +0200 + +tinc (1.0pre7-3) unstable; urgency=low + + * Properly install _all_ info pages. (Closes: #144718) + + -- Ivo Timmermans Wed, 29 May 2002 14:01:21 +0200 + tinc (1.0pre7-2) unstable; urgency=low * Dutch translation wasn't being installed. diff --git a/debian/conffiles b/debian/conffiles deleted file mode 100644 index 7983a3c..0000000 --- a/debian/conffiles +++ /dev/null @@ -1 +0,0 @@ -/etc/init.d/tinc diff --git a/debian/config b/debian/config deleted file mode 100644 index ab660b8..0000000 --- a/debian/config +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -e - -# Source debconf library. -. /usr/share/debconf/confmodule - -db_title tinc configuration - -db_input medium tinc/restart_on_upgrade || true -db_go diff --git a/debian/control b/debian/control index 9c18ccf..98c0678 100644 --- a/debian/control +++ b/debian/control @@ -1,19 +1,20 @@ Source: tinc Section: net Priority: optional -Maintainer: Ivo Timmermans -Standards-Version: 3.5.6 -Build-Depends: libssl-dev, autoconf (>= 2.12), automake, debhelper, libtool, gettext, texi2html, zlib1g-dev +Maintainer: Guus Sliepen +Standards-Version: 4.4.0 +Build-Depends: libssl-dev, debhelper-compat (= 12), gettext, texinfo, zlib1g-dev, liblzo2-dev +Homepage: http://www.tinc-vpn.org/ +Vcs-Browser: https://salsa.debian.org/guus/tinc +Vcs-Git: https://salsa.debian.org/guus/tinc.git +Rules-Requires-Root: no Package: tinc Architecture: any -Depends: debconf, ${shlibs:Depends} +Pre-Depends: ${misc:Pre-Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6) Description: Virtual Private Network daemon tinc is a daemon with which you can create a virtual private network - (VPN). One daemon can handle multiple connections, so you can + (VPN). One daemon can handle multiple connections, so you can create an entire (moderately sized) VPN with only one daemon per participating computer. - . - You need to have two kernel modules installed, on a Debian system - they should already be there. If they are not, the manual will - explain you how to do that. diff --git a/debian/copyright b/debian/copyright index 49b9921..c8a6fb8 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,20 +1,34 @@ This package was debianized by Ivo Timmermans on Fri, 21 Apr 2000 17:07:50 +0200. -It was downloaded from http://tinc.nl.linux.org/ +It was downloaded from http://www.tinc-vpn.org/ -Upstream Author(s): - Guus Sliepen - Ivo Timmermans +Upstream Authors: + Guus Sliepen + Ivo Timmermans -Copyright: GPL version 2. On Debian GNU/Linux systems, the complete -text of the GNU General Public License can be found in -/usr/share/common-licenses/GPL. +Copyright (C) 1998-2005 Ivo Timmermans + 1998-2008 Guus Sliepen + 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. -The following is the text from /usr/share/doc/tinc/COPYING.README: +On Debian GNU/Linux systems, the complete text of the GNU General Public +License version 2 can be found in /usr/share/common-licenses/GPL-2. + +The following applies to tinc: This program is released under the GPL with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. You may provide binary packages linked to the OpenSSL libraries, provided that all other requirements of the GPL are met. + +The following applies to the LZO library: + +Hereby I grant a special exception to the tinc VPN project +(http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library +(http://www.openssl.org). + +Markus F.X.J. Oberhumer diff --git a/debian/dirs b/debian/dirs deleted file mode 100644 index 08152ec..0000000 --- a/debian/dirs +++ /dev/null @@ -1,3 +0,0 @@ -etc/tinc -etc/tinc/example -usr/share/doc/tinc diff --git a/debian/doc-base.tinc b/debian/doc-base.tinc index 6f28d1f..a37f46a 100644 --- a/debian/doc-base.tinc +++ b/debian/doc-base.tinc @@ -3,8 +3,8 @@ Title: tinc Manual Author: Ivo Timmermans, Guus Sliepen Abstract: This manual describes how to set up a Virtual Private Network with tinc. -Section: net +Section: System/Security Format: HTML -Files: /usr/share/doc/tinc/tinc*.html -Index: /usr/share/doc/tinc/tinc_toc.html +Files: /usr/share/doc/tinc/tinc.html/* +Index: /usr/share/doc/tinc/tinc.html/index.html diff --git a/debian/init.d b/debian/init.d deleted file mode 100644 index 5dac505..0000000 --- a/debian/init.d +++ /dev/null @@ -1,77 +0,0 @@ -#! /bin/sh -# -# System startup script for tinc -# $Id: init.d,v 1.14.2.4 2000/12/05 09:03:41 zarq Exp $ -# -# Based on Lubomir Bulej's Redhat init script. -# -# Create a file $NETSFILE (/etc/tinc/nets.boot), and put all the names of -# the networks in there. These names must be valid directory names under -# $TCONF (/etc/tinc). Lines starting with a # will be ignored in this -# file. -# - -DAEMON="/usr/sbin/tincd" -NAME="tinc" -DESC="tinc daemons" -TCONF="/etc/tinc" -EXTRA="" -NETSFILE="$TCONF/nets.boot" -NETS="" - -test -f $DAEMON || exit 0 - -find_nets () { - if [ ! -f $NETSFILE ] ; then - echo "Please create $NETSFILE." - exit 0 - fi - NETS="`egrep '^[ ]*[a-zA-Z0-9_]+[ ]*$' $NETSFILE`" -} - -case "$1" in - start) - find_nets - echo -n "Starting $DESC:" - for n in $NETS ; do - echo -n " $n" - $DAEMON -n $n $EXTRA - done - echo "." - ;; - stop) - find_nets - echo -n "Stopping $DESC:" - for n in $NETS ; do - echo -n " $n" - $DAEMON -n $n $EXTRA -k - done - echo "." - ;; - reload) - find_nets - echo -n "Reloading $DESC configuration:" - for n in $NETS ; do - echo -n " $n" - $DAEMON -n $n $EXTRA -k1 - done - echo "." - ;; - restart|force-reload) - find_nets - echo -n "Restarting $DESC:" - for n in $NETS ; do - echo -n " $n" - $DAEMON -n $n $EXTRA -k - sleep 1 - $DAEMON -n $n $EXTRA - done - echo "." - ;; - *) - echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload}" - exit 1 - ;; -esac - -exit 0 diff --git a/debian/patches/fix-incorrect-icmpv6-checksum b/debian/patches/fix-incorrect-icmpv6-checksum new file mode 100644 index 0000000..4448b88 --- /dev/null +++ b/debian/patches/fix-incorrect-icmpv6-checksum @@ -0,0 +1,65 @@ +Package: tinc +Version: 1.0.33-1 +Severity: important + +Dear Guus, + +I have been using tinc since 2009 and it is great! + +When PMTUDiscovery=yes and Mode=switch, and if ipv6 is used inside +tinc, the ICMPv6 "Packet Too Big" packets have incorrect checksums. +It can be reproduced by `ping6 -s 1800` and `tcpdump -i +`. Consequently, the host ignores the tinc-generated +ICMPv6 packets, PMTUDiscovery does not work and the connections freeze +when data flows are big. + +I find the bug is gone if the function "inet_checksum" in route.c is +not inlined, either by compiling tinc with "-O2 +-fno-inline-functions", or apply a patch such as, + +diff --git a/src/route.c b/src/route.c +index ff82c06e..cd55383a 100644 +--- a/src/route.c ++++ b/src/route.c +@@ -60,7 +60,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr); + + /* RFC 1071 */ + +-static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { ++__attribute__ ((noinline)) static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { + uint16_t *p = data; + uint32_t checksum = prevsum ^ 0xFFFF; + + + +I have tested with gcc-7.3.0 and gcc-5.4.0. They behaved the same. I +am not good at assembly to find out what really happened, but it is +for sure that inet_checksum does not work as expected if compiled +inline. + +Thanks! + +Yours, +Benda + +-- System Information: +Debian Release: buster/sid + APT prefers unstable + APT policy: (500, 'unstable') +Architecture: amd64 (x86_64) + +Kernel: Linux 4.9.0-5-amd64 (SMP w/8 CPU cores) +Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8), LANGUAGE=en_US:en (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8) +Shell: /bin/sh linked to /bin/dash +Init: sysvinit (via /sbin/init) + +Versions of packages tinc depends on: +ii libc6 2.26-2 +ii liblzo2-2 2.08-1.2+b2 +ii libssl1.1 1.1.0g-2 +ii lsb-base 9.20170808 +ii zlib1g 1:1.2.8.dfsg-5 + +tinc recommends no packages. + +tinc suggests no packages. diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..a4c8974 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,2 @@ +fix-incorrect-icmpv6-checksum +support-etc-defaults-tinc diff --git a/debian/patches/support-etc-defaults-tinc b/debian/patches/support-etc-defaults-tinc new file mode 100644 index 0000000..80b3d86 --- /dev/null +++ b/debian/patches/support-etc-defaults-tinc @@ -0,0 +1,12 @@ +--- a/systemd/tinc@.service.in ++++ b/systemd/tinc@.service.in +@@ -9,7 +9,8 @@ + [Service] + Type=simple + WorkingDirectory=@sysconfdir@/tinc/%i +-ExecStart=@sbindir@/tincd -n %i -D ++EnvironmentFile=/etc/default/tinc ++ExecStart=@sbindir@/tincd -n %i -D $EXTRA + ExecReload=@sbindir@/tincd -n %i -kHUP + KillMode=mixed + Restart=on-failure diff --git a/debian/po-Makefile.in.in.diff b/debian/po-Makefile.in.in.diff deleted file mode 100644 index b33223a..0000000 --- a/debian/po-Makefile.in.in.diff +++ /dev/null @@ -1,32 +0,0 @@ ---- Makefile.in.in.orig Thu Nov 2 20:02:58 2000 -+++ Makefile.in.in Thu Nov 2 23:25:42 2000 -@@ -24,6 +24,8 @@ - gettextsrcdir = $(prefix)/share/gettext/po - subdir = po - -+DESTDIR = -+ - INSTALL = @INSTALL@ - INSTALL_DATA = @INSTALL_DATA@ - MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@ -@@ -111,16 +113,16 @@ - install-data-no: all - install-data-yes: all - if test -r "$(MKINSTALLDIRS)"; then \ -- $(MKINSTALLDIRS) $(datadir); \ -+ $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ - else \ -- $(SHELL) $(top_srcdir)/mkinstalldirs $(datadir); \ -+ $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \ - fi - @catalogs='$(CATALOGS)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - case "$$cat" in \ -- *.gmo) destdir=$(gnulocaledir);; \ -- *) destdir=$(localedir);; \ -+ *.gmo) destdir=$(DESTDIR)$(gnulocaledir);; \ -+ *) destdir=$(DESTDIR)$(localedir);; \ - esac; \ - lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ - dir=$$destdir/$$lang/LC_MESSAGES; \ diff --git a/debian/postinst b/debian/postinst index 9b8421b..c4f5d53 100644 --- a/debian/postinst +++ b/debian/postinst @@ -1,69 +1,25 @@ #! /bin/sh -# postinst script for tinc -# -# $Id: postinst,v 1.6 2000/05/21 23:01:28 zarq Exp $ -# -# see: dh_installdeb(1) -TCONF="/etc/tinc" -NETSFILE="$TCONF/nets.boot" +NETSFILE="/etc/tinc/nets.boot" set -e -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see /usr/doc/packaging-manual/ -# -# quoting from the policy: -# Any necessary prompting should almost always be confined to the -# post-installation script, and should be protected with a conditional -# so that unnecessary prompting doesn't happen if a package's -# installation fails and the `postinst' is called with `abort-upgrade', -# `abort-remove' or `abort-deconfigure'. - case "$1" in configure) - if [ ! -e /dev/.devfsd -a ! -e /dev/.devfs ] ; then - devices_exist=1 - for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do - test -e /dev/tap$d || devices_exist=0 - done - if [ $devices_exist -eq 0 ] ; then - cat </dev/null || ./MAKEDEV tun 2>/dev/null || echo "Failed to create tun device." + fi; fi; fi + fi; fi if [ ! -e $NETSFILE ] ; then - echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE + echo "## This file contains all names of the networks to be started on system startup when using sysvinit." > $NETSFILE + echo "## If you are using systemd, use systemctl enable tinc@netname to enable individual networks." >> $NETSFILE fi ;; abort-upgrade|abort-remove|abort-deconfigure) - ;; *) @@ -72,37 +28,4 @@ EOF ;; esac -# Automatically added by dh_installinit, edited for use with debconf -if [ -x "/etc/init.d/tinc" ]; then - update-rc.d tinc defaults >/dev/null - - if [ "$1" = "configure" ] ; then - if dpkg --compare-versions "$2" lt "1.0pre5-4" ; then - /etc/init.d/tinc start - else - if [ -e /usr/share/debconf/confmodule ] ; then - . /usr/share/debconf/confmodule - db_get tinc/restart_on_upgrade - if [ "$RET" = "true" ] ; then - /etc/init.d/tinc start - else - echo "I have not stopped or restarted the tinc daemon. You should do this" - echo "yourself whenever you're ready; type \`\`/etc/init.d/tinc restart''." - fi - db_stop - else - /etc/init.d/tinc start - fi - fi - fi -fi -# End automatically added section - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - #DEBHELPER# - -exit 0 - - diff --git a/debian/postrm b/debian/postrm index 8b30ded..dc3247b 100644 --- a/debian/postrm +++ b/debian/postrm @@ -1,9 +1,9 @@ #!/bin/sh + set -e -# Automatically added by package maintainer + if [ "$1" = purge ]; then - update-rc.d tinc remove >/dev/null 2>/dev/null + rm -f /etc/tinc/nets.boot fi -# End automatically added section #DEBHELPER# diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000..721a2bd --- /dev/null +++ b/debian/preinst @@ -0,0 +1,28 @@ +#!/bin/sh + +NETSFILE="/etc/tinc/nets.boot" +SYSTEM="/lib/systemd/system" +WANTS="/etc/systemd/system/multi-user.target.wants" + +set -e + +case "$1" in + upgrade) + if dpkg --compare-versions "$2" '<<' "1.0.27-1"; then + if [ -f "$NETSFILE" ]; then + echo -n "Creating systemd service instances from nets.boot:" + mkdir -p "$WANTS" + egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do + echo -n " $net" + ln -s "$SYSTEM/tinc@.service" "$WANTS/tinc@$net.service" 2>/dev/null || true + done + echo "." + fi + fi + ;; + + *) + ;; +esac + +#DEBHELPER# diff --git a/debian/prerm b/debian/prerm deleted file mode 100644 index 1b54335..0000000 --- a/debian/prerm +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# Automatically added by dh_installinit, edited for use with debconf -if [ -x "/etc/init.d/tinc" ]; then - if [ -e /usr/share/debconf/confmodule ] ; then - . /usr/share/debconf/confmodule - db_get tinc/restart_on_upgrade - if [ "$RET" = "true" ] ; then - /etc/init.d/tinc stop - fi - db_stop - else - /etc/init.d/tinc stop - fi -fi -# End automatically added section - -#DEBHELPER# diff --git a/debian/rules b/debian/rules index 296a943..ee2949d 100755 --- a/debian/rules +++ b/debian/rules @@ -1,81 +1,16 @@ #!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -# This is the debhelper compatability version to use. -export DH_COMPAT=3 - -build: build-stamp -build-stamp: - dh_testdir - -# # If the Makefile.in.in file in po/ already contains DESTDIR support, skip the patching. - cd `pwd`/po ; ( \ - if ! grep DESTDIR Makefile.in.in > /dev/null ; then \ - patch -Ns -p0 < `pwd`/../debian/po-Makefile.in.in.diff || true ;\ - fi ;\ - ) - ./configure --prefix=/usr --mandir=\$${prefix}/share/man \ - --infodir=\$${prefix}/share/info --sysconfdir=/etc \ - --localstatedir=/var - $(MAKE) -# cd doc && texi2html -split=chapter tinc.texi - - touch build-stamp - -clean: - dh_testdir - dh_testroot - rm -f build-stamp - - -$(MAKE) distclean - rm -f src/device.c +%: + dh $@ +override_dh_clean: dh_clean + rm -f doc/tinc.info -install: build - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs +override_dh_auto_configure: + dh_auto_configure -- --enable-uml --with-systemd=/lib/systemd/system --runstatedir=/run - $(MAKE) install DESTDIR=`pwd`/debian/tmp - mkdir -p `pwd`/debian/tmp/etc/tinc/example -# cp doc/tinc.conf.sample `pwd`/debian/tmp/etc/tinc/example/tinc.conf - mkdir -p `pwd`/debian/tmp/usr/share/doc/tinc/examples - cd `pwd`/debian/tmp/usr/share/doc/tinc/examples/ && tar xfz $(PWD)/doc/sample-config.tar.gz - cp COPYING.README `pwd`/debian/tmp/usr/share/doc/tinc/ - ln -s /usr/share/doc/tinc/README.Debian `pwd`/debian/tmp/etc/tinc/example/README - p="`pwd`" ; cd $$p/debian/tmp/usr/share/doc/tinc ; texi2html -split=chapter $$p/doc/tinc.texi - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_movefiles - dh_installdocs - dh_installexamples - install -o root -g root -m 755 debian/init.d debian/tinc/etc/init.d/tinc - dh_installmanpages - dh_installinfo - dh_installchangelogs ChangeLog - dh_link - dh_strip - dh_installdebconf - dh_compress - dh_fixperms - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install +override_dh_auto_install: + dh_auto_install -- install-html + # Remove info dir file + rm -f debian/tinc/usr/share/info/dir diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/tinc-down b/debian/tinc-down deleted file mode 100644 index 9f3b499..0000000 --- a/debian/tinc-down +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# This file closes down the tap device. -# Note that if you use the universal tun/tap driver, you don't -# need to do anything; once tinc quits the tap device is already -# removed by the kernel. - -ifconfig tap0 down diff --git a/debian/tinc.default b/debian/tinc.default new file mode 100644 index 0000000..bca2432 --- /dev/null +++ b/debian/tinc.default @@ -0,0 +1,7 @@ +# Extra options to be passed to tincd. +# EXTRA="-d" + +# Limits to be configured for the tincd process. Please read your shell +# (pointed by /bin/sh) documentation for ulimit. You probably want to raise the +# max locked memory value if using both --mlock and --user flags. +# LIMITS="-l 1024" diff --git a/debian/tinc.dirs b/debian/tinc.dirs index 7f2c4e3..1eae2e2 100644 --- a/debian/tinc.dirs +++ b/debian/tinc.dirs @@ -3,4 +3,5 @@ usr/share etc etc/init.d usr/share/locale - +usr/share/doc/tinc +etc/tinc diff --git a/debian/docs b/debian/tinc.docs similarity index 100% rename from debian/docs rename to debian/tinc.docs diff --git a/debian/tinc.files b/debian/tinc.files index 439807b..3d376cc 100644 --- a/debian/tinc.files +++ b/debian/tinc.files @@ -3,3 +3,4 @@ usr/share/man etc usr/share/doc/tinc usr/share/locale +usr/share/info diff --git a/debian/tinc.if-post-down b/debian/tinc.if-post-down new file mode 100755 index 0000000..e173476 --- /dev/null +++ b/debian/tinc.if-post-down @@ -0,0 +1,41 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then + exit 0 +fi + +# Determine location of the PID file + +EXTRA="" +if [ -n "$IF_TINC_PIDFILE" ]; then + EXTRA="--pidfile=$IF_TINC_PIDFILE" +else + IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid +fi + +# Stop the tinc daemon + +read pid rest < $IF_TINC_PIDFILE 2>/dev/null + +/usr/sbin/tincd -n "$IF_TINC_NET" -k $EXTRA + +# Wait for it to shut down properly + +/bin/sleep 0.1 +i=0; +while [ -f $IF_TINC_PIDFILE ] ; do + if [ ! -e "/proc/$pid" ] ; then + exit 0 + fi + + if [ $i = '30' ] ; then + echo 'Failed to stop tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +exit 0 diff --git a/debian/tinc.if-pre-up b/debian/tinc.if-pre-up new file mode 100755 index 0000000..68a3b53 --- /dev/null +++ b/debian/tinc.if-pre-up @@ -0,0 +1,70 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then + exit 0 +fi + +# Read options from /etc/default + +[ -r /etc/default/tinc ] && . /etc/default/tinc + +# Set process limits + +setlimits() { + while [ $# -gt 0 ]; do + parm=$1 ; shift + if [ -n "$1" -a "${1#-}" = "$1" ]; then + value=$1 ; shift + ulimit $parm $value + else + ulimit $parm + fi + done +} + +test -n "$LIMITS" && setlimits $LIMITS + +# Read options from /etc/network/interfaces + +[ -n "$IF_TINC_CONFIG" ] && EXTRA="$EXTRA -c $IF_TINC_CONFIG" +[ -n "$IF_TINC_DEBUG" ] && EXTRA="$EXTRA -d$IF_TINC_DEBUG" +[ -n "$IF_TINC_MLOCK" ] && EXTRA="$EXTRA --mlock" +[ -n "$IF_TINC_LOGFILE" ] && EXTRA="$EXTRA --logfile=$IF_TINC_LOGFILE" +[ -n "$IF_TINC_PIDFILE" ] && EXTRA="$EXTRA --pidfile=$IF_TINC_PIDFILE" || IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid +[ -n "$IF_TINC_CHROOT" ] && EXTRA="$EXTRA --chroot" +[ -n "$IF_TINC_USER" ] && EXTRA="$EXTRA --user=$IF_TINC_USER" + + +# Start tinc daemon + +/usr/sbin/tincd -n "$IF_TINC_NET" -o "Interface=$IFACE" $EXTRA + +# Wait for it to come up properly + +/bin/sleep 0.1 +i=0; +while [ ! -f $IF_TINC_PIDFILE ] ; do + if [ $i = '30' ] ; then + echo 'Failed to start tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +while read pid rest < $IF_TINC_PIDFILE ; do + if [ -e "/proc/$pid" ] ; then + exit 0 + fi + + if [ $i = '30' ] ; then + echo 'Failed to start tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +exit 0 diff --git a/debian/tinc.if-up b/debian/tinc.if-up new file mode 100755 index 0000000..364f88f --- /dev/null +++ b/debian/tinc.if-up @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -n "$IF_TINC_NET" ]; then + exit 0 +fi + +invoke-rc.d tinc alarm || exit 0 diff --git a/debian/tinc.init b/debian/tinc.init new file mode 100644 index 0000000..44ff4cf --- /dev/null +++ b/debian/tinc.init @@ -0,0 +1,140 @@ +#! /bin/sh +# +### BEGIN INIT INFO +# Provides: tinc +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Should-Start: $syslog $named +# Should-Stop: $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start tinc daemons +# Description: Create a file $NETSFILE (/etc/tinc/nets.boot), +# and put all the names of the networks in there. +# These names must be valid directory names under +# $TCONF (/etc/tinc). Lines starting with a # will be +# ignored in this file. +### END INIT INFO +# +# Based on Lubomir Bulej's Redhat init script. + +. /lib/lsb/init-functions + +DAEMON="/usr/sbin/tincd" +NAME="tinc" +DESC="tinc daemons" +TCONF="/etc/tinc" +NETSFILE="$TCONF/nets.boot" +NETS="" + +test -f $DAEMON || exit 0 + +[ -r /etc/default/tinc ] && . /etc/default/tinc + +# foreach_net "what-to-say" action [arguments...] +foreach_net() { + if [ ! -f $NETSFILE ] ; then + echo "Please create $NETSFILE." + exit 0 + fi + echo -n "$1" + shift + egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do + echo -n " $net" + "$@" $net $args + done + echo "." +} + +signal_running() { + for i in /var/run/tinc.*pid; do + if [ -f "$i" ]; then + head -1 $i | while read pid; do + kill -$1 $pid + done + fi + done +} + +setlimits() { + while [ $# -gt 0 ]; do + parm=$1 ; shift + if [ -n "$1" -a "${1#-}" = "$1" ]; then + value=$1 ; shift + ulimit $parm $value + else + ulimit $parm + fi + done +} + +test -n "$LIMITS" && setlimits $LIMITS + +start() { + $DAEMON $EXTRA -n "$@" +} + +stop() { + [ -f /var/run/tinc.$1.pid ] || return + read pid rest /dev/null || return + + $DAEMON -n $1 -k || return + + i=0; + /bin/sleep 0.5 + + # Wait for the pidfile to disappear + while [ -f /var/run/tinc.$1.pid ]; do + # And check that there is an actual process running + kill -0 "$pid" 2>/dev/null || return + + if [ $i = '10' ] ; then + # It's still alive, kill it again and give up + $DAEMON -n $1 -k && /bin/sleep 0.5 + break + else + echo -n "." + i=$(($i+1)) + fi + + /bin/sleep 0.5 + done +} + +reload() { + $DAEMON -n $1 -kHUP +} + +alarm() { + $DAEMON -n $1 -kALRM +} + +restart() { + stop "$@" + start "$@" +} + +case "$1" in + start) + foreach_net "Starting $DESC:" start + ;; + stop) + foreach_net "Stopping $DESC:" stop + ;; + reload|force-reload) + foreach_net "Reloading $DESC configuration:" reload + ;; + restart) + foreach_net "Restarting $DESC:" restart + ;; + alarm) + signal_running ALRM + ;; + *) + echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload|alarm}" + exit 1 + ;; +esac + +exit 0 diff --git a/debian/tinc.modules b/debian/tinc.modules deleted file mode 100644 index 198e92a..0000000 --- a/debian/tinc.modules +++ /dev/null @@ -1,11 +0,0 @@ -alias char-major-36 netlink_dev - -alias tap0 ethertap -alias tap1 ethertap -alias tap2 ethertap -alias tap3 ethertap - -options tap0 -o tap0 -x unit=0 -options tap1 -o tap1 -x unit=1 -options tap2 -o tap2 -x unit=2 -options tap3 -o tap3 -x unit=3 diff --git a/debian/tinc.templates b/debian/tinc.templates deleted file mode 100644 index 8e07209..0000000 --- a/debian/tinc.templates +++ /dev/null @@ -1,14 +0,0 @@ -Template: tinc/restart_on_upgrade -Type: boolean -Default: true -Description: Restart tinc on each upgrade? - You may choose if you want me to restart the tinc daemon every time - you install a new version of this package. - . - Sometimes you don't want to do this, for example if you are doing the - upgrade over a tunnel that is created with tinc. Stopping the daemon - would probably leave you with a dead connection, and tinc may not be - started again. - . - If you say no, you have to restart tinc yourself if you upgraded, - by typing `/etc/init.d/tinc restart' whenever it suits you. diff --git a/debian/tinc.templates.nl b/debian/tinc.templates.nl deleted file mode 100644 index e509612..0000000 --- a/debian/tinc.templates.nl +++ /dev/null @@ -1,13 +0,0 @@ -Template: tinc/restart_on_upgrade -Description: Start tinc opnieuw na iedere upgrade? - Je kunt kiezen of ik de tinc daemon opnieuw moet starten iedere keer - als je een nieuwe versie van het pakket installeert. - . - Soms wil je dit niet doen, bij voorbeeld als je de upgrade uitvoert - over een tunnel die met tinc is gemaakt. Het stoppen van tinc - resulteert dan waarschijnlijk is een dode verbinding, en tinc wordt - dan misschien niet opnieuw gestart. - . - Als je nee antwoordt, moet je zelf tinc opnieuw starten na een - upgrade, door `/etc/init.d/tinc restart' in te tiepen wanneer het - goed uitkomt. diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc new file mode 100644 index 0000000..a79b551 --- /dev/null +++ b/debian/upstream/signing-key.asc @@ -0,0 +1,70 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBEVZzTABEADawFv/ibQ48uA1eRhL07vdM36Pcq2HDyuyNA+vYEalNH4jLmha +nGPvDALWwX0DXIWDAG8zeTj8s8zliLIjuPS4WRI2YdKIvWeG9fEvpKSXVWa42ica +dpzn/H2aBd4Ax6rQaiTXKOvxANAp2Veb+73ssPV5AL00uGTpzhh98xQzfFQCZ9ZL +YSVPqbMed5oCt/4jM9FBO2CuBtkfiO0dVVYtW7FAVjcIlE2NaZol/KGvz7wsS+yA +dE42W0l5MdQueLmTF4AIUSSTyPFGMQoyqh+MPif73Y589IGcW6GdfKYWnVDo6Trh +HOhcEky+uTYKb6NL0vrJgUiYVMzAOXFDdJni1eQGO6EfZRNYtTga3alWq/jVelK7 +BID5JyNbkrTAqdPnhJGivVyk8gGX3+Hng8rkXTfWhp6yAYau1QfBm0F2tIQmpL1C ++7DoLvFErboQf685jXJBjzyvsJxB2ZLH1OOw6mNL0hy2LFkIyGza/bktY2em4apo +KWV5AM5LpyW6THH1oDS7706xFNkf4IFhKE0hKPzBiRnMDjRtMI131lkc5+P8Lqf5 +jLTCFUgbEhU6Dz2YjhHAumVm0NWJETUpFDtVvMrqk+mp5xldUOWRNlYQC5aQOyda +eHOlNzB/BFbPhKMWI/zWlEH6f0t6WjHb4iwpWO47511aVNHF59aPzbAHxwARAQAB +tC9UaW5jIERldmVsb3BtZW50IFRlYW0gPHRpbmMtZGV2ZWxAdGluYy12cG4ub3Jn +PokCNgQTAQIAIAUCRVnNMAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEEpg +hLnA1x9KxOAQAMPhO2WTXv9AaGQBQhyyoGseKoSfcRjtI9YEfE0OInQQ2E+SPYF/ +dkfeLGAUqa4foTYQlMqfw70vBhTdVCb7HLTGn6/ICFUtDwakUQCgUQGlUVQiondA +8W6jj+QWrh5BQhHuXy2nCVaKnksu0/xQPsJotghxuYqaot3iJ4qVw9iT/Yeo9irH +Ffftqu0OVCdQ5zQuFNI9YCv/C83L59ecH7bOzYz2efTyobvxrhmgQtgOQwCWOE09 +Kr3veM9KLG33YoXlqv8QN/3CwtsJvSwfhj+R2JowZC7RqHe/yznRzmRMsgbrolxi +uiJLonGxcNNkD7WhXi7/zL4A/JaC27XrFf1MPLv8aiTwnOIfrXd5jawpauUOZOXK +UjIZHlIqviB0r5s7A+AFeHW38Tp9VzNuQ7aEl5bHbSXV+s7DTAwGb279z0AVaJ3h +5hWFxupw7UoGdzROwCBYzeX3sioAL6QvkXua8X6zOH45VEiSwrRX3Hlx/MLo7Z4g +PWgFLf6WviHQXCG834To1XIwUk9RgNsL7OzGjtaCuRymADImKMNwierq2zTfoRFQ +v9onIadIMF1fsc70hiBG9yAi36MEuk4VxG8Jc3PQQfSFm4RWazv1k3E0AAIob2Ek +DLVjvLO62Navo/OQ6D7yyiX0qes5S7/k3F1h8+87eRn3yxZE2kbxPg8KuQENBEVZ +zYYBCACoYgExmMKEtABL3pir/IXI4exR/45hkP6txFIrkVQb8DGJ9H39kiDr4gtj +F+pvcgMpec35S3m4fJ7WhDNvbDB4ZvONc1NMKs9cqDXfB+TLWPm4W+SkcKUrs+nK +i8l7ieggTALJcvRoLTX2EFmUFrD6y870W3rK2SfC/0VJX8Ou5cPbwCeueExjo5x0 +3gNfu0jWUS0cyA9y+1rVVekrLuJY/+SI4jv3gdzrYbxD0f6dpbpC37QHoJdd0KGF +acPtT2azjY+HxW10EA3Aw9oZWFXnb1nFg2RbDpkaGLmLbaXweltLyw154UmCXxym +PXPqi9bSfEkj0GiYrapk4mW114u9ABEBAAGJA0QEGAECAA8FAkVZzYcCGwIFCQHh +M4ABKQkQSmCEucDXH0rAXSAEGQECAAYFAkVZzYcACgkQ017duBDeLmmu3wf/TFZM +tLKxiyQPtGSTE3eULPdWCEMDZXdSPTY0QHM7Zvh+qn1ei+iFpD0549MYnBEAwDIV +4o62Nrcg8IPu0CEkZIAn2JiFFGYvMGk91awZGV1GS3umd7Dt349E1oKDPZVzRn+j +QIKarXxxabRmx2s/dZZgSs/eguWTboBFmvls9tVfe8x/xPvcHFmqHVUoGKEJy6Tm +no+s4yNjpc5wAaRml+GYf1tK9WMFuZn79qKxkYv4WI96dXR0FL59YbFRkkaI+1/b +G31MvWTqVjY1nJGslByFPUUB8Ca1djtp1gx6NXnOYr3V5MEDfdbjjPu79No+/y6M +tIua5yNtSRlk2nKhIqo3D/sGQ/uHijiMRAtoLhiyqYMc9W9vx/KOoCUHoMJqE39a +Eputvgwwo0rwgSmNfB1dzneFojBdJ47WBSHC8NKtkpJj6mzvvlaI9jmEpK54x3nl +OmBj3X/xaepoRGAtrmgTBP4A9hSjrTMGu/tUQjlX+Xcr6n3g7GSVe5FpUyIMPXEU ++JZDTiEUyn1OdzfNGmnWP+KJX5pQVq4czf5XK6otLZJELDVw/Hbjnjmdz5WOKgEH +jSof3WPeMBgPAcd/cMAZeiGtWM1UpJBHqEXTkthmrpmtRftJKDbooNM9d5OwKiT+ +I3vNBv/plMSr8NDjhTWC+ihrN6RBj1vaqpDgGpucPhoO2hwNqWuI4q5WUKtCyw6J +An7ErNaH4c0nVaZq6kJ8Vxdt+LpKYmOsJ8y9xtl6StcrkKNn+6ZfCfee7DEo2bvb +scfpqJqqOqb5KOagTpYs8mo6yQ3leRvFtoeBOQHVQzct23EwOMxbDyeunT50a1eH +MZTEWuIiuCUudM81QXU46oIcaAtj8tpG0Tmnku9g27EjwxUt+8kVmhlPHMb2TdoF +k5d0ce+JuxIG5+i+t8sUCorMc8zfp4g1bxZeMOcPnfyO3bSW11EVcN7ZxHlFC+XE +YOByP50CM3P8lItPlQ+WpY9kYWjiwu9kVPaGQ16G47nspngJInU5dhka3KJGtIZe +q7kBDQRFWc3GAQgAz/JUs24niKsd0ZtOjUWd4R4y0gjS0kC/vvLL2gbXYkA9tcjG +5iEvVWJY34QsudX0v1ULsVnJ89X/gsk8hAhAia1TQm+0Qq+MSxEaQkMSaOO8N70U +XzgH1dielvpea20WO4MyWQuRIJ0K2nsGmEPnt6ZP7fK8HVHFNggP/mQ6LMu1reAF +gvb8cEtjb9B5QaCUEoLjsbsuo+vLW7AWy4GfIRNESHw2Qt08AUaGrihpu6zi7N2b +QkHHJtqa63GzYJ+kYzAVvrFJXdwL/TRXLBzv+6yyvYSIHi8uB6/o6CZN6hpjfpME +ph+oYPqXeNOyMd1E9Kg8ymcPrNyQKfE3WnCRXQARAQABiQIlBBgBAgAPBQJFWc3H +AhsMBQkB4TOAAAoJEEpghLnA1x9KXYMP/3D9JYti6C8DWuX2hWv+2SUbLcMa5u1e +ETewIo5S3mqGWSaxX4YLPVRkZ1lOLmFysOLimf0thYm7IsatLcWmBdYUpK92ilvr +Sk2sKlhrOoBXEX/79Kz+Aj5PjeyiQxgQ7Ba/afwhU6aTqs2Dp1T0YNu2eBvV+1QH +lZnW2Wh96zzwc0dJUuY9eBk5Fgpu08Wce7o6jxFPtVyAaQa0zcNAmw2TSY7wbunJ +WTl9OgATAyqVCuhWW7AnPcSqkH8lQigSc00wfqJKOD2Us0FqN6UKDCZTyQkdP6hx +G+3aUkkvGSOxy7u9bVWmrikuJMoiIY/CH/m+GcJJATVibI7t5MhhtBGySKc3PAwc +58sVe9AnbDvs84efrNP59j2KG2KKqcqjTGAmKyJnG3N50xJGakDIsqfneIRNWpEE +pOOPaOqR4qnPAS9OSt9A3hqBpWPjQcScd6AuO+J2PE5y23pTnb9PtLBQb5e4VFiv +N54u8j4bU2CO0SC2isZ3CR68dPHthWsxt4XbjhgktjbpQRQ8L2EDBQ8oE13GOrOw +P8x4Q0eC5uzkXNyRqzKOsxlZEuc+75aDDd3M2GDw08FG7GI1p/L+NgenwT+9TmFX +2hOKVrjgyx+fPut1t5DJJubDWXGOK33qvrL7HTCEv1zz7LNbbPwwNHK4lfMAWuJW +D9wc3Y9Se/P/ +=5MAs +-----END PGP PUBLIC KEY BLOCK----- diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..f29609e --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=3 +opts=pgpsigurlmangle=s/$/.sig/ http://www.tinc-vpn.org/packages/tinc-(1\.0\.\d+)\.tar\.gz diff --git a/depcomp b/depcomp index 6589965..6b39162 100755 --- a/depcomp +++ b/depcomp @@ -1,7 +1,9 @@ #! /bin/sh - # depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2020 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 @@ -14,9 +16,7 @@ # 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. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -25,17 +25,112 @@ # Originally written by Alexandre Oliva . +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + 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/'`} +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" +# Avoid interferences from the environment. +gccflag= dashmflag= + # 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 @@ -47,9 +142,32 @@ if test "$depmode" = hp; then fi if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc fi case "$depmode" in @@ -57,10 +175,22 @@ 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" +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi @@ -68,13 +198,17 @@ gcc3) ;; gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). ## 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). +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then @@ -82,31 +216,31 @@ gcc) fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then 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. + # 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. +## 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 +## 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. +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. ## 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" + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -124,8 +258,7 @@ sgi) "$@" -MDupdate "$tmpdepfile" fi stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi @@ -133,106 +266,302 @@ sgi) 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 + # 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 - + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$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 + tr ' ' "$nl" < "$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" + make_dummy_depfile fi rm -f "$tmpdepfile" ;; +xlc) + # 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 + ;; + 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" + # in a .u file. In older versions, 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. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u "$@" -M fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 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" + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" 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. +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d - tmpdepfile1="$object.d" - tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` - if test "$libtool" = yes; then - "$@" -Wc,-MD - else + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. "$@" -MD - fi + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; - 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" - ;; +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 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. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # 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 + ;; #nosideeffect) # This comment above is used by automake to tell side-effect @@ -240,41 +569,49 @@ tru64) 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 + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; esac - "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" 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" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -285,74 +622,93 @@ dashXmstdout) ;; 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 + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift 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 + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 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" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | 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 + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; 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 + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" @@ -362,42 +718,56 @@ cpp) 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 + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; 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 + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" 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" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; +msvcmsys) + # 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 + ;; + none) exec "$@" ;; @@ -409,3 +779,13 @@ none) esac exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/doc/GNUmakefile b/doc/GNUmakefile deleted file mode 100644 index 8fb7a6b..0000000 --- a/doc/GNUmakefile +++ /dev/null @@ -1,23 +0,0 @@ -# Having a separate GNUmakefile lets me use features of GNU make -# to generate the man pages. -# This makefile is used only if you run GNU Make. -# It is necessary if you want to build targets usually of interest -# only to the maintainer. - -have-Makefile := $(shell test -f Makefile && echo yes) - -# If the user runs GNU make but has not yet run ./configure, -# give them a diagnostic. -ifeq ($(have-Makefile),yes) - -include Makefile -include $(srcdir)/Makefile.maint - -else - -all: - @echo There seems to be no Makefile in this directory. - @echo "You must run ./configure before running \`make'." - @exit 1 - -endif diff --git a/doc/Makefile.am b/doc/Makefile.am index b62feb7..29d6ffd 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,25 +1,35 @@ ## Process this file with automake to get Makefile.in -SUBDIRS = es - info_TEXINFOS = tinc.texi +tinc_TEXINFOS = tincinclude.texi -dyn_MANS = -man_aux = $(dyn_MANS:.8=.x) +man_MANS = tincd.8 tinc.conf.5 -man_MANS = tincd.8 tinc.conf.5 $(dyn_MANS) +EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config -PERL = @PERL@ -HELP2MAN = help2man -MAINTAINERCLEANFILES = $(dyn_MANS) +CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi -EXTRA_DIST = $(man_MANS) $(HELP2MAN) $(man_aux) \ - Makefile.maint GNUmakefile Makefile.summ sample-config.tar.gz +texi2html: tinc.texi + $(AM_V_GEN)texi2html -split=chapter $< -# Use `ginstall' in the definition of man_MANS to avoid -# confusion with the `install' target. The install rule transforms `ginstall' -# to install before applying any user-specified name transformations. -transform = s/ginstall/install/; @program_transform_name@ +tincd.8.html: tincd.8 + $(AM_V_GEN)w3mman2html $< > $@ -# For additional rules usually of interest only to the maintainer, -# see GNUmakefile and Makefile.maint. +tinc.conf.5.html: tinc.conf.5 + $(AM_V_GEN)w3mman2html $< > $@ + +substitute = sed \ + -e s,'@PACKAGE\@',"$(PACKAGE)",g \ + -e s,'@VERSION\@',"$(VERSION)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g \ + -e s,'@runstatedir\@',"$(runstatedir)",g \ + -e s,'@localstatedir\@',"$(localstatedir)",g + +tincd.8: $(srcdir)/tincd.8.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ + +tinc.conf.5: $(srcdir)/tinc.conf.5.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ + +tincinclude.texi: $(srcdir)/tincinclude.texi.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@ diff --git a/doc/Makefile.in b/doc/Makefile.in index 28ae503..81e9c93 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,7 +1,8 @@ -# Makefile.in generated automatically by automake 1.5 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. -# 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. @@ -12,528 +13,841 @@ # 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 +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ +build_triplet = @build@ host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INCLUDES = @INCLUDES@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ - -# Use `ginstall' in the definition of man_MANS to avoid -# confusion with the `install' target. The install rule transforms `ginstall' -# to install before applying any user-specified name transformations. -transform = s/ginstall/install/; @program_transform_name@ - -PERL = @PERL@ - -SUBDIRS = es - -info_TEXINFOS = tinc.texi - -dyn_MANS = -man_aux = $(dyn_MANS:.8=.x) - -man_MANS = tincd.8 tinc.conf.5 $(dyn_MANS) -HELP2MAN = help2man -MAINTAINERCLEANFILES = $(dyn_MANS) - -EXTRA_DIST = $(man_MANS) $(HELP2MAN) $(man_aux) \ - Makefile.maint GNUmakefile Makefile.summ sample-config.tar.gz - subdir = doc -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = DIST_SOURCES = -INFO_DEPS = tinc.info +AM_V_DVIPS = $(am__v_DVIPS_@AM_V@) +am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@) +am__v_DVIPS_0 = @echo " DVIPS " $@; +am__v_DVIPS_1 = +AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@) +am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@) +am__v_MAKEINFO_0 = @echo " MAKEINFO" $@; +am__v_MAKEINFO_1 = +AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@) +am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@) +am__v_INFOHTML_0 = @echo " INFOHTML" $@; +am__v_INFOHTML_1 = +AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@) +am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@) +am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@; +am__v_TEXI2DVI_1 = +AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@) +am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@) +am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@; +am__v_TEXI2PDF_1 = +AM_V_texinfo = $(am__v_texinfo_@AM_V@) +am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@) +am__v_texinfo_0 = -q +am__v_texinfo_1 = +AM_V_texidevnull = $(am__v_texidevnull_@AM_V@) +am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@) +am__v_texidevnull_0 = > /dev/null +am__v_texidevnull_1 = +INFO_DEPS = $(srcdir)/tinc.info +am__TEXINFO_TEX_DIR = $(srcdir) DVIS = tinc.dvi +PDFS = tinc.pdf +PSS = tinc.ps +HTMLS = tinc.html TEXINFOS = tinc.texi - +TEXI2DVI = texi2dvi +TEXI2PDF = $(TEXI2DVI) --pdf --batch +MAKEINFOHTML = $(MAKEINFO) --html +AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) +DVIPS = dvips +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man5dir)" \ + "$(DESTDIR)$(man8dir)" +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(tinc_TEXINFOS) texinfo.tex +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +info_TEXINFOS = tinc.texi +tinc_TEXINFOS = tincinclude.texi +man_MANS = tincd.8 tinc.conf.5 +EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config +CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi +substitute = sed \ + -e s,'@PACKAGE\@',"$(PACKAGE)",g \ + -e s,'@VERSION\@',"$(VERSION)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g \ + -e s,'@runstatedir\@',"$(runstatedir)",g \ + -e s,'@localstatedir\@',"$(localstatedir)",g -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 texinfo.tex -DIST_SUBDIRS = $(SUBDIRS) -all: all-recursive +all: all-am .SUFFIXES: -.SUFFIXES: .dvi .info .ps .texi -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && \ - CONFIG_HEADERS= CONFIG_LINKS= \ - CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status +.SUFFIXES: .dvi .html .info .pdf .ps .texi +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; -tinc.info: tinc.texi -tinc.dvi: tinc.texi +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): .texi.info: - @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] - cd $(srcdir) \ - && $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) \ - `echo $< | sed 's,.*/,,'` + $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \ + am__cwd=`pwd` && $(am__cd) $(srcdir) && \ + rm -rf $$backupdir && mkdir $$backupdir && \ + if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ + for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ + if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ + done; \ + else :; fi && \ + cd "$$am__cwd"; \ + if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $@ $<; \ + then \ + rc=0; \ + $(am__cd) $(srcdir); \ + else \ + rc=$$?; \ + $(am__cd) $(srcdir) && \ + $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ + fi; \ + rm -rf $$backupdir; exit $$rc .texi.dvi: - TEXINPUTS=$(srcdir):$$TEXINPUTS \ + $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ - $(TEXI2DVI) $< + $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \ + $< -.texi: - @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] - cd $(srcdir) \ - && $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) \ - `echo $< | sed 's,.*/,,'` +.texi.pdf: + $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \ + $< -MAKEINFO = @MAKEINFO@ -TEXI2DVI = texi2dvi -DVIPS = dvips +.texi.html: + $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp) + $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) $<; \ + then \ + rm -rf $@ && mv $(@:.html=.htp) $@; \ + else \ + rm -rf $(@:.html=.htp); exit 1; \ + fi +$(srcdir)/tinc.info: tinc.texi $(tinc_TEXINFOS) +tinc.dvi: tinc.texi $(tinc_TEXINFOS) +tinc.pdf: tinc.texi $(tinc_TEXINFOS) +tinc.html: tinc.texi $(tinc_TEXINFOS) .dvi.ps: - $(DVIPS) $< -o $@ + $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + $(DVIPS) $(AM_V_texinfo) -o $@ $< + +uninstall-dvi-am: + @$(NORMAL_UNINSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ + rm -f "$(DESTDIR)$(dvidir)/$$f"; \ + done + +uninstall-html-am: + @$(NORMAL_UNINSTALL) + @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ + rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ + done uninstall-info-am: - $(PRE_UNINSTALL) - @if (install-info --version && \ - install-info --version | fgrep -i -v debian) >/dev/null 2>&1; then \ + @$(PRE_UNINSTALL) + @if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ - echo " install-info --info-dir=$(DESTDIR)$(infodir) --remove $(DESTDIR)$(infodir)/$$file"; \ - install-info --info-dir=$(DESTDIR)$(infodir) --remove $(DESTDIR)$(infodir)/$$file; \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ + if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ + then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ done; \ else :; fi @$(NORMAL_UNINSTALL) @list='$(INFO_DEPS)'; \ for file in $$list; do \ - (if cd $(DESTDIR)$(infodir); then \ - echo " rm -f $$file $$file-[0-9] $$file-[0-9][0-9])"; \ - rm -f $$file $$file-[0-9] $$file-[0-9][0-9]; \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ + (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ + echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ + rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ else :; fi); \ done +uninstall-pdf-am: + @$(NORMAL_UNINSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ + rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ + done + +uninstall-ps-am: + @$(NORMAL_UNINSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ + rm -f "$(DESTDIR)$(psdir)/$$f"; \ + done + dist-info: $(INFO_DEPS) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for base in $$list; do \ - d=$(srcdir); \ - for file in `CDPATH=: && cd $$d && eval echo $$base*`; do \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file; \ + case $$base in \ + $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ + for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ + if test -f $$file; then \ + relfile=`expr "$$file" : "$$d/\(.*\)"`; \ + test -f "$(distdir)/$$relfile" || \ + cp -p $$file "$(distdir)/$$relfile"; \ + else :; fi; \ done; \ done mostlyclean-aminfo: - -rm -f tinc.aux tinc.cp tinc.cps tinc.dvi tinc.fn tinc.ky tinc.log tinc.pg \ - tinc.ps tinc.toc tinc.tp tinc.vr + -rm -rf tinc.t2d tinc.t2p + +clean-aminfo: + -test -z "tinc.dvi tinc.pdf tinc.ps tinc.html" \ + || rm -rf tinc.dvi tinc.pdf tinc.ps tinc.html maintainer-clean-aminfo: - cd $(srcdir) && \ - for i in $(INFO_DEPS); do \ - rm -f $$i; \ - if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \ - rm -f $$i-[0-9]*; \ - fi; \ + @list='$(INFO_DEPS)'; for i in $$list; do \ + i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ + echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ + rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ done - -man5dir = $(mandir)/man5 -install-man5: $(man5_MANS) $(man_MANS) +install-man5: $(man_MANS) @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(man5dir) - @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.5*) list="$$list $$i" ;; \ - esac; \ + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ done; \ - for i in $$list; do \ - if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ - else file=$$i; fi; \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ - $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ - done + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + uninstall-man5: @$(NORMAL_UNINSTALL) - @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.5*) list="$$list $$i" ;; \ - esac; \ - done; \ - for i in $$list; do \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ - rm -f $(DESTDIR)$(man5dir)/$$inst; \ - done - -man8dir = $(mandir)/man8 -install-man8: $(man8_MANS) $(man_MANS) + @list=''; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +install-man8: $(man_MANS) @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(man8dir) - @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.8*) list="$$list $$i" ;; \ - esac; \ + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ done; \ - for i in $$list; do \ - if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ - else file=$$i; fi; \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ - $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ - done + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + uninstall-man8: @$(NORMAL_UNINSTALL) - @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.8*) list="$$list $$i" ;; \ - esac; \ - done; \ - for i in $$list; do \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ - rm -f $(DESTDIR)$(man8dir)/$$inst; \ - done + @list=''; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.8[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) +tags TAGS: -# 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" +ctags CTAGS: -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)' ;; \ +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ 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; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ - cp -pR $$d/$$file $(distdir) \ - || exit 1; \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + 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 $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="${top_distdir}" distdir="$(distdir)" \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-info check-am: all-am -check: check-recursive +check: check-am all-am: Makefile $(INFO_DEPS) $(MANS) -installdirs: installdirs-recursive -installdirs-am: - $(mkinstalldirs) $(DESTDIR)$(infodir) $(DESTDIR)$(man5dir) $(DESTDIR)$(man8dir) - -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive +installdirs: + for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +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-recursive +installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 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 "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-recursive +clean: clean-am -clean-am: clean-generic mostlyclean-am +clean-am: clean-aminfo clean-generic mostlyclean-am -distclean: distclean-recursive +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-recursive +dvi: dvi-am dvi-am: $(DVIS) -info: info-recursive +html: html-am + +html-am: $(HTMLS) + +info: info-am info-am: $(INFO_DEPS) install-data-am: install-info-am install-man +install-dvi: install-dvi-am + +install-dvi-am: $(DVIS) + @$(NORMAL_INSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ + done install-exec-am: -install-info: install-info-recursive +install-html: install-html-am + +install-html-am: $(HTMLS) + @$(NORMAL_INSTALL) + @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ + $(am__strip_dir) \ + d2=$$d$$p; \ + if test -d "$$d2"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ + echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ + else \ + list2="$$list2 $$d2"; \ + fi; \ + done; \ + test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ + done; } +install-info: install-info-am install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(infodir) - @list='$(INFO_DEPS)'; \ + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \ + fi; \ for file in $$list; do \ - d=$(srcdir); \ - for ifile in `CDPATH=: && cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \ - if test -f $$d/$$ifile; then \ - echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \ - $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ + for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ + $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ + if test -f $$ifile; then \ + echo "$$ifile"; \ else : ; fi; \ done; \ - done + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done @$(POST_INSTALL) - @if (install-info --version && \ - install-info --version | fgrep -i -v debian) >/dev/null 2>&1; then \ - list='$(INFO_DEPS)'; \ + @if $(am__can_run_installinfo); then \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ for file in $$list; do \ - echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ - install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ done; \ else : ; fi install-man: install-man5 install-man8 +install-pdf: install-pdf-am + +install-pdf-am: $(PDFS) + @$(NORMAL_INSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done +install-ps: install-ps-am + +install-ps-am: $(PSS) + @$(NORMAL_INSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done installcheck-am: -maintainer-clean: maintainer-clean-recursive - +maintainer-clean: maintainer-clean-am + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-aminfo \ maintainer-clean-generic -mostlyclean: mostlyclean-recursive +mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-aminfo mostlyclean-generic -uninstall-am: uninstall-info-am uninstall-man +pdf: pdf-am -uninstall-info: uninstall-info-recursive +pdf-am: $(PDFS) + +ps: ps-am + +ps-am: $(PSS) + +uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ + uninstall-man uninstall-pdf-am uninstall-ps-am uninstall-man: uninstall-man5 uninstall-man8 -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-generic clean-recursive dist-info distclean \ - distclean-generic 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-man5 install-man8 install-recursive install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - installdirs-recursive maintainer-clean maintainer-clean-aminfo \ - maintainer-clean-generic maintainer-clean-recursive mostlyclean \ - mostlyclean-aminfo mostlyclean-generic mostlyclean-recursive \ - tags tags-recursive uninstall uninstall-am uninstall-info-am \ - uninstall-info-recursive uninstall-man uninstall-man5 \ - uninstall-man8 uninstall-recursive +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-aminfo clean-generic \ + cscopelist-am ctags-am dist-info distclean distclean-generic \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man5 install-man8 install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-aminfo maintainer-clean-generic mostlyclean \ + mostlyclean-aminfo mostlyclean-generic pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am uninstall-dvi-am \ + uninstall-html-am uninstall-info-am uninstall-man \ + uninstall-man5 uninstall-man8 uninstall-pdf-am uninstall-ps-am + +.PRECIOUS: Makefile -# For additional rules usually of interest only to the maintainer, -# see GNUmakefile and Makefile.maint. +texi2html: tinc.texi + $(AM_V_GEN)texi2html -split=chapter $< + +tincd.8.html: tincd.8 + $(AM_V_GEN)w3mman2html $< > $@ + +tinc.conf.5.html: tinc.conf.5 + $(AM_V_GEN)w3mman2html $< > $@ + +tincd.8: $(srcdir)/tincd.8.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ + +tinc.conf.5: $(srcdir)/tinc.conf.5.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ + +tincinclude.texi: $(srcdir)/tincinclude.texi.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@ + # 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/doc/Makefile.maint b/doc/Makefile.maint deleted file mode 100644 index 75804f0..0000000 --- a/doc/Makefile.maint +++ /dev/null @@ -1,38 +0,0 @@ -# This -*- Makefile -*- uses features of GNU make. -# It is included via GNUmakefile. - -# The following one line summaries were extracted from the -# original man pages using this bit of sh code: -# for i in *.1; do echo "$i: "|tr -d '\012'; \ -# grep -A1 SH.NAME $i|sed '/SH NAME/d;s/^[^ ][^ ]* .- //'; done - -include Makefile.summ - -HELP2MAN-run = $(PERL) -w -- $(srcdir)/$(HELP2MAN) - -# Depend on configure.in to get version number changes. -$(dyn_MANS): $(top_srcdir)/configure.in - -# Depend on the source file containing the --help text. -# Filter out irregular cases. -regular-men = $(filter-out $(irregular-men),$(dyn_MANS)) -$(regular-men): %.8: $(top_srcdir)/src/%.c - -executable = $(patsubst %/install,%/ginstall, ../src/$(basename $@)) -$(dyn_MANS): %.8: %.x $(HELP2MAN) - @if test -f $(executable); then \ - echo "Updating man page $@"; \ - rm -f $@-t $@; \ - $(HELP2MAN-run) \ - --name="$($(basename $@)-summary)" \ - --include=$(basename $@).x \ - $(executable) > $@-t; \ - chmod -w $@-t; \ - mv $@-t $@; \ - else \ - echo "WARNING: The man page $@ cannot be updated yet."; \ - echo " Retry once the corresponding executable is built."; \ - fi - -sample-config.tar.gz: - GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz sample-config diff --git a/doc/Makefile.summ b/doc/Makefile.summ deleted file mode 100644 index a97b492..0000000 --- a/doc/Makefile.summ +++ /dev/null @@ -1,2 +0,0 @@ -# -*- makefile -*- -tincd-summary = tinc VPN daemon diff --git a/doc/es/Makefile.am b/doc/es/Makefile.am deleted file mode 100644 index 756d670..0000000 --- a/doc/es/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -## Process this file with automake to get Makefile.in - -# Nothing to see here, go away! diff --git a/doc/es/Makefile.in b/doc/es/Makefile.in deleted file mode 100644 index 7261008..0000000 --- a/doc/es/Makefile.in +++ /dev/null @@ -1,218 +0,0 @@ -# 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@ - -# Nothing to see here, go away! - -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 = : -host_alias = @host_alias@ -host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INCLUDES = @INCLUDES@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ -subdir = doc/es -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: -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/es/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 mostlyclean-am - -distclean: distclean-am - -distclean-am: clean-am distclean-generic - -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 - -uninstall-am: uninstall-info-am - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic 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 uninstall uninstall-am uninstall-info-am - -# 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/doc/help2man b/doc/help2man deleted file mode 100755 index 71778a9..0000000 --- a/doc/help2man +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/perl -w - -# Generate a short man page from --help and --version output. -# Copyright © 1997, 98 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. - -# Written by Brendan O'Dea - -use 5.004; -use strict; -use Getopt::Long; -use POSIX qw(strftime setlocale LC_TIME); - -my $this_program = 'help2man'; -my $this_version = '1.006'; -my $version_info = < -EOT - -my $help_info = < \$opt_name, - 'include=s' => \$include, - 'opt-include=s' => \$opt_include, - 'output=s' => \$opt_output, - 'no-info' => \$opt_no_info, - help => sub { print $help_info; exit }, - version => sub { print $version_info; exit }, -) or die $help_info; - -die $help_info unless @ARGV == 1; - -my %include = (); -my @include = (); # to retain order - -# Process include file (if given). Format is: -# -# [section name] -# verbatim text - -if ($include or $opt_include) -{ - if (open INC, $include || $opt_include) - { - my $sect; - - while () - { - if (/^\[([^]]+)\]/) - { - $sect = uc $1; - $sect =~ s/^\s+//; - $sect =~ s/\s+$//; - next; - } - - # Silently ignore anything before the first - # section--allows for comments and revision info. - next unless $sect; - - push @include, $sect unless $include{$sect}; - $include{$sect} ||= ''; - $include{$sect} .= $_; - } - - close INC; - - die "$this_program: no valid information found in `$include'\n" - unless %include; - - # Compress trailing blank lines. - for (keys %include) - { - $include{$_} =~ s/\n+$//; - $include{$_} .= "\n" unless /^NAME$/; - } - } - else - { - die "$this_program: can't open `$include' ($!)\n" if $include; - } -} - -# Turn off localisation of executable's ouput. -@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; - -# Turn off localisation of date (for strftime) -setlocale LC_TIME, 'C'; - -# Grab help and version paragraphs from executable -my @help = split /\n\n+/, `$ARGV[0] --help 2>/dev/null` - or die "$this_program: can't get `--help' info from $ARGV[0]\n"; - -my @version = split /\n\n+/, `$ARGV[0] --version 2>/dev/null` - or die "$this_program: can't get `--version' info from $ARGV[0]\n"; - -my $date = strftime "%B %Y", localtime; -my $program = $ARGV[0]; $program =~ s!.*/!!; -my $package = $program; -my $version; - -if ($opt_output) -{ - unlink $opt_output - or die "$this_program: can't unlink $opt_output ($!)\n" - if -e $opt_output; - - open STDOUT, ">$opt_output" - or die "$this_program: can't create $opt_output ($!)\n"; -} - -# The first line of the --version information is assumed to be in one -# of the following formats: -# -# -# -# GNU -# (GNU ) -# - GNU -# -# and seperated from any copyright/author details by a blank line. - -$_ = shift @version; - -if (/^(\S+)\s+\((GNU\s+[^)]+)\)\s+(.*)/ or - /^(\S+)\s+-\s*(GNU\s+\S+)\s+(.*)/) -{ - $program = $1; - $package = $2; - $version = $3; -} -elsif (/^(GNU\s+)?(\S+)\s+(.*)/) -{ - $program = $2; - $package = $1 ? "$1$2" : $2; - $version = $3; -} -else -{ - $version = $_; -} - -$program =~ s!.*/!!; - -# no info for `info' itself -$opt_no_info = 1 if $program eq 'info'; - -# --name overrides --include contents -$include{NAME} = "$program \\- $opt_name" if $opt_name; - -# Default (useless) NAME paragraph -$include{NAME} ||= "$program \\- manual page for $program $version"; - -# Man pages traditionally have the page title in caps. -my $PROGRAM = uc $program; - -# Header. -print <. % -% In other words, you are welcome to use, share and improve this program. -% You are forbidden to forbid anyone else to use, share and improve -% what you give them. Help stamp out software-hoarding! +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. This Exception is an additional permission under section 7 +% of the GNU General Public License, version 3 ("GPLv3"). % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: -% ftp://ftp.gnu.org/pub/gnu/texinfo.tex -% /home/gd/gnu/doc/texinfo.tex on the GNU machines. -% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) -% ftp://tug.org/tex/texinfo.tex -% ftp://ctan.org/macros/texinfo/texinfo.tex -% (and all CTAN mirrors, finger ctan@ctan.org for a list). -% The texinfo.tex in the texinfo distribution itself could well be out +% https://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or +% https://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or +% https://www.gnu.org/software/texinfo/ (the Texinfo home page) +% The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. -% -% Send bug reports to bug-texinfo@gnu.org. -% Please include a precise test case in each bug report, -% including a complete document with which we can reproduce the problem. -% +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% % To process a Texinfo manual with TeX, it's most reliable to use the -% texi2dvi shell script that comes with the distribution. For simple -% manuals, however, you can get away with: +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: % tex foo.texi % texindex foo.?? % tex foo.texi % tex foo.texi -% dvips foo.dvi -o # or whatever, to process the dvi file. -% The extra runs of TeX get the cross-reference information correct. +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. % Sometimes one run after texindex suffices, and sometimes you need more % than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. +% +% The GNU Texinfo home page is https://www.gnu.org/software/texinfo. + \message{Loading texinfo [version \texinfoversion]:} @@ -62,8 +64,17 @@ \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} -% Save some parts of plain tex whose names we will redefine. +% LaTeX's \typeout. This ensures that the messages it is used for +% are identical in format to the corresponding ones from latex/pdflatex. +\def\typeout{\immediate\write17}% +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. \let\ptexb=\b \let\ptexbullet=\bullet \let\ptexc=\c @@ -73,386 +84,508 @@ \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! +\let\ptexfootnote=\footnote +\let\ptexgtr=> +\let\ptexhat=^ \let\ptexi=\i +\let\ptexindent=\indent +\let\ptexinsert=\insert \let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent +\let\ptexplus=+ +\let\ptexraggedright=\raggedright \let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexsp=\sp \let\ptexstar=\* +\let\ptexsup=\sup \let\ptext=\t - -% We never want plain's outer \+ definition in Texinfo. -% For @tex, we can use \tabalign. -\let\+ = \relax - - -\message{Basics,} -\chardef\other=12 +\let\ptextop=\top +{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{l.\the\inputlineno:\space} +\fi + % Set up fixed words for English if not already set. -\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi -\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi -\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi -\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi -\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi -\ifx\putwordon\undefined \gdef\putwordon{on}\fi -\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi -\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi -\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi -\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi -\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi -\ifx\putwordShortContents\undefined \gdef\putwordShortContents{Short Contents}\fi -\ifx\putwordTableofContents\undefined\gdef\putwordTableofContents{Table of Contents}\fi +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putworderror\undefined \gdef\putworderror{error}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi + +% Give the space character the catcode for a space. +\def\spaceisspace{\catcode`\ =10\relax} + +% Likewise for ^^M, the end of line character. +\def\endlineisspace{\catcode13=10\relax} + +\chardef\dashChar = `\- +\chardef\slashChar = `\/ +\chardef\underChar = `\_ % Ignore a token. % \def\gobble#1{} -\hyphenation{ap-pen-dix} -\hyphenation{mini-buf-fer mini-buf-fers} -\hyphenation{eshell} -\hyphenation{white-space} +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} -% Margin to add to right of even pages, to left of odd pages. -\newdimen \bindingoffset -\newdimen \normaloffset -\newdimen\pagewidth \newdimen\pageheight +% Hyphenation fixes. +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, -% since that produces some useless output on the terminal. +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% -\ifx\eTeXversion\undefined -\def\loggingall{\tracingcommands2 \tracingstats2 - \tracingpages1 \tracingoutput1 \tracinglostchars1 - \tracingmacros2 \tracingparagraphs1 \tracingrestores1 - \showboxbreadth\maxdimen\showboxdepth\maxdimen +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\thisisundefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines16 }% -\else -\def\loggingall{\tracingcommands3 \tracingstats2 - \tracingpages1 \tracingoutput1 \tracinglostchars1 - \tracingmacros2 \tracingparagraphs1 \tracingrestores1 - \tracingscantokens1 \tracingassigns1 \tracingifs1 - \tracinggroups1 \tracingnesting2 - \showboxbreadth\maxdimen\showboxdepth\maxdimen -}% -\fi -% For @cropmarks command. -% Do @cropmarks to get crop marks. -% -\newif\ifcropmarks -\let\cropmarks = \cropmarkstrue +% @errormsg{MSG}. Do the index-like expansions on MSG, but if things +% aren't perfect, it's not the end of the world, being an error message, +% after all. % -% Dimensions to add cropmarks at corners. -% Added by P. A. MacKay, 12 Nov. 1986 +\def\errormsg{\begingroup \indexnofonts \doerrormsg} +\def\doerrormsg#1{\errmessage{#1}} + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. % +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% Output routine +% + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt } + \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines -\newdimen\cornerlong \cornerlong=1pc -\newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in +% Output a mark which sets \thischapter, \thissection and \thiscolor. +% We dump everything together because we only have one kind of mark. +% This works because we only use \botmark / \topmark, not \firstmark. +% +% A mark contains a subexpression of the \ifcase ... \fi construct. +% \get*marks macros below extract the needed part using \ifcase. +% +% Another complication is to let the user choose whether \thischapter +% (\thissection) refers to the chapter (section) in effect at the top +% of a page, or that at the bottom of a page. + +% \domark is called twice inside \chapmacro, to add one +% mark before the section break, and one after. +% In the second call \prevchapterdefs is the same as \currentchapterdefs, +% and \prevsectiondefs is the same as \currentsectiondefs. +% Then if the page is not broken at the mark, some of the previous +% section appears on the page, and we can get the name of this section +% from \firstmark for @everyheadingmarks top. +% @everyheadingmarks bottom uses \botmark. +% +% See page 260 of The TeXbook. +\def\domark{% + \toks0=\expandafter{\currentchapterdefs}% + \toks2=\expandafter{\currentsectiondefs}% + \toks4=\expandafter{\prevchapterdefs}% + \toks6=\expandafter{\prevsectiondefs}% + \toks8=\expandafter{\currentcolordefs}% + \mark{% + \the\toks0 \the\toks2 % 0: marks for @everyheadingmarks top + \noexpand\or \the\toks4 \the\toks6 % 1: for @everyheadingmarks bottom + \noexpand\else \the\toks8 % 2: color marks + }% +} + +% \gettopheadingmarks, \getbottomheadingmarks, +% \getcolormarks - extract needed part of mark. +% +% \topmark doesn't work for the very first chapter (after the title +% page or the contents), so we use \firstmark there -- this gets us +% the mark with the chapter defs, unless the user sneaks in, e.g., +% @setcolor (or @url, or @link, etc.) between @contents and the very +% first @chapter. +\def\gettopheadingmarks{% + \ifcase0\the\savedtopmark\fi + \ifx\thischapter\empty \ifcase0\firstmark\fi \fi +} +\def\getbottomheadingmarks{\ifcase1\botmark\fi} +\def\getcolormarks{\ifcase2\the\savedtopmark\fi} + +% Avoid "undefined control sequence" errors. +\def\currentchapterdefs{} +\def\currentsectiondefs{} +\def\currentsection{} +\def\prevchapterdefs{} +\def\prevsectiondefs{} +\def\currentcolordefs{} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\txipagewidth \newdimen\txipageheight + % Main output routine. +% \chardef\PAGE = 255 -\output = {\onepageout{\pagecontents\PAGE}} +\newtoks\defaultoutput +\defaultoutput = {\savetopmark\onepageout{\pagecontents\PAGE}} +\output=\expandafter{\the\defaultoutput} \newbox\headlinebox \newbox\footlinebox -% \onepageout takes a vbox as an argument. Note that \pagecontents -% does insertions, but you have to call it yourself. +% When outputting the double column layout for indices, an output routine +% is run several times, which hides the original value of \topmark. This +% can lead to a page heading being output and duplicating the chapter heading +% of the index. Hence, save the contents of \topmark at the beginning of +% the output routine. The saved contents are valid until we actually +% \shipout a page. +% +% (We used to run a short output routine to actually set \topmark and +% \firstmark to the right values, but if this was called with an empty page +% containing whatsits for writing index entries, the whatsits would be thrown +% away and the index auxiliary file would remain empty.) +% +\newtoks\savedtopmark +\newif\iftopmarksaved +\topmarksavedtrue +\def\savetopmark{% + \iftopmarksaved\else + \global\savedtopmark=\expandafter{\topmark}% + \global\topmarksavedtrue + \fi +} + +% \onepageout takes a vbox as an argument. +% \shipout a vbox for a single page, adding an optional header, footer +% and footnote. This also causes index entries for this page to be written +% to the auxiliary files. +% \def\onepageout#1{% - \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + \hoffset=\normaloffset % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % + % Retrieve the information for the headings from the marks in the page, + % and call Plain TeX's \makeheadline and \makefootline, which use the + % values in \headline and \footline. + % + % This is used to check if we are on the first page of a chapter. + \ifcase1\the\savedtopmark\fi + \let\prevchaptername\thischaptername + \ifcase0\firstmark\fi + \let\curchaptername\thischaptername + % + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi + % + \ifx\curchaptername\prevchaptername + \let\thischapterheading\thischapter + \else + % \thischapterheading is the same as \thischapter except it is blank + % for the first page of a chapter. This is to prevent the chapter name + % being shown twice. + \def\thischapterheading{}% + \fi + % + % Common context changes for both heading and footing. % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). - \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% - \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + \def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars} + % + \global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}% + % + \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi + \global\setbox\footlinebox = \vbox{\commonheadfootline \makefootline}% % {% + % Set context for writing to auxiliary files like index files. % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % - \escapechar = `\\ % use backslash in output files. - \indexdummies % don't expand commands in the output. - \normalturnoffactive % \ in index entries must not stay \, e.g., if - % the page break happens to be in the middle of an example. + \atdummies % don't expand commands in the output. + \turnoffactive \shipout\vbox{% - \ifcropmarks \vbox to \outervsize\bgroup - \hsize = \outerhsize - \vskip-\topandbottommargin - \vtop to0pt{% - \line{\ewtop\hfil\ewtop}% - \nointerlineskip - \line{% - \vbox{\moveleft\cornerthick\nstop}% - \hfill - \vbox{\moveright\cornerthick\nstop}% - }% - \vss}% - \vskip\topandbottommargin - \line\bgroup - \hfil % center the page within the outer (page) hsize. - \ifodd\pageno\hskip\bindingoffset\fi - \vbox\bgroup - \fi + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. - % (We lessened \vsize for it in \oddfootingxxx.) + % (We lessened \vsize for it in \oddfootingyyy.) % The \baselineskip=24pt in plain's \makefootline has no effect. - \vskip 2\baselineskip + \vskip 24pt \unvbox\footlinebox \fi % - \ifcropmarks - \egroup % end of \vbox\bgroup - \hfil\egroup % end of (centering) \line\bgroup - \vskip\topandbottommargin plus1fill minus1fill - \boxmaxdepth = \cornerthick - \vbox to0pt{\vss - \line{% - \vbox{\moveleft\cornerthick\nsbot}% - \hfill - \vbox{\moveright\cornerthick\nsbot}% - }% - \nointerlineskip - \line{\ewbot\hfil\ewbot}% - }% - \egroup % \vbox from first cropmarks clause - \fi - }% end of \shipout\vbox - }% end of group with \turnoffactive + }% + }% + \global\topmarksavedfalse \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen -\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +% Main part of page, including any footnotes +\def\pagebody#1{\vbox to\txipageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi -\dimen@=\dp#1 \unvbox#1 +\dimen@=\dp#1\relax \unvbox#1\relax \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } -% Here are the rules for the cropmarks. Note that they are -% offset so that the space between them is truly \outerhsize or \outervsize -% (P. A. MacKay, 12 November, 1986) -% -\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} -\def\nstop{\vbox - {\hrule height\cornerthick depth\cornerlong width\cornerthick}} -\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} -\def\nsbot{\vbox - {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Argument parsing % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. +% For example, \def\foo{\parsearg\fooxxx}. % -\def\parsearg#1{% - \let\next = #1% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\argtorun{#2}% \begingroup \obeylines - \futurelet\temp\parseargx + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. } -% If the next token is an obeyed space (from an @example environment or -% the like), remove it and recurse. Otherwise, we're done. -\def\parseargx{% - % \obeyedspace is defined far below, after the definition of \sepspaces. - \ifx\obeyedspace\temp - \expandafter\parseargdiscardspace - \else - \expandafter\parseargline - \fi -} - -% Remove a single space (as the delimiter token to the macro call). -{\obeyspaces % - \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} - {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. - % - % First remove any @c comment, then any @comment. - % Result of each macro is put in \toks0. - \argremovec #1\c\relax % - \expandafter\argremovecomment \the\toks0 \comment\relax % - % - % Call the caller's macro, saved as \next in \parsearg. - \expandafter\next\expandafter{\the\toks0}% + \argremovecomment #1\comment\ArgTerm% }% } -% Since all \c{,omment} does is throw away the argument, we can let TeX -% do that for us. The \relax here is matched by the \relax in the call -% in \parseargline; it could be more or less anything, its purpose is -% just to delimit the argument to the \c. -\def\argremovec#1\c#2\relax{\toks0 = {#1}} -\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} +% First remove any @comment, then any @c comment. Pass the result on to +% \argcheckspaces. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} -% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% Each occurrence of `\^^M' or `\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, e.g., % @end itemize @c foo -% will have two active spaces as part of the argument with the -% `itemize'. Here we remove all active spaces from #1, and assign the -% result to \toks0. +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. % -% This loses if there are any *other* active characters besides spaces -% in the argument -- _ ^ +, for example -- since they get expanded. -% Fortunately, Texinfo does not define any such commands. (If it ever -% does, the catcode of the characters in questionwill have to be changed -% here.) But this means we cannot call \removeactivespaces as part of -% \argremovec{,omment}, since @c uses \parsearg, and thus the argument -% that \parsearg gets might well have any character at all in it. -% -\def\removeactivespaces#1{% - \begingroup - \ignoreactivespaces - \edef\temp{#1}% - \global\toks0 = \expandafter{\temp}% - \endgroup +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm } -% Change the active space to expand to nothing. +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \argtorun. +% (Similarly, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. % -\begingroup +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} + + +% \parseargdef - define a command taking an argument on the line +% +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} + +% Several utility definitions with active space: +{ \obeyspaces - \gdef\ignoreactivespaces{\obeyspaces\let =\empty} -\endgroup + \gdef\obeyedspace{ } + + % Make each space character in the input produce a normal interword + % space in the output. Don't allow a line break at this space, as this + % is used only in environments like @example, where each line of input + % should produce a line of output anyway. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % If an index command is used in an @example environment, any spaces + % therein should become regular spaces in the raw index file, not the + % expansion of \tie (\leavevmode \penalty \@M \ ). + \gdef\unsepspaces{\let =\space} +} \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} -%% These are used to keep @begin/@end levels from running away -%% Call \inENV within environments (after a \begingroup) -\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} -\def\ENVcheck{% -\ifENV\errmessage{Still within an environment; press RETURN to continue} -\endgroup\fi} % This is not perfect, but it should reduce lossage - -% @begin foo is the same as @foo, for now. -\newhelp\EMsimple{Press RETURN to continue.} - -\outer\def\begin{\parsearg\beginxxx} - -\def\beginxxx #1{% -\expandafter\ifx\csname #1\endcsname\relax -{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else -\csname #1\endcsname\fi} - -% @end foo executes the definition of \Efoo. +% Define the framework for environments in texinfo.tex. It's used like this: % -\def\end{\parsearg\endxxx} -\def\endxxx #1{% - \removeactivespaces{#1}% - \edef\endthing{\the\toks0}% - % - \expandafter\ifx\csname E\endthing\endcsname\relax - \expandafter\ifx\csname \endthing\endcsname\relax - % There's no \foo, i.e., no ``environment'' foo. - \errhelp = \EMsimple - \errmessage{Undefined command `@end \endthing'}% - \else - \unmatchedenderror\endthing - \fi +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as environments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At run-time, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp \else - % Everything's ok; the right environment has been started. - \csname E\endthing\endcsname + \badenverr \fi } -% There is an environment #1, but it hasn't been started. Give an error. -% -\def\unmatchedenderror#1{% +% Environment mismatch, #1 expected: +\def\badenverr{% \errhelp = \EMsimple - \errmessage{This `@end #1' doesn't have a matching `@#1'}% + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + outside of any environment% + \else + in environment \expandafter\string#1% + \fi } -% Define the control sequence \E#1 to give an unmatched @end error. +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv % -\def\defineunmatchedend#1{% - \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal. + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi } +\newhelp\EMsimple{Press RETURN to continue.} -% Single-spacing is done by various environments (specifically, in -% \nonfillstart and \quotations). -\newskip\singlespaceskip \singlespaceskip = 12.5pt -\def\singlespace{% - % Why was this kern here? It messes up equalizing space above and below - % environments. --karl, 6may93 - %{\advance \baselineskip by -\singlespaceskip - %\kern \baselineskip}% - \setleading \singlespaceskip -} - -%% Simple single-character @ commands - -% @@ prints an @ -% Kludge this until the fonts are right (grr). -\def\@{{\tt\char64}} - -% This is turned off because it was never documented -% and you can use @w{...} around a quote to suppress ligatures. -%% Define @` and @' to be the same as ` and ' -%% but suppressing ligatures. -%\def\`{{`}} -%\def\'{{'}} - -% Used to generate quoted braces. -\def\mylbrace {{\tt\char123}} -\def\myrbrace {{\tt\char125}} -\let\{=\mylbrace -\let\}=\myrbrace -\begingroup - % Definitions to produce actual \{ & \} command in an index. - \catcode`\{ = 12 \catcode`\} = 12 - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\@ = 0 \catcode`\\ = 12 - @gdef@lbracecmd[\{]% - @gdef@rbracecmd[\}]% -@endgroup - -% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent -% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H. -\let\, = \c -\let\dotaccent = \. -\def\ringaccent#1{{\accent23 #1}} -\let\tieaccent = \t -\let\ubaraccent = \b -\let\udotaccent = \d - -% Other special characters: @questiondown @exclamdown -% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss. -\def\questiondown{?`} -\def\exclamdown{!`} - -% Dotless i and dotless j, used for accents. -\def\imacro{i} -\def\jmacro{j} -\def\dotless#1{% - \def\temp{#1}% - \ifx\temp\imacro \ptexi - \else\ifx\temp\jmacro \j - \else \errmessage{@dotless can be used only with i or j}% - \fi\fi -} % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space @@ -470,16 +603,34 @@ \def\:{\spacefactor=1000 } % @* forces a line break. -\def\*{\hfil\break\hbox{}\ignorespaces} +\def\*{\unskip\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak % @. is an end-of-sentence period. -\def\.{.\spacefactor=3000 } +\def\.{.\spacefactor=\endofsentencespacefactor\space} % @! is an end-of-sentence bang. -\def\!{!\spacefactor=3000 } +\def\!{!\spacefactor=\endofsentencespacefactor\space} % @? is an end-of-sentence query. -\def\?{?\spacefactor=3000 } +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on|off}% + \fi\fi +} % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would @@ -494,47 +645,24 @@ % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % -\def\group{\begingroup - \ifnum\catcode13=\active \else +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\envdef\group{% + \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi + \startsavinginserts % - % The \vtop we start below produces a box with normal height and large - % depth; thus, TeX puts \baselineskip glue before it, and (when the - % next line of text is done) \lineskip glue after it. (See p.82 of - % the TeXbook.) Thus, space below is not quite equal to space - % above. But it's pretty close. - \def\Egroup{% - \egroup % End the \vtop. - \endgroup % End the \group. - }% - % - \vtop\bgroup - % We have to put a strut on the last line in case the @group is in - % the midst of an example, rather than completely enclosing it. - % Otherwise, the interline space between the last line of the group - % and the first line afterwards is too small. But we can't put the - % strut in \Egroup, since there it would be on a line by itself. - % Hence this just inserts a strut at the beginning of each line. - \everypar = {\strut}% - % - % Since we have a strut on every line, we don't need any of TeX's - % normal interline spacing. - \offinterlineskip - % - % OK, but now we have to do something about blank - % lines in the input in @example-like environments, which normally - % just turn into \lisppar, which will insert no space now that we've - % turned off the interline space. Simplest is to make them be an - % empty paragraph. - \ifx\par\lisppar - \edef\par{\leavevmode \par}% - % - % Reset ^^M's definition to new definition of \par. - \obeylines - \fi - % + \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after @@ -543,6 +671,37 @@ % manual), we don't worry about eating any user text. \comment } +% +% The \vtop produces a box with normal height and large depth; thus, TeX puts +% \baselineskip glue before it, and (when the next line of text is done) +% \lineskip glue after it. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \egroup % End the \vtop. + \addgroupbox + \prevdepth = \dimen1 + \checkinserts +} + +\def\addgroupbox{ + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \txipageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\txipageheight + \page + \fi + \fi + \box\groupbox +} + % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. @@ -556,81 +715,50 @@ where each line of input produces a line of output.} \newdimen\mil \mil=0.001in -\def\need{\parsearg\needx} - -% Old definition--didn't work. -%\def\needx #1{\par % -%% This method tries to make TeX break the page naturally -%% if the depth of the box does not fit. -%{\baselineskip=0pt% -%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak -%\prevdepth=-1000pt -%}} - -\def\needx#1{% - % Go into vertical mode, so we don't make a big box in the middle of a +\parseargdef\need{% + % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % - % Don't add any leading before our big empty box, but allow a page - % break, since the best break might be right here. - \allowbreak - \nointerlineskip - \vtop to #1\mil{\vfil}% - % - % TeX does not even consider page breaks if a penalty added to the - % main vertical list is 10000 or more. But in order to see if the - % empty box we just added fits on the page, we must make it consider - % page breaks. On the other hand, we don't want to actually break the - % page after the empty box. So we use a penalty of 9999. - % - % There is an extremely small chance that TeX will actually break the - % page at this \penalty, if there are no other feasible breakpoints in - % sight. (If the user is using lots of big @group commands, which - % almost-but-not-quite fill up a page, TeX will have a hard time doing - % good page breaking, for example.) However, I could not construct an - % example where a page broke at this \penalty; if it happens in a real - % document, then we can reconsider our strategy. - \penalty9999 - % - % Back up by the size of the box, whether we did a page break or not. - \kern -#1\mil - % - % Do not allow a page break right after this kern. - \nobreak + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi } -% @br forces paragraph break +% @br forces paragraph break (and is undocumented). \let\br = \par -% @dots{} output an ellipsis using the current font. -% We do .5em per period so that it has the same spacing in a typewriter -% font as three actual period characters. -% -\def\dots{% - \leavevmode - \hbox to 1.5em{% - \hskip 0pt plus 0.25fil minus 0.25fil - .\hss.\hss.% - \hskip 0pt plus 0.5fil minus 0.5fil - }% -} - -% @enddots{} is an end-of-sentence ellipsis. -% -\def\enddots{% - \leavevmode - \hbox to 2em{% - \hskip 0pt plus 0.25fil minus 0.25fil - .\hss.\hss.\hss.% - \hskip 0pt plus 0.5fil minus 0.5fil - }% - \spacefactor=3000 -} - - -% @page forces the start of a new page +% @page forces the start of a new page. % \def\page{\par\vfill\supereject} @@ -642,515 +770,1380 @@ where each line of input produces a line of output.} \newskip\exdentamount % This defn is used inside fill environments such as @defun. -\def\exdent{\parsearg\exdentyyy} -\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} +\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. -\def\nofillexdent{\parsearg\nofillexdentyyy} -\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount -\leftline{\hskip\leftskip{\rm#1}}}} +\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount + \leftline{\hskip\leftskip{\rm#1}}}} -% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. - -\def\inmargin#1{% -\strut\vadjust{\nobreak\kern-\strutdepth - \vtop to \strutdepth{\baselineskip\strutdepth\vss - \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. Not documented, written for gawk manual. +% \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} -%\hbox{{\rm#1}}\hfil\break}} - -% @include file insert text of that file as input. -% Allow normal characters that we make active in the argument (a file name). -\def\include{\begingroup - \catcode`\\=12 - \catcode`~=12 - \catcode`^=12 - \catcode`_=12 - \catcode`|=12 - \catcode`<=12 - \catcode`>=12 - \catcode`+=12 - \parsearg\includezzz} -% Restore active chars for included file. -\def\includezzz#1{\endgroup\begingroup - % Read the included file in a group so nested @include's work. +% @include FILE -- \input text of FILE. +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack \def\thisfile{#1}% - \input\thisfile -\endgroup} + {% + \makevalueexpandable % we want to expand any @value in FILE. + \turnoffactive % and allow special characters in the expansion + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @include of #1^^J}% + \edef\temp{\noexpand\input #1 }% + % + % This trickery is to read FILE outside of a group, in case it makes + % definitions, etc. + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \catcode`-=\other + \catcode`\`=\other + \catcode`\'=\other +} +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} +% \def\thisfile{} -% @center line outputs that line, centered - -\def\center{\parsearg\centerzzz} -\def\centerzzz #1{{\advance\hsize by -\leftskip -\advance\hsize by -\rightskip -\centerline{#1}}} +% @center line +% outputs that line, centered. +% +\parseargdef\center{% + \ifhmode + \let\centersub\centerH + \else + \let\centersub\centerV + \fi + \centersub{\hfil \ignorespaces#1\unskip \hfil}% + \let\centersub\relax % don't let the definition persist, just in case +} +\def\centerH#1{{% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break +}} +% +\newcount\centerpenalty +\def\centerV#1{% + % The idea here is the same as in \startdefun, \cartouche, etc.: if + % @center is the first thing after a section heading, we need to wipe + % out the negative parskip inserted by \sectionheading, but still + % prevent a page break here. + \centerpenalty = \lastpenalty + \ifnum\centerpenalty>10000 \vskip\parskip \fi + \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi + \line{\kern\leftskip #1\kern\rightskip}% +} % @sp n outputs n lines of vertical space - -\def\sp{\parsearg\spxxx} -\def\spxxx #1{\vskip #1\baselineskip} +% +\parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment -\def\comment{\begingroup \catcode`\^^M=\other% + +\def\c{\begingroup \catcode`\^^M=\active% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% -\commentxxx} -{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} - -\let\c=\comment - -% @paragraphindent is defined for the Info formatting commands only. -\let\paragraphindent=\comment - -% Prevent errors for section commands. -% Used in @ignore and in failing conditionals. -\def\ignoresections{% -\let\chapter=\relax -\let\unnumbered=\relax -\let\top=\relax -\let\unnumberedsec=\relax -\let\unnumberedsection=\relax -\let\unnumberedsubsec=\relax -\let\unnumberedsubsection=\relax -\let\unnumberedsubsubsec=\relax -\let\unnumberedsubsubsection=\relax -\let\section=\relax -\let\subsec=\relax -\let\subsubsec=\relax -\let\subsection=\relax -\let\subsubsection=\relax -\let\appendix=\relax -\let\appendixsec=\relax -\let\appendixsection=\relax -\let\appendixsubsec=\relax -\let\appendixsubsection=\relax -\let\appendixsubsubsec=\relax -\let\appendixsubsubsection=\relax -\let\contents=\relax -\let\smallbook=\relax -\let\titlepage=\relax -} - -% Used in nested conditionals, where we have to parse the Texinfo source -% and so want to turn off most commands, in case they are used -% incorrectly. +\cxxx} +{\catcode`\^^M=\active \gdef\cxxx#1^^M{\endgroup}} % -\def\ignoremorecommands{% - \let\defcodeindex = \relax - \let\defcv = \relax - \let\deffn = \relax - \let\deffnx = \relax - \let\defindex = \relax - \let\defivar = \relax - \let\defmac = \relax - \let\defmethod = \relax - \let\defop = \relax - \let\defopt = \relax - \let\defspec = \relax - \let\deftp = \relax - \let\deftypefn = \relax - \let\deftypefun = \relax - \let\deftypevar = \relax - \let\deftypevr = \relax - \let\defun = \relax - \let\defvar = \relax - \let\defvr = \relax - \let\ref = \relax - \let\xref = \relax - \let\printindex = \relax - \let\pxref = \relax - \let\settitle = \relax - \let\setchapternewpage = \relax - \let\setchapterstyle = \relax - \let\everyheading = \relax - \let\evenheading = \relax - \let\oddheading = \relax - \let\everyfooting = \relax - \let\evenfooting = \relax - \let\oddfooting = \relax - \let\headings = \relax - \let\include = \relax - \let\lowersections = \relax - \let\down = \relax - \let\raisesections = \relax - \let\up = \relax - \let\set = \relax - \let\clear = \relax - \let\item = \relax -} +\let\comment\c -% Ignore @ignore ... @end ignore. +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. % -\def\ignore{\doignore{ignore}} - -% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text. +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} % -\def\ifinfo{\doignore{ifinfo}} -\def\ifhtml{\doignore{ifhtml}} -\def\ifnottex{\doignore{ifnottex}} -\def\html{\doignore{html}} -\def\menu{\doignore{menu}} -\def\direntry{\doignore{direntry}} - -% @dircategory CATEGORY -- specify a category of the dir file -% which this file should belong to. Ignore this in TeX. -\let\dircategory = \comment - -% Ignore text until a line `@end #1'. -% -\def\doignore#1{\begingroup - % Don't complain about control sequences we have declared \outer. - \ignoresections - % - % Define a command to swallow text until we reach `@end #1'. - % This @ is a catcode 12 token (that is the normal catcode of @ in - % this texinfo.tex file). We change the catcode of @ below to match. - \long\def\doignoretext##1@end #1{\enddoignore}% - % - % Make sure that spaces turn into tokens that match what \doignoretext wants. - \catcode32 = 10 - % - % Ignore braces, too, so mismatched braces don't cause trouble. - \catcode`\{ = 9 - \catcode`\} = 9 - % - % We must not have @c interpreted as a control sequence. - \catcode`\@ = 12 - % - % Make the letter c a comment character so that the rest of the line - % will be ignored. This way, the document can have (for example) - % @c @end ifinfo - % and the @end ifinfo will be properly ignored. - % (We've just changed @ to catcode 12.) - \catcode`\c = 14 - % - % And now expand that command. - \doignoretext -} - -% What we do to finish off ignored text. -% -\def\enddoignore{\endgroup\ignorespaces}% - -\newif\ifwarnedobs\warnedobsfalse -\def\obstexwarn{% - \ifwarnedobs\relax\else - % We need to warn folks that they may have trouble with TeX 3.0. - % This uses \immediate\write16 rather than \message to get newlines. - \immediate\write16{} - \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} - \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} - \immediate\write16{If you are running another version of TeX, relax.} - \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} - \immediate\write16{ Then upgrade your TeX installation if you can.} - \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)} - \immediate\write16{If you are stuck with version 3.0, run the} - \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} - \immediate\write16{ to use a workaround.} - \immediate\write16{} - \global\warnedobstrue +\parseargdef\paragraphindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em \fi -} - -% **In TeX 3.0, setting text in \nullfont hangs tex. For a -% workaround (which requires the file ``dummy.tfm'' to be installed), -% uncomment the following line: -%%%%%\font\nullfont=dummy\let\obstexwarn=\relax - -% Ignore text, except that we keep track of conditional commands for -% purposes of nesting, up to an `@end #1' command. -% -\def\nestedignore#1{% - \obstexwarn - % We must actually expand the ignored text to look for the @end - % command, so that nested ignore constructs work. Thus, we put the - % text into a \vbox and then do nothing with the result. To minimize - % the change of memory overflow, we follow the approach outlined on - % page 401 of the TeXbook: make the current font be a dummy font. - % - \setbox0 = \vbox\bgroup - % Don't complain about control sequences we have declared \outer. - \ignoresections - % - % Define `@end #1' to end the box, which will in turn undefine the - % @end command again. - \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% - % - % We are going to be parsing Texinfo commands. Most cause no - % trouble when they are used incorrectly, but some commands do - % complicated argument parsing or otherwise get confused, so we - % undefine them. - % - % We can't do anything about stray @-signs, unfortunately; - % they'll produce `undefined control sequence' errors. - \ignoremorecommands - % - % Set the current font to be \nullfont, a TeX primitive, and define - % all the font commands to also use \nullfont. We don't use - % dummy.tfm, as suggested in the TeXbook, because not all sites - % might have that installed. Therefore, math mode will still - % produce output, but that should be an extremely small amount of - % stuff compared to the main input. - % - \nullfont - \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont - \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont - \let\tensf = \nullfont - % Similarly for index fonts (mostly for their use in - % smallexample) - \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont - \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont - \let\indsf = \nullfont - % - % Don't complain when characters are missing from the fonts. - \tracinglostchars = 0 - % - % Don't bother to do space factor calculations. - \frenchspacing - % - % Don't report underfull hboxes. - \hbadness = 10000 - % - % Do minimal line-breaking. - \pretolerance = 10000 - % - % Do not execute instructions in @tex - \def\tex{\doignore{tex}}% - % Do not execute macro definitions. - % `c' is a comment character, so the word `macro' will get cut off. - \def\macro{\doignore{ma}}% -} - -% @set VAR sets the variable VAR to an empty value. -% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. -% -% Since we want to separate VAR from REST-OF-LINE (which might be -% empty), we can't just use \parsearg; we have to insert a space of our -% own to delimit the rest of the line, and then take it out again if we -% didn't need it. Make sure the catcode of space is correct to avoid -% losing inside @example, for instance. -% -\def\set{\begingroup\catcode` =10 - \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. - \parsearg\setxxx} -\def\setxxx#1{\setyyy#1 \endsetyyy} -\def\setyyy#1 #2\endsetyyy{% - \def\temp{#2}% - \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty - \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. \fi - \endgroup + \parindent = \defaultparindent } -% Can't use \xdef to pre-expand #2 and save some time, since \temp or -% \next or other control sequences that we've defined might get us into -% an infinite loop. Consider `@set foo @cite{bar}'. -\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} -% @clear VAR clears (i.e., unsets) the variable VAR. -% -\def\clear{\parsearg\clearxxx} -\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} - -% @value{foo} gets the text saved in variable foo. -% -{ - \catcode`\_ = \active - % - % We might end up with active _ or - characters in the argument if - % we're called from @code, as @code{@value{foo-bar_}}. So \let any - % such active characters to their normal equivalents. - \gdef\value{\begingroup - \catcode`\-=12 \catcode`\_=12 - \indexbreaks \let_\normalunderscore - \valuexxx} -} -\def\valuexxx#1{\expandablevalue{#1}\endgroup} - -% We have this subroutine so that we can handle at least some @value's -% properly in indexes (we \let\value to this in \indexdummies). Ones -% whose names contain - or _ still won't work, but we can't do anything -% about that. The command has to be fully expandable, since the result -% winds up in the index file. This means that if the variable's value -% contains other Texinfo commands, it's almost certain it will fail -% (although perhaps we could fix that with sufficient work to do a -% one-level expansion on the result, instead of complete). -% -\def\expandablevalue#1{% - \expandafter\ifx\csname SET#1\endcsname\relax - {[No value for ``#1'']}% +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\parseargdef\exampleindent{% + \def\temp{#1}% + \ifx\temp\asisword \else - \csname SET#1\endcsname + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi \fi } -% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined -% with @set. +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indent at such +% paragraphs. % -\def\ifset{\parsearg\ifsetxxx} -\def\ifsetxxx #1{% - \expandafter\ifx\csname SET#1\endcsname\relax - \expandafter\ifsetfail +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. +% We switch the definition of this back and forth according to WORD. +% By default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\def\insertword{insert} +% +\parseargdef\firstparagraphindent{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax \else - \expandafter\ifsetsucceed - \fi -} -\def\ifsetsucceed{\conditionalsucceed{ifset}} -\def\ifsetfail{\nestedignore{ifset}} -\defineunmatchedend{ifset} - -% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been -% defined with @set, or has been undefined with @clear. -% -\def\ifclear{\parsearg\ifclearxxx} -\def\ifclearxxx #1{% - \expandafter\ifx\csname SET#1\endcsname\relax - \expandafter\ifclearsucceed - \else - \expandafter\ifclearfail - \fi -} -\def\ifclearsucceed{\conditionalsucceed{ifclear}} -\def\ifclearfail{\nestedignore{ifclear}} -\defineunmatchedend{ifclear} - -% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text -% following, through the first @end iftex (etc.). Make `@end iftex' -% (etc.) valid only after an @iftex. -% -\def\iftex{\conditionalsucceed{iftex}} -\def\ifnothtml{\conditionalsucceed{ifnothtml}} -\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} -\defineunmatchedend{iftex} -\defineunmatchedend{ifnothtml} -\defineunmatchedend{ifnotinfo} - -% We can't just want to start a group at @iftex (for example) and end it -% at @end iftex, since then @set commands inside the conditional have no -% effect (they'd get reverted at the end of the group). So we must -% define \Eiftex to redefine itself to be its previous value. (We can't -% just define it to fail again with an ``unmatched end'' error, since -% the @ifset might be nested.) -% -\def\conditionalsucceed#1{% - \edef\temp{% - % Remember the current value of \E#1. - \let\nece{prevE#1} = \nece{E#1}% - % - % At the `@end #1', redefine \E#1 to be its previous value. - \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% - }% - \temp + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi } -% We need to expand lots of \csname's, but we don't want to expand the -% control sequences after we've constructed them. +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. % -\def\nece#1{\expandafter\noexpand\csname#1\endcsname} +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent {\restorefirstparagraphindent \indent}% + \gdef\noindent{\restorefirstparagraphindent \noindent}% + \global\everypar = {\kern -\parindent \restorefirstparagraphindent}% +} +% +\gdef\restorefirstparagraphindent{% + \global\let\indent = \ptexindent + \global\let\noindent = \ptexnoindent + \global\everypar = {}% +} -% @asis just yields its argument. Used with @table, for example. -% -\def\asis#1{#1} - -% @math means output in math mode. -% We don't use $'s directly in the definition of \math because control -% sequences like \math are expanded when the toc file is written. Then, -% we read the toc file back, the $'s will be normal characters (as they -% should be, according to the definition of Texinfo). So we must use a -% control sequence to switch into and out of math mode. -% -% This isn't quite enough for @math to work properly in indices, but it -% seems unlikely it will ever be needed there. -% -\let\implicitmath = $ -\def\math#1{\implicitmath #1\implicitmath} - -% @bullet and @minus need the same treatment as @math, just above. -\def\bullet{\implicitmath\ptexbullet\implicitmath} -\def\minus{\implicitmath-\implicitmath} % @refill is a no-op. \let\refill=\relax -% If working on a large document in chapters, it is convenient to -% be able to disable indexing, cross-referencing, and contents, for test runs. -% This is done with @novalidate (before @setfilename). -% -\newif\iflinks \linkstrue % by default we want the aux files. -\let\novalidate = \linksfalse - -% @setfilename is done at the beginning of every texinfo file. -% So open here the files we need to have open while reading the input. -% This makes it possible to make a .fmt file for texinfo. -\def\setfilename{% - \iflinks - \readauxfile - \fi % \openindices needs to do some work in any case. - \openindices - \fixbackslash % Turn off hack to swallow `\input texinfo'. - \global\let\setfilename=\comment % Ignore extra @setfilename cmds. - % - % If texinfo.cnf is present on the system, read it. - % Useful for site-wide @afourpaper, etc. - % Just to be on the safe side, close the input stream before the \input. - \openin 1 texinfo.cnf - \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi - \closein1 - \temp - % - \comment % Ignore the actual filename. -} - -% Called from \setfilename. -% -\def\openindices{% - \newindex{cp}% - \newcodeindex{fn}% - \newcodeindex{vr}% - \newcodeindex{tp}% - \newcodeindex{ky}% - \newcodeindex{pg}% -} +% @setfilename INFO-FILENAME - ignored +\let\setfilename=\comment % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newbox\boxB +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +% +% For LuaTeX +% + +\newif\iftxiuseunicodedestname +\txiuseunicodedestnamefalse % For pdfTeX etc. + +\ifx\luatexversion\thisisundefined +\else + % Use Unicode destination names + \txiuseunicodedestnametrue + % Escape PDF strings with converting UTF-16 from UTF-8 + \begingroup + \catcode`\%=12 + \directlua{ + function UTF16oct(str) + tex.sprint(string.char(0x5c) .. '376' .. string.char(0x5c) .. '377') + for c in string.utfvalues(str) do + if c < 0x10000 then + tex.sprint( + string.format(string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o', + math.floor(c / 256), math.floor(c % 256))) + else + c = c - 0x10000 + local c_hi = c / 1024 + 0xd800 + local c_lo = c % 1024 + 0xdc00 + tex.sprint( + string.format(string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o', + math.floor(c_hi / 256), math.floor(c_hi % 256), + math.floor(c_lo / 256), math.floor(c_lo % 256))) + end + end + end + } + \endgroup + \def\pdfescapestrutfsixteen#1{\directlua{UTF16oct('\luaescapestring{#1}')}} + % Escape PDF strings without converting + \begingroup + \directlua{ + function PDFescstr(str) + for c in string.bytes(str) do + if c <= 0x20 or c >= 0x80 or c == 0x28 or c == 0x29 or c == 0x5c then + tex.sprint(-2, + string.format(string.char(0x5c) .. string.char(0x25) .. '03o', + c)) + else + tex.sprint(-2, string.char(c)) + end + end + end + } + % The -2 in the arguments here gives all the input to TeX catcode 12 + % (other) or 10 (space), preventing undefined control sequence errors. See + % https://lists.gnu.org/archive/html/bug-texinfo/2019-08/msg00031.html + % + \endgroup + \def\pdfescapestring#1{\directlua{PDFescstr('\luaescapestring{#1}')}} + \ifnum\luatexversion>84 + % For LuaTeX >= 0.85 + \def\pdfdest{\pdfextension dest} + \let\pdfoutput\outputmode + \def\pdfliteral{\pdfextension literal} + \def\pdfcatalog{\pdfextension catalog} + \def\pdftexversion{\numexpr\pdffeedback version\relax} + \let\pdfximage\saveimageresource + \let\pdfrefximage\useimageresource + \let\pdflastximage\lastsavedimageresourceindex + \def\pdfendlink{\pdfextension endlink\relax} + \def\pdfoutline{\pdfextension outline} + \def\pdfstartlink{\pdfextension startlink} + \def\pdffontattr{\pdfextension fontattr} + \def\pdfobj{\pdfextension obj} + \def\pdflastobj{\numexpr\pdffeedback lastobj\relax} + \let\pdfpagewidth\pagewidth + \let\pdfpageheight\pageheight + \edef\pdfhorigin{\pdfvariable horigin} + \edef\pdfvorigin{\pdfvariable vorigin} + \fi +\fi + +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as being undefined. +\ifx\pdfoutput\thisisundefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi + +\newif\ifpdforxetex +\pdforxetexfalse +\ifpdf + \pdforxetextrue +\fi +\ifx\XeTeXrevision\thisisundefined\else + \pdforxetextrue +\fi + + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% +% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and +% related messages. The final outcome is that it is up to the TeX user +% to double the backslashes and otherwise make the string valid, so +% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to +% do this reliably, so we use it. + +% #1 is a control sequence in which to do the replacements, +% which we \xdef. +\def\txiescapepdf#1{% + \ifx\pdfescapestring\thisisundefined + % No primitive available; should we give a warning or log? + % Many times it won't matter. + \xdef#1{#1}% + \else + % The expandable \pdfescapestring primitive escapes parentheses, + % backslashes, and other special chars. + \xdef#1{\pdfescapestring{#1}}% + \fi +} +\def\txiescapepdfutfsixteen#1{% + \ifx\pdfescapestrutfsixteen\thisisundefined + % No UTF-16 converting macro available. + \txiescapepdf{#1}% + \else + \xdef#1{\pdfescapestrutfsixteen{#1}}% + \fi +} + +\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images +with PDF output, and none of those formats could be found. (.eps cannot +be supported due to the design of the PDF format; use regular TeX (DVI +output) for that.)} + +\ifpdf + % + % Color manipulation macros using ideas from pdfcolor.tex, + % except using rgb instead of cmyk; the latter is said to render as a + % very dark gray on-screen and a very dark halftone in print, instead + % of actual black. The dark red here is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. We use + % black by default, though. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + % rg sets the color for filling (usual text, etc.); + % RG sets the color for stroking (thin rules, e.g., normal _'s). + \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\rgbBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\currentcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % + \pdfcatalog{/PageMode /UseOutlines} + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\dopdfimage#1#2#3{% + \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % pdftex (and the PDF format) support .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if + % someone has a scalable image, presumably better to use that than a + % bitmap. + \let\pdfimgext=\empty + \begingroup + \openin 1 #1.pdf \ifeof 1 + \openin 1 #1.PDF \ifeof 1 + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \errhelp = \nopdfimagehelp + \errmessage{Could not find image file #1 for pdf}% + \else \gdef\pdfimgext{JPG}% + \fi + \else \gdef\pdfimgext{jpeg}% + \fi + \else \gdef\pdfimgext{jpg}% + \fi + \else \gdef\pdfimgext{png}% + \fi + \else \gdef\pdfimgext{PDF}% + \fi + \else \gdef\pdfimgext{pdf}% + \fi + \closein 1 + \endgroup + % + % without \immediate, ancient pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifdim \wd0 >0pt width \pdfimagewidth \fi + \ifdim \wd2 >0pt height \pdfimageheight \fi + \ifnum\pdftexversion<13 + #1.\pdfimgext + \else + {#1.\pdfimgext}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + % + \def\setpdfdestname#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \makevalueexpandable + \turnoffactive + \iftxiuseunicodedestname + \ifx \declaredencoding \latone + % Pass through Latin-1 characters. + % LuaTeX with byte wise I/O converts Latin-1 characters to Unicode. + \else + \ifx \declaredencoding \utfeight + % Pass through Unicode characters. + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi + \fi + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi + \def\pdfdestname{#1}% + \txiescapepdf\pdfdestname + }} + % + \def\setpdfoutlinetext#1{{% + \indexnofonts + \makevalueexpandable + \turnoffactive + \ifx \declaredencoding \latone + % The PDF format can use an extended form of Latin-1 in bookmark + % strings. See Appendix D of the PDF Reference, Sixth Edition, for + % the "PDFDocEncoding". + \passthroughcharstrue + % Pass through Latin-1 characters. + % LuaTeX: Convert to Unicode + % pdfTeX: Use Latin-1 as PDFDocEncoding + \def\pdfoutlinetext{#1}% + \else + \ifx \declaredencoding \utfeight + \ifx\luatexversion\thisisundefined + % For pdfTeX with UTF-8. + % TODO: the PDF format can use UTF-16 in bookmark strings, + % but the code for this isn't done yet. + % Use ASCII approximations. + \passthroughcharsfalse + \def\pdfoutlinetext{#1}% + \else + % For LuaTeX with UTF-8. + % Pass through Unicode characters for title texts. + \passthroughcharstrue + \def\pdfoutlinetext{#1}% + \fi + \else + % For non-Latin-1 or non-UTF-8 encodings. + % Use ASCII approximations. + \passthroughcharsfalse + \def\pdfoutlinetext{#1}% + \fi + \fi + % LuaTeX: Convert to UTF-16 + % pdfTeX: Use Latin-1 as PDFDocEncoding + \txiescapepdfutfsixteen\pdfoutlinetext + }} + % + \def\pdfmkdest#1{% + \setpdfdestname{#1}% + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + } + % + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1} + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \def\linkcolor{\rgbBlack} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by 1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + % + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worth the trouble, since most documents are normally structured. + \setpdfoutlinetext{#1} + \setpdfdestname{#3} + \ifx\pdfdestname\empty + \def\pdfdestname{#4}% + \fi + % + \pdfoutline goto name{\pdfmkpgn{\pdfdestname}}#2{\pdfoutlinetext}% + } + % + \def\pdfmakeoutlines{% + \begingroup + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\partentry##1##2##3##4{}% ignore parts in the outlines + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \def\thissubsecnum{0}% + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% + \readdatafile{toc}% + % + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. + % + % TODO this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Too + % much work for too little return. Just use the ASCII equivalents + % we use for the index sort strings. + % + \indexnofonts + \setupdatafile + % We can have normal brace characters in the PDF outlines, unlike + % Texinfo index files. So set that up. + \def\{{\lbracecharliteral}% + \def\}{\rbracecharliteral}% + \catcode`\\=\active \otherbackslash + \input \tocreadfilename + \endgroup + } + {\catcode`[=1 \catcode`]=2 + \catcode`{=\other \catcode`}=\other + \gdef\lbracecharliteral[{]% + \gdef\rbracecharliteral[}]% + ] + % + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \nextsp} + \def\getfilename#1{% + \filenamelength=0 + % If we don't expand the argument now, \skipspaces will get + % snagged on things like "@value{foo}". + \edef\temp{#1}% + \expandafter\skipspaces\temp|\relax + } + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + \endgroup} + % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may + % be a simple number, or a list of numbers in the case of an index + % entry. + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \setcolor{\linkcolor}#1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\else + % non-pdf mode + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\setcolor = \gobble + \let\pdfsetcolor = \gobble + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput + +% +% For XeTeX +% +\ifx\XeTeXrevision\thisisundefined +\else + % + % XeTeX version check + % + \ifnum\strcmp{\the\XeTeXversion\XeTeXrevision}{0.99996}>-1 + % TeX Live 2016 contains XeTeX 0.99996 and xdvipdfmx 20160307. + % It can use the `dvipdfmx:config' special (from TeX Live SVN r40941). + % For avoiding PDF destination name replacement, we use this special + % instead of xdvipdfmx's command line option `-C 0x0010'. + \special{dvipdfmx:config C 0x0010} + % XeTeX 0.99995+ comes with xdvipdfmx 20160307+. + % It can handle Unicode destination names for PDF. + \txiuseunicodedestnametrue + \else + % XeTeX < 0.99996 (TeX Live < 2016) cannot use the + % `dvipdfmx:config' special. + % So for avoiding PDF destination name replacement, + % xdvipdfmx's command line option `-C 0x0010' is necessary. + % + % XeTeX < 0.99995 can not handle Unicode destination names for PDF + % because xdvipdfmx 20150315 has a UTF-16 conversion issue. + % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). + \txiuseunicodedestnamefalse + \fi + % + % Color support + % + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + \def\pdfsetcolor#1{\special{pdf:scolor [#1]}} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\rgbBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\currentcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % PDF outline support + % + % Emulate pdfTeX primitive + \def\pdfdest name#1 xyz{% + \special{pdf:dest (#1) [@thispage /XYZ @xpos @ypos null]}% + } + % + \def\setpdfdestname#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \makevalueexpandable + \turnoffactive + \iftxiuseunicodedestname + % Pass through Unicode characters. + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi + \def\pdfdestname{#1}% + \txiescapepdf\pdfdestname + }} + % + \def\setpdfoutlinetext#1{{% + \turnoffactive + % Always use Unicode characters in title texts. + \def\pdfoutlinetext{#1}% + % For XeTeX, xdvipdfmx converts to UTF-16. + % So we do not convert. + \txiescapepdf\pdfoutlinetext + }} + % + \def\pdfmkdest#1{% + \setpdfdestname{#1}% + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + } + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \def\linkcolor{\rgbBlack} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + \def\dopdfoutline#1#2#3#4{% + \setpdfoutlinetext{#1} + \setpdfdestname{#3} + \ifx\pdfdestname\empty + \def\pdfdestname{#4}% + \fi + % + \special{pdf:out [-] #2 << /Title (\pdfoutlinetext) /A + << /S /GoTo /D (\pdfdestname) >> >> }% + } + % + \def\pdfmakeoutlines{% + \begingroup + % + % For XeTeX, counts of subentries are not necessary. + % Therefore, we read toc only once. + % + % We use node names as destinations. + \def\partentry##1##2##3##4{}% ignore parts in the outlines + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{1}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{2}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{3}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{4}{##3}{##4}}% + % + \let\appentry\numchapentry% + \let\appsecentry\numsecentry% + \let\appsubsecentry\numsubsecentry% + \let\appsubsubsecentry\numsubsubsecentry% + \let\unnchapentry\numchapentry% + \let\unnsecentry\numsecentry% + \let\unnsubsecentry\numsubsecentry% + \let\unnsubsubsecentry\numsubsubsecentry% + % + % For XeTeX, xdvipdfmx converts strings to UTF-16. + % Therefore, the encoding and the language may not be considered. + % + \indexnofonts + \setupdatafile + % We can have normal brace characters in the PDF outlines, unlike + % Texinfo index files. So set that up. + \def\{{\lbracecharliteral}% + \def\}{\rbracecharliteral}% + \catcode`\\=\active \otherbackslash + \input \tocreadfilename + \endgroup + } + {\catcode`[=1 \catcode`]=2 + \catcode`{=\other \catcode`}=\other + \gdef\lbracecharliteral[{]% + \gdef\rbracecharliteral[}]% + ] + + \special{pdf:docview << /PageMode /UseOutlines >> } + % ``\special{pdf:tounicode ...}'' is not necessary + % because xdvipdfmx converts strings from UTF-8 to UTF-16 without it. + % However, due to a UTF-16 conversion issue of xdvipdfmx 20150315, + % ``\special{pdf:dest ...}'' cannot handle non-ASCII strings. + % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). +% + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \nextsp} + \def\getfilename#1{% + \filenamelength=0 + % If we don't expand the argument now, \skipspaces will get + % snagged on things like "@value{foo}". + \edef\temp{#1}% + \expandafter\skipspaces\temp|\relax + } + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \special{pdf:bann << /Border [0 0 0] + /Subtype /Link /A << /S /URI /URI (#1) >> >>}% + \endgroup} + \def\endlink{\setcolor{\maincolor}\special{pdf:eann}} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \special{pdf:bann << /Border [0 0 0] + /Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}% + \setcolor{\linkcolor}#1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +% + % + % @image support + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\doxeteximage#1#2#3{% + \def\xeteximagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\xeteximageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % XeTeX (and the PDF format) supports .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if + % someone has a scalable image, presumably better to use that than a + % bitmap. + \let\xeteximgext=\empty + \begingroup + \openin 1 #1.pdf \ifeof 1 + \openin 1 #1.PDF \ifeof 1 + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \errmessage{Could not find image file #1 for XeTeX}% + \else \gdef\xeteximgext{JPG}% + \fi + \else \gdef\xeteximgext{jpeg}% + \fi + \else \gdef\xeteximgext{jpg}% + \fi + \else \gdef\xeteximgext{png}% + \fi + \else \gdef\xeteximgext{PDF}% + \fi + \else \gdef\xeteximgext{pdf}% + \fi + \closein 1 + \endgroup + % + \def\xetexpdfext{pdf}% + \ifx\xeteximgext\xetexpdfext + \XeTeXpdffile "#1".\xeteximgext "" + \else + \def\xetexpdfext{PDF}% + \ifx\xeteximgext\xetexpdfext + \XeTeXpdffile "#1".\xeteximgext "" + \else + \XeTeXpicfile "#1".\xeteximgext "" + \fi + \fi + \ifdim \wd0 >0pt width \xeteximagewidth \fi + \ifdim \wd2 >0pt height \xeteximageheight \fi \relax + } +\fi + + +% \message{fonts,} -% Font-change commands. -% Texinfo sort of supports the sans serif font style, which plain TeX does not. -% So we set up a \sf analogous to plain's \rm, etc. -\newfam\sffam -\def\sf{\fam=\sffam \tensf} -\let\li = \sf % Sometimes we call it \li, not \sf. +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +% can get a sort of poor man's double spacing by redefining this. +\def\baselinefactor{1} +% +\newdimen\textleading +\def\setleading#1{% + \dimen0 = #1\relax + \normalbaselineskip = \baselinefactor\dimen0 + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} -% We don't need math for this one. -\def\ttsl{\tenttsl} +% PDF CMaps. See also LaTeX's t1.cmap. +% +% do nothing with this by default. +\expandafter\let\csname cmapOT1\endcsname\gobble +\expandafter\let\csname cmapOT1IT\endcsname\gobble +\expandafter\let\csname cmapOT1TT\endcsname\gobble -% Use Computer Modern fonts at \magstephalf (11pt). -\newcount\mainmagstep -\mainmagstep=\magstephalf +% if we are producing pdf, and we have \pdffontattr, then define cmaps. +% (\pdffontattr was introduced many years ago, but people still run +% older pdftex's; it's easy to conditionalize, so we do.) +\ifpdf \ifx\pdffontattr\thisisundefined \else + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1-0) +%%Title: (TeX-OT1-0 TeX OT1 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1) +/Supplement 0 +>> def +/CMapName /TeX-OT1-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<23> <26> <0023> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +40 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1IT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1IT-0) +%%Title: (TeX-OT1IT-0 TeX OT1IT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1IT) +/Supplement 0 +>> def +/CMapName /TeX-OT1IT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<25> <26> <0025> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +42 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<23> <0023> +<24> <00A3> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1IT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1TT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1TT-0) +%%Title: (TeX-OT1TT-0 TeX OT1TT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1TT) +/Supplement 0 +>> def +/CMapName /TeX-OT1TT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +5 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<21> <26> <0021> +<28> <5F> <0028> +<61> <7E> <0061> +endbfrange +32 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <2191> +<0C> <2193> +<0D> <0027> +<0E> <00A1> +<0F> <00BF> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<20> <2423> +<27> <2019> +<60> <2018> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1TT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +\fi\fi -% Set the font macro #1 to the font named #2, adding on the -% specified font prefix (normally `cm'). -% #3 is the font's design size, #4 is a scale factor -\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Set the font macro #1 to the font named \fontprefix#2. +% #3 is the font's design size, #4 is a scale factor, #5 is the CMap +% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). +% Example: +% #1 = \textrm +% #2 = \rmshape +% #3 = 10 +% #4 = \mainmagstep +% #5 = OT1 +% +\def\setfont#1#2#3#4#5{% + \font#1=\fontprefix#2#3 scaled #4 + \csname cmap#5\endcsname#1% +} +% This is what gets called when #5 of \setfont is empty. +\let\cmap\gobble +% +% (end of cmaps) % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. -\ifx\fontprefix\undefined +\ifx\fontprefix\thisisundefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} -\def\rmbshape{bx} %where the normal face is bold +\def\rmbshape{bx} % where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} @@ -1165,201 +2158,671 @@ where each line of input produces a line of output.} \def\scshape{csc} \def\scbshape{csc} -\ifx\bigger\relax -\let\mainmagstep=\magstep1 -\setfont\textrm\rmshape{12}{1000} -\setfont\texttt\ttshape{12}{1000} -\else -\setfont\textrm\rmshape{10}{\mainmagstep} -\setfont\texttt\ttshape{10}{\mainmagstep} -\fi -% Instead of cmb10, you many want to use cmbx10. -% cmbx10 is a prettier font on its own, but cmb10 -% looks better when embedded in a line with cmr10. -\setfont\textbf\bfshape{10}{\mainmagstep} -\setfont\textit\itshape{10}{\mainmagstep} -\setfont\textsl\slshape{10}{\mainmagstep} -\setfont\textsf\sfshape{10}{\mainmagstep} -\setfont\textsc\scshape{10}{\mainmagstep} -\setfont\textttsl\ttslshape{10}{\mainmagstep} +% Definitions for a main text size of 11pt. (The default in Texinfo.) +% +\def\definetextfontsizexi{% +% Text fonts (11.2pt, magstep1). +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1095} -% A few fonts for @defun, etc. -\setfont\defbf\bxshape{10}{\magstep1} %was 1314 -\setfont\deftt\ttshape{10}{\magstep1} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1}{OT1} +\setfont\deftt\ttshape{10}{\magstep1}{OT1TT} +\setfont\defsl\slshape{10}{\magstep1}{OT1} +\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} +\def\df{\let\ttfont=\deftt \let\bffont = \defbf +\let\ttslfont=\defttsl \let\slfont=\defsl \bf} -% Fonts for indices and small examples (9pt). -% We actually use the slanted font rather than the italic, -% because texinfo normally uses the slanted fonts for that. -% Do not make many font distinctions in general in the index, since they -% aren't very useful. -\setfont\ninett\ttshape{9}{1000} -\setfont\ninettsl\ttslshape{10}{900} -\setfont\indrm\rmshape{9}{1000} -\setfont\indit\itshape{9}{1000} -\setfont\indsl\slshape{9}{1000} -\let\indtt=\ninett -\let\indttsl=\ninettsl -\let\indsf=\indrm -\let\indbf=\indrm -\setfont\indsc\scshape{10}{900} -\font\indi=cmmi9 -\font\indsy=cmsy9 +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} -% Fonts for title page: -\setfont\titlerm\rmbshape{12}{\magstep3} -\setfont\titleit\itbshape{10}{\magstep4} -\setfont\titlesl\slbshape{10}{\magstep4} -\setfont\titlett\ttbshape{12}{\magstep3} -\setfont\titlettsl\ttslshape{10}{\magstep4} -\setfont\titlesf\sfbshape{17}{\magstep1} +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for math mode superscripts (7pt). +\def\sevennominalsize{7pt} +\setfont\sevenrm\rmshape{7}{1000}{OT1} +\setfont\seventt\ttshape{10}{700}{OT1TT} +\setfont\sevenbf\bfshape{10}{700}{OT1} +\setfont\sevenit\itshape{7}{1000}{OT1IT} +\setfont\sevensl\slshape{10}{700}{OT1} +\setfont\sevensf\sfshape{10}{700}{OT1} +\setfont\sevensc\scshape{10}{700}{OT1} +\setfont\seventtsl\ttslshape{10}{700}{OT1TT} +\font\seveni=cmmi7 +\font\sevensy=cmsy7 +\def\sevenecsize{0700} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4} +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 -\def\authorrm{\secrm} +\def\titleecsize{2074} % Chapter (and unnumbered) fonts (17.28pt). -\setfont\chaprm\rmbshape{12}{\magstep2} -\setfont\chapit\itbshape{10}{\magstep3} -\setfont\chapsl\slbshape{10}{\magstep3} -\setfont\chaptt\ttbshape{12}{\magstep2} -\setfont\chapttsl\ttslshape{10}{\magstep3} -\setfont\chapsf\sfbshape{17}{1000} +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2}{OT1} +\setfont\chapit\itbshape{10}{\magstep3}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep3}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} +\setfont\chapsf\sfbshape{17}{1000}{OT1} \let\chapbf=\chaprm -\setfont\chapsc\scbshape{10}{\magstep3} +\setfont\chapsc\scbshape{10}{\magstep3}{OT1} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 +\def\chapecsize{1728} % Section fonts (14.4pt). -\setfont\secrm\rmbshape{12}{\magstep1} -\setfont\secit\itbshape{10}{\magstep2} -\setfont\secsl\slbshape{10}{\magstep2} -\setfont\sectt\ttbshape{12}{\magstep1} -\setfont\secttsl\ttslshape{10}{\magstep2} -\setfont\secsf\sfbshape{12}{\magstep1} +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1}{OT1} +\setfont\secrmnotbold\rmshape{12}{\magstep1}{OT1} +\setfont\secit\itbshape{10}{\magstep2}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep2}{OT1} +\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\secsf\sfbshape{12}{\magstep1}{OT1} \let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep2} +\setfont\secsc\scbshape{10}{\magstep2}{OT1} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 - -% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. -% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. -% \setfont\ssecsl\slshape{10}{\magstep1} -% \setfont\ssectt\ttshape{10}{\magstep1} -% \setfont\ssecsf\sfshape{10}{\magstep1} - -%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. -%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than -%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. -%\setfont\ssectt\ttshape{10}{1315} -%\setfont\ssecsf\sfshape{10}{1315} - -%\let\ssecbf=\ssecrm +\def\sececsize{1440} % Subsection fonts (13.15pt). -\setfont\ssecrm\rmbshape{12}{\magstephalf} -\setfont\ssecit\itbshape{10}{1315} -\setfont\ssecsl\slbshape{10}{1315} -\setfont\ssectt\ttbshape{12}{\magstephalf} -\setfont\ssecttsl\ttslshape{10}{1315} -\setfont\ssecsf\sfbshape{12}{\magstephalf} +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} +\setfont\ssecit\itbshape{10}{1315}{OT1IT} +\setfont\ssecsl\slbshape{10}{1315}{OT1} +\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} +\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} \let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{\magstep1} +\setfont\ssecsc\scbshape{10}{1315}{OT1} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 -% The smallcaps and symbol fonts should actually be scaled \magstep1.5, -% but that is not a standard magnification. +\def\ssececsize{1200} -% In order for the font changes to affect most math symbols and letters, -% we have to define the \textfont of the standard families. Since -% texinfo doesn't allow for producing subscripts and superscripts, we -% don't bother to reset \scriptfont and \scriptscriptfont (which would -% also require loading a lot more fonts). +% Reduced fonts for @acronym in text (10pt). +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000}{OT1} +\setfont\reducedtt\ttshape{10}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{1000}{OT1} +\setfont\reducedit\itshape{10}{1000}{OT1IT} +\setfont\reducedsl\slshape{10}{1000}{OT1} +\setfont\reducedsf\sfshape{10}{1000}{OT1} +\setfont\reducedsc\scshape{10}{1000}{OT1} +\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 +\def\reducedecsize{1000} + +\textleading = 13.2pt % line spacing for 11pt CM +\textfonts % reset the current fonts +\rm +} % end of 11pt text font size definitions, \definetextfontsizexi + + +% Definitions to make the main text be 10pt Computer Modern, with +% section, chapter, etc., sizes following suit. This is for the GNU +% Press printing of the Emacs 22 manual. Maybe other manuals in the +% future. Used with @smallbook, which sets the leading to 12pt. % -\def\resetmathfonts{% - \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy - \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf - \textfont\ttfam = \tentt \textfont\sffam = \tensf +\def\definetextfontsizex{% +% Text fonts (10pt). +\def\textnominalsize{10pt} +\edef\mainmagstep{1000} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1000} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstephalf}{OT1} +\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} +\setfont\defsl\slshape{10}{\magstephalf}{OT1} +\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} +\def\df{\let\ttfont=\deftt \let\bffont = \defbf +\let\slfont=\defsl \let\ttslfont=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for math mode superscripts (7pt). +\def\sevennominalsize{7pt} +\setfont\sevenrm\rmshape{7}{1000}{OT1} +\setfont\seventt\ttshape{10}{700}{OT1TT} +\setfont\sevenbf\bfshape{10}{700}{OT1} +\setfont\sevenit\itshape{7}{1000}{OT1IT} +\setfont\sevensl\slshape{10}{700}{OT1} +\setfont\sevensf\sfshape{10}{700}{OT1} +\setfont\sevensc\scshape{10}{700}{OT1} +\setfont\seventtsl\ttslshape{10}{700}{OT1TT} +\font\seveni=cmmi7 +\font\sevensy=cmsy7 +\def\sevenecsize{0700} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\titleecsize{2074} + +% Chapter fonts (14.4pt). +\def\chapnominalsize{14pt} +\setfont\chaprm\rmbshape{12}{\magstep1}{OT1} +\setfont\chapit\itbshape{10}{\magstep2}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep2}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\chapsf\sfbshape{12}{\magstep1}{OT1} +\let\chapbf\chaprm +\setfont\chapsc\scbshape{10}{\magstep2}{OT1} +\font\chapi=cmmi12 scaled \magstep1 +\font\chapsy=cmsy10 scaled \magstep2 +\def\chapecsize{1440} + +% Section fonts (12pt). +\def\secnominalsize{12pt} +\setfont\secrm\rmbshape{12}{1000}{OT1} +\setfont\secit\itbshape{10}{\magstep1}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep1}{OT1} +\setfont\sectt\ttbshape{12}{1000}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} +\setfont\secsf\sfbshape{12}{1000}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep1}{OT1} +\font\seci=cmmi12 +\font\secsy=cmsy10 scaled \magstep1 +\def\sececsize{1200} + +% Subsection fonts (10pt). +\def\ssecnominalsize{10pt} +\setfont\ssecrm\rmbshape{10}{1000}{OT1} +\setfont\ssecit\itbshape{10}{1000}{OT1IT} +\setfont\ssecsl\slbshape{10}{1000}{OT1} +\setfont\ssectt\ttbshape{10}{1000}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} +\setfont\ssecsf\sfbshape{10}{1000}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1000}{OT1} +\font\sseci=cmmi10 +\font\ssecsy=cmsy10 +\def\ssececsize{1000} + +% Reduced fonts for @acronym in text (9pt). +\def\reducednominalsize{9pt} +\setfont\reducedrm\rmshape{9}{1000}{OT1} +\setfont\reducedtt\ttshape{9}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{900}{OT1} +\setfont\reducedit\itshape{9}{1000}{OT1IT} +\setfont\reducedsl\slshape{9}{1000}{OT1} +\setfont\reducedsf\sfshape{9}{1000}{OT1} +\setfont\reducedsc\scshape{10}{900}{OT1} +\setfont\reducedttsl\ttslshape{10}{900}{OT1TT} +\font\reducedi=cmmi9 +\font\reducedsy=cmsy9 +\def\reducedecsize{0900} + +\divide\parskip by 2 % reduce space between paragraphs +\textleading = 12pt % line spacing for 10pt CM +\textfonts % reset the current fonts +\rm +} % end of 10pt text font size definitions, \definetextfontsizex + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000}{OT1} +\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000}{OT1} +\setfont\shortconttt\ttshape{12}{1000}{OT1TT} + + +% We provide the user-level command +% @fonttextsize 10 +% (or 11) to redefine the text font size. pt is assumed. +% +\def\xiword{11} +\def\xword{10} +\def\xwordpt{10pt} +% +\parseargdef\fonttextsize{% + \def\textsizearg{#1}% + %\wlog{doing @fonttextsize \textsizearg}% + % + % Set \globaldefs so that documents can use this inside @tex, since + % makeinfo 4.8 does not support it, but we need it nonetheless. + % + \begingroup \globaldefs=1 + \ifx\textsizearg\xword \definetextfontsizex + \else \ifx\textsizearg\xiword \definetextfontsizexi + \else + \errhelp=\EMsimple + \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} + \fi\fi + \endgroup } +% +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname #1font\endcsname % change the current font +} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. +% We don't bother to reset \scriptscriptfont; awaiting user need. +% +\def\resetmathfonts{% + \textfont0=\rmfont \textfont1=\ifont \textfont2=\syfont + \textfont\itfam=\itfont \textfont\slfam=\slfont \textfont\bffam=\bffont + \textfont\ttfam=\ttfont \textfont\sffam=\sffont + % + % Fonts for superscript. Note that the 7pt fonts are used regardless + % of the current font size. + \scriptfont0=\sevenrm \scriptfont1=\seveni \scriptfont2=\sevensy + \scriptfont\itfam=\sevenit \scriptfont\slfam=\sevensl + \scriptfont\bffam=\sevenbf \scriptfont\ttfam=\seventt + \scriptfont\sffam=\sevensf +} + +% + +% The font-changing commands (all called \...fonts) redefine the meanings +% of \STYLEfont, instead of just \STYLE. We do this because \STYLE needs +% to also set the current \fam for math mode. Our \STYLE (e.g., \rm) +% commands hardwire \STYLEfont to set the current font. +% +% The fonts used for \ifont are for "math italics" (\itfont is for italics +% in regular text). \syfont is also used in math mode only. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used +% in, e.g., the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% + +\def\assignfonts#1{% + \expandafter\let\expandafter\rmfont\csname #1rm\endcsname + \expandafter\let\expandafter\itfont\csname #1it\endcsname + \expandafter\let\expandafter\slfont\csname #1sl\endcsname + \expandafter\let\expandafter\bffont\csname #1bf\endcsname + \expandafter\let\expandafter\ttfont\csname #1tt\endcsname + \expandafter\let\expandafter\smallcaps\csname #1sc\endcsname + \expandafter\let\expandafter\sffont \csname #1sf\endcsname + \expandafter\let\expandafter\ifont \csname #1i\endcsname + \expandafter\let\expandafter\syfont \csname #1sy\endcsname + \expandafter\let\expandafter\ttslfont\csname #1ttsl\endcsname +} + +\newif\ifrmisbold + +% Select smaller font size with the current style. Used to change font size +% in, e.g., the LaTeX logo and acronyms. If we are using bold fonts for +% normal roman text, also use bold fonts for roman text in the smaller size. +\def\switchtolllsize{% + \expandafter\assignfonts\expandafter{\lllsize}% + \ifrmisbold + \let\rmfont\bffont + \fi + \csname\curfontstyle\endcsname +}% + +\def\switchtolsize{% + \expandafter\assignfonts\expandafter{\lsize}% + \ifrmisbold + \let\rmfont\bffont + \fi + \csname\curfontstyle\endcsname +}% + +\def\definefontsetatsize#1#2#3#4#5{% +\expandafter\def\csname #1fonts\endcsname{% + \def\curfontsize{#1}% + \def\lsize{#2}\def\lllsize{#3}% + \csname rmisbold#5\endcsname + \assignfonts{#1}% + \resetmathfonts + \setleading{#4}% +}} + +\definefontsetatsize{text} {reduced}{smaller}{\textleading}{false} +\definefontsetatsize{title} {chap} {subsec} {27pt} {true} +\definefontsetatsize{chap} {sec} {text} {19pt} {true} +\definefontsetatsize{sec} {subsec} {reduced}{17pt} {true} +\definefontsetatsize{ssec} {text} {small} {15pt} {true} +\definefontsetatsize{reduced}{small} {smaller}{10.5pt}{false} +\definefontsetatsize{small} {smaller}{smaller}{10.5pt}{false} +\definefontsetatsize{smaller}{smaller}{smaller}{9.5pt} {false} -% The font-changing commands redefine the meanings of \tenSTYLE, instead -% of just \STYLE. We do this so that font changes will continue to work -% in math mode, where it is the current \fam that is relevant in most -% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam -% \tenbf}, for example. By redefining \tenbf, we obviate the need to -% redefine \bf itself. -\def\textfonts{% - \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl - \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc - \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl - \resetmathfonts} -\def\titlefonts{% - \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl - \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc - \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy - \let\tenttsl=\titlettsl - \resetmathfonts \setleading{25pt}} \def\titlefont#1{{\titlefonts\rm #1}} -\def\chapfonts{% - \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl - \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl - \resetmathfonts \setleading{19pt}} -\def\secfonts{% - \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl - \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc - \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl - \resetmathfonts \setleading{16pt}} -\def\subsecfonts{% - \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl - \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc - \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl - \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? -\def\indexfonts{% - \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl - \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc - \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl - \resetmathfonts \setleading{12pt}} +\let\subsecfonts = \ssecfonts +\let\subsubsecfonts = \ssecfonts + +% Define these just so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \scriptfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % -\textfonts +\definetextfontsizexi -% Define these so they can be easily changed for other fonts. -\def\angleleft{$\langle$} -\def\angleright{$\rangle$} + +\message{markup,} + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will +% define and register \INITMACRO to be called on markup style changes. +% \INITMACRO can check \currentmarkupstyle for the innermost +% style. + +\let\currentmarkupstyle\empty + +\def\setupmarkupstyle#1{% + \def\currentmarkupstyle{#1}% + \markupstylesetup +} + +\let\markupstylesetup\empty + +\def\defmarkupstylesetup#1{% + \expandafter\def\expandafter\markupstylesetup + \expandafter{\markupstylesetup #1}% + \def#1% +} + +% Markup style setup for left and right quotes. +\defmarkupstylesetup\markupsetuplq{% + \expandafter\let\expandafter \temp + \csname markupsetuplq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuplqdefault \else \temp \fi +} + +\defmarkupstylesetup\markupsetuprq{% + \expandafter\let\expandafter \temp + \csname markupsetuprq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuprqdefault \else \temp \fi +} + +{ +\catcode`\'=\active +\catcode`\`=\active + +\gdef\markupsetuplqdefault{\let`\lq} +\gdef\markupsetuprqdefault{\let'\rq} + +\gdef\markupsetcodequoteleft{\let`\codequoteleft} +\gdef\markupsetcodequoteright{\let'\codequoteright} +} + +\let\markupsetuplqcode \markupsetcodequoteleft +\let\markupsetuprqcode \markupsetcodequoteright +% +\let\markupsetuplqexample \markupsetcodequoteleft +\let\markupsetuprqexample \markupsetcodequoteright +% +\let\markupsetuplqkbd \markupsetcodequoteleft +\let\markupsetuprqkbd \markupsetcodequoteright +% +\let\markupsetuplqsamp \markupsetcodequoteleft +\let\markupsetuprqsamp \markupsetcodequoteright +% +\let\markupsetuplqverb \markupsetcodequoteleft +\let\markupsetuprqverb \markupsetcodequoteright +% +\let\markupsetuplqverbatim \markupsetcodequoteleft +\let\markupsetuprqverbatim \markupsetcodequoteright + +% Allow an option to not use regular directed right quote/apostrophe +% (char 0x27), but instead the undirected quote from cmtt (char 0x0d). +% The undirected quote is ugly, so don't make it the default, but it +% works for pasting with more pdf viewers (at least evince), the +% lilypond developers report. xpdf does work with the regular 0x27. +% +\def\codequoteright{% + \ifmonospace + \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else \char'15 \fi + \else \char'15 \fi + \else + '% + \fi +} +% +% and a similar option for the left quote char vs. a grave accent. +% Modern fonts display ASCII 0x60 as a grave accent, so some people like +% the code environments to do likewise. +% +\def\codequoteleft{% + \ifmonospace + \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + % [Knuth] pp. 380,381,391 + % \relax disables Spanish ligatures ?` and !` of \tt font. + \relax`% + \else \char'22 \fi + \else \char'22 \fi + \else + \relax`% + \fi +} + +% Commands to set the quote options. +% +\parseargdef\codequoteundirected{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}% + \fi\fi +} +% +\parseargdef\codequotebacktick{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}% + \fi\fi +} + +% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. +\def\noligaturesquoteleft{\relax\lq} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000} -\setfont\shortcontbf\bxshape{12}{1000} -\setfont\shortcontsl\slshape{12}{1000} +% Font commands. -%% Add scribe-like font environments, plus @l for inline lisp (usually sans -%% serif) and @ii for TeX italic +% #1 is the font command (\sl or \it), #2 is the text to slant. +% If we are in a monospaced environment, however, 1) always use \ttsl, +% and 2) do not add an italic correction. +\def\dosmartslant#1#2{% + \ifusingtt + {{\ttsl #2}\let\next=\relax}% + {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% + \next +} +\def\smartslanted{\dosmartslant\sl} +\def\smartitalic{\dosmartslant\it} -% \smartitalic{ARG} outputs arg in italics, followed by an italic correction -% unless the following character is such as not to need one. -\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} -\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx} -\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx} +% Output an italic correction unless \next (presumed to be the following +% character) is such as not to need one. +\def\smartitaliccorrection{% + \ifx\next,% + \else\ifx\next-% + \else\ifx\next.% + \else\ifx\next\.% + \else\ifx\next\comma% + \else\ptexslash + \fi\fi\fi\fi\fi + \aftersmartic +} + +% Unconditional use \ttsl, and no ic. @var is set to this for defuns. +\def\ttslanted#1{{\ttsl #1}} + +% @cite is like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} + +\def\aftersmartic{} +\def\var#1{% + \let\saveaftersmartic = \aftersmartic + \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% + \smartslanted{#1}% +} \let\i=\smartitalic -\let\var=\smartslanted +\let\slanted=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic -\let\cite=\smartslanted +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @b, explicit bold. Also @strong. \def\b#1{{\bf #1}} \let\strong=\b +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. @@ -1367,30 +2830,39 @@ where each line of input produces a line of output.} \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\plainfrenchspacing{% + \sfcode`\.=\@m \sfcode`\?=\@m \sfcode`\!=\@m + \sfcode`\:=\@m \sfcode`\;=\@m \sfcode`\,=\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends + } +\catcode`@=\other +\def\endofsentencespacefactor{3000}% default + +% @t, explicit typewriter. \def\t#1{% - {\tt \rawbackslash \frenchspacing #1}% + {\tt \plainfrenchspacing #1}% \null } -\let\ttfont=\t -\def\samp#1{`\tclose{#1}'\null} -\setfont\smallrm\rmshape{8}{1000} -\font\smallsy=cmsy9 -\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{% - \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% - \vbox{\hrule\kern-0.4pt - \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% - \kern-0.4pt\hrule}% - \kern-.06em\raise0.4pt\hbox{\angleright}}}} -% The old definition, with no lozenge: -%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} -\def\ctrl #1{{\tt \rawbackslash \hat}#1} -% @file, @option are the same as @samp. -\let\file=\samp -\let\option=\samp +% @samp. +\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} -% @code is a modification of @t, -% which makes spaces the same size as normal in the surrounding text. +% @indicateurl is \samp, that is, with quotes. +\let\indicateurl=\samp + +% @code (and similar) prints in typewriter, but with spaces the same +% size as normal in the surrounding text, without hyphenation, etc. +% This is a subroutine for that. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. @@ -1405,129 +2877,792 @@ where each line of input produces a line of output.} % Turn off hyphenation. \nohyphenation % - \rawbackslash - \frenchspacing + \plainfrenchspacing #1% }% - \null + \null % reset spacefactor to 1000 } -% We *must* turn on hyphenation at `-' and `_' in \code. +% We *must* turn on hyphenation at `-' and `_' in @code. +% (But see \codedashfinish below.) % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. - +% % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) -% and arrange explicitly to hyphenate at a dash. -% -- rms. +% and arrange explicitly to hyphenate at a dash. -- rms. { - \catcode`\-=\active - \catcode`\_=\active + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active + \global\let'=\rq \global\let`=\lq % default definitions % \global\def\code{\begingroup - \catcode`\-=\active \let-\codedash - \catcode`\_=\active \let_\codeunder + \setupmarkupstyle{code}% + % The following should really be moved into \setupmarkupstyle handlers. + \catcode\dashChar=\active \catcode\underChar=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\normaldash + \let_\realunder + \fi + % Given -foo (with a single dash), we do not want to allow a break + % after the hyphen. + \global\let\codedashprev=\codedash + % \codex } % - % If we end up with any active - characters when handling the index, - % just treat them as a normal -. - \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} + \gdef\codedash{\futurelet\next\codedashfinish} + \gdef\codedashfinish{% + \normaldash % always output the dash character itself. + % + % Now, output a discretionary to allow a line break, unless + % (a) the next character is a -, or + % (b) the preceding character is a -. + % E.g., given --posix, we do not want to allow a break after either -. + % Given --foo-bar, we do want to allow a break between the - and the b. + \ifx\next\codedash \else + \ifx\codedashprev\codedash + \else \discretionary{}{}{}\fi + \fi + % we need the space after the = for the case when \next itself is a + % space token; it would get swallowed otherwise. As in @code{- a}. + \global\let\codedashprev= \next + } } - -\def\realdash{-} -\def\codedash{-\discretionary{}{}{}} -\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} +\def\normaldash{-} +% \def\codex #1{\tclose{#1}\endgroup} -%\let\exp=\tclose %Was temporary +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is bad. +% @allowcodebreaks provides a document-level way to turn breaking at - +% and _ on and off. +% +\newif\ifallowcodebreaks \allowcodebreakstrue + +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse + \else + \errhelp = \EMsimple + \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}% + \fi\fi +} + +% For @command, @env, @file, @option quotes seem unnecessary, +% so use \code rather than \samp. +\let\command=\code +\let\env=\code +\let\file=\code +\let\option=\code + +% @uref (abbreviation for `urlref') aka @url takes an optional +% (comma-separated) second argument specifying the text to display and +% an optional third arg as text to display instead of (rather than in +% addition to) the url itself. First (mandatory) arg is the url. + +% TeX-only option to allow changing PDF output to show only the second +% arg (if given), and not the url (which is then just the link target). +\newif\ifurefurlonlylink + +% The main macro is \urefbreak, which allows breaking at expected +% places within the url. (There used to be another version, which +% didn't support automatic breaking.) +\def\urefbreak{\begingroup \urefcatcodes \dourefbreak} +\let\uref=\urefbreak +% +\def\dourefbreak#1{\urefbreakfinish #1,,,\finish} +\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% look for second arg + \ifdim\wd0 > 0pt + \ifpdf + % For pdfTeX and LuaTeX + \ifurefurlonlylink + % PDF plus option to not display url, show just arg + \unhbox0 + \else + % PDF, normally display both arg and url for consistency, + % visibility, if the pdf is eventually used to print, etc. + \unhbox0\ (\urefcode{#1})% + \fi + \else + \ifx\XeTeXrevision\thisisundefined + \unhbox0\ (\urefcode{#1})% DVI, always show arg and url + \else + % For XeTeX + \ifurefurlonlylink + % PDF plus option to not display url, show just arg + \unhbox0 + \else + % PDF, normally display both arg and url for consistency, + % visibility, if the pdf is eventually used to print, etc. + \unhbox0\ (\urefcode{#1})% + \fi + \fi + \fi + \else + \urefcode{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% Allow line breaks around only a few characters (only). +\def\urefcatcodes{% + \catcode`\&=\active \catcode`\.=\active + \catcode`\#=\active \catcode`\?=\active + \catcode`\/=\active +} +{ + \urefcatcodes + % + \global\def\urefcode{\begingroup + \setupmarkupstyle{code}% + \urefcatcodes + \let&\urefcodeamp + \let.\urefcodedot + \let#\urefcodehash + \let?\urefcodequest + \let/\urefcodeslash + \codex + } + % + % By default, they are just regular characters. + \global\def&{\normalamp} + \global\def.{\normaldot} + \global\def#{\normalhash} + \global\def?{\normalquest} + \global\def/{\normalslash} +} + +\def\urefcodeamp{\urefprebreak \&\urefpostbreak} +\def\urefcodedot{\urefprebreak .\urefpostbreak} +\def\urefcodehash{\urefprebreak \#\urefpostbreak} +\def\urefcodequest{\urefprebreak ?\urefpostbreak} +\def\urefcodeslash{\futurelet\next\urefcodeslashfinish} +{ + \catcode`\/=\active + \global\def\urefcodeslashfinish{% + \urefprebreak \slashChar + % Allow line break only after the final / in a sequence of + % slashes, to avoid line break between the slashes in http://. + \ifx\next/\else \urefpostbreak \fi + } +} + +% By default we'll break after the special characters, but some people like to +% break before the special chars, so allow that. Also allow no breaking at +% all, for manual control. +% +\parseargdef\urefbreakstyle{% + \def\txiarg{#1}% + \ifx\txiarg\wordnone + \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordbefore + \def\urefprebreak{\urefallowbreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordafter + \def\urefprebreak{\nobreak}\def\urefpostbreak{\urefallowbreak} + \else + \errhelp = \EMsimple + \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% + \fi\fi\fi +} +\def\wordafter{after} +\def\wordbefore{before} +\def\wordnone{none} + +% Allow a ragged right output to aid breaking long URL's. There can +% be a break at the \allowbreak with no extra glue (if the existing stretch in +% the line is sufficent), a break at the \penalty100 with extra glue added +% at the end of the line, or no break at all here. +% Changing the value of the penalty and/or the amount of stretch affects how +% preferrable one choice is over the other. +\def\urefallowbreak{% + \allowbreak + \hskip 0pt plus 2 em\relax + \penalty300 + \hskip 0pt plus -2 em\relax +} + +\urefbreakstyle after + +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdforxetex + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). -\def\kbdinputstyle{\parsearg\kbdinputstylexxx} -\def\kbdinputstylexxx#1{% - \def\arg{#1}% - \ifx\arg\worddistinct +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% - \else\ifx\arg\wordexample + \else\ifx\txiarg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% - \else\ifx\arg\wordcode + \else\ifx\txiarg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle setting `\txiarg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} -% Default is kbdinputdistinct. (Too much of a hassle to call the macro, -% the catcodes are wrong for parsearg to work.) -\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl} +% Default is `distinct'. +\kbdinputstyle distinct + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. +\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} \def\xkey{\key} -\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% -\ifx\one\xkey\ifx\threex\three \key{#2}% -\else{\tclose{\kbdfont\look}}\fi -\else{\tclose{\kbdfont\look}}\fi} - -% For @url, @env, @command quotes seem unnecessary, so use \code. -\let\url=\code -\let\env=\code -\let\command=\code - -% @uref (abbreviation for `urlref') takes an optional second argument -% specifying the text to display. First (mandatory) arg is the url. -% Perhaps eventually put in a hypertex \special here. -% -\def\uref#1{\urefxxx #1,,\finish} -\def\urefxxx#1,#2,#3\finish{% - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \unhbox0\ (\code{#1})% - \else - \code{#1}% - \fi +\def\kbdsub#1#2#3\par{% + \def\one{#1}\def\three{#3}\def\threex{??}% + \ifx\one\xkey\ifx\threex\three \key{#2}% + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi } -% rms does not like the angle brackets --karl, 17may97. -% So now @email is just like @uref. -%\def\email#1{\angleleft{\tt #1}\angleright} -\let\email=\uref +% definition of @key that produces a lozenge. Doesn't adjust to text size. +%\setfont\keyrm\rmshape{8}{1000}{OT1} +%\font\keysy=cmsy9 +%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% +% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% +% \vbox{\hrule\kern-0.4pt +% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% +% \kern-0.4pt\hrule}% +% \kern-.06em\raise0.4pt\hbox{\angleright}}}} -% Check if we are currently using a typewriter font. Since all the -% Computer Modern typewriter fonts have zero interword stretch (and -% shrink), and it is reasonable to expect all typewriter fonts to have -% this property, we can check that font parameter. +% definition of @key with no lozenge. If the current font is already +% monospace, don't change it; that way, we respect @kbdinputstyle. But +% if it isn't monospace, then use \tt. % -\def\ifmonospace{\ifdim\fontdimen3\font=0pt } +\def\key#1{{\setupmarkupstyle{key}% + \nohyphenation + \ifmonospace\else\tt\fi + #1}\null} + +% @clicksequence{File @click{} Open ...} +\def\clicksequence#1{\begingroup #1\endgroup} + +% @clickstyle @arrow (by default) +\parseargdef\clickstyle{\def\click{#1}} +\def\click{\arrow} % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} -\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\switchtolsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi + \null % reset \spacefactor=1000 +} -% @l was never documented to mean ``switch to the Lisp font'', -% and it is not used as such in any manual I can find. We need it for -% Polish suppressed-l. --karl, 22sep96. -%\def\l#1{{\li #1}\null} +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\plainfrenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi + \null % reset \spacefactor=1000 +} -% Explicit font changes: @r, @sc, undocumented @ii. -\def\r#1{{\rm #1}} % roman font -\def\sc#1{{\smallcaps#1}} % smallcaps font -\def\ii#1{{\it #1}} % italic font +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} -% @acronym downcases the argument and prints in smallcaps. -\def\acronym#1{{\smallcaps \lowercase{#1}}} +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a math (or tt) \. +% FYI, plain.tex uses \\ as a temporary control sequence (for no +% particular reason), but this is not advertised and we don't care. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \ifmmode\else % only go into math if not in math mode already + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + % make the texinfo accent commands work in math mode + \let\"=\ddot + \let\'=\acute + \let\==\bar + \let\^=\hat + \let\`=\grave + \let\u=\breve + \let\v=\check + \let\~=\tilde + \let\dotaccent=\dot + % have to provide another name for sup operator + \let\mathopsup=\sup + $\expandafter\finishmath\fi +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. -% @pounds{} is a sterling sign. +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \catcode`' = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + \let' = \ptexquoteright + } +} + +% for @sub and @sup, if in math mode, just do a normal sub/superscript. +% If in text, use math to place as sub/superscript, but switch +% into text mode, with smaller fonts. This is a different font than the +% one used for real math sub/superscripts (8pt vs. 7pt), but let's not +% fix it (significant additions to font machinery) until someone notices. +% +\def\sub{\ifmmode \expandafter\sb \else \expandafter\finishsub\fi} +\def\finishsub#1{$\sb{\hbox{\switchtolllsize #1}}$}% +% +\def\sup{\ifmmode \expandafter\ptexsp \else \expandafter\finishsup\fi} +\def\finishsup#1{$\ptexsp{\hbox{\switchtolllsize #1}}$}% + +% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. +% Ignore unless FMTNAME == tex; then it is like @iftex and @tex, +% except specified as a normal braced arg, so no newlines to worry about. +% +\def\outfmtnametex{tex} +% +\long\def\inlinefmt#1{\doinlinefmt #1,\finish} +\long\def\doinlinefmt#1,#2,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi +} +% +% @inlinefmtifelse{FMTNAME,THEN-TEXT,ELSE-TEXT} expands THEN-TEXT if +% FMTNAME is tex, else ELSE-TEXT. +\long\def\inlinefmtifelse#1{\doinlinefmtifelse #1,,,\finish} +\long\def\doinlinefmtifelse#1,#2,#3,#4,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\else \ignorespaces #3\fi +} +% +% For raw, must switch into @tex before parsing the argument, to avoid +% setting catcodes prematurely. Doing it this way means that, for +% example, @inlineraw{html, foo{bar} gets a parse error instead of being +% ignored. But this isn't important because if people want a literal +% *right* brace they would have to use a command anyway, so they may as +% well use a command to get a left brace too. We could re-use the +% delimiter character idea from \verb, but it seems like overkill. +% +\long\def\inlineraw{\tex \doinlineraw} +\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} +\def\doinlinerawtwo#1,#2,\finish{% + \def\inlinerawname{#1}% + \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi + \endgroup % close group opened by \tex. +} + +% @inlineifset{VAR, TEXT} expands TEXT if VAR is @set. +% +\long\def\inlineifset#1{\doinlineifset #1,\finish} +\long\def\doinlineifset#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax + \else\ignorespaces#2\fi +} + +% @inlineifclear{VAR, TEXT} expands TEXT if VAR is not @set. +% +\long\def\inlineifclear#1{\doinlineifclear #1,\finish} +\long\def\doinlineifclear#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax \ignorespaces#2\fi +} + + +\message{glyphs,} +% and logos. + +% @@ prints an @, as does @atchar{}. +\def\@{\char64 } +\let\atchar=\@ + +% @{ @} @lbracechar{} @rbracechar{} all generate brace characters. +\def\lbracechar{{\ifmonospace\char123\else\ensuremath\lbrace\fi}} +\def\rbracechar{{\ifmonospace\char125\else\ensuremath\rbrace\fi}} +\let\{=\lbracechar +\let\}=\rbracechar + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \ptexc +\let\dotaccent = \ptexdot +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \ptext +\let\ubaraccent = \ptexb +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi + \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{% + \ifx\textnominalsize\xwordpt + % for 10pt running text, lllsize (8pt) is too small for the A in LaTeX. + % Revert to plain's \scriptsize, which is 7pt. + \count255=\the\fam $\fam\count255 \scriptstyle A$% + \else + % For 11pt, we can use our lllsize. + \switchtolllsize A% + \fi + }% + \vss + }}% + \kern-.15em + \TeX +} + +% Some math mode symbols. Define \ensuremath to switch into math mode +% unless we are already there. Expansion tricks may not be needed here, +% but safer, and can't hurt. +\def\ensuremath{\ifmmode \expandafter\asis \else\expandafter\ensuredmath \fi} +\def\ensuredmath#1{$\relax#1$} +% +\def\bullet{\ensuremath\ptexbullet} +\def\geq{\ensuremath\ge} +\def\leq{\ensuremath\le} +\def\minus{\ensuremath-} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in the cm +% typewriter fonts as three actual period characters; on the other hand, +% in other typewriter fonts three periods are wider than 1.5em. So do +% whichever is larger. +% +\def\dots{% + \leavevmode + \setbox0=\hbox{...}% get width of three periods + \ifdim\wd0 > 1.5em + \dimen0 = \wd0 + \else + \dimen0 = 1.5em + \fi + \hbox to \dimen0{% + \hskip 0pt plus.25fil + .\hskip 0pt plus1fil + .\hskip 0pt plus1fil + .\hskip 0pt plus.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, they should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} +\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\ttfont \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% \def\pounds{{\it\$}} +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% Glyphs from the EC fonts. We don't use \let for the aliases, because +% sometimes we redefine the original macro, and the alias should reflect +% the redefinition. +% +% Use LaTeX names for the Icelandic letters. +\def\DH{{\ecfont \char"D0}} % Eth +\def\dh{{\ecfont \char"F0}} % eth +\def\TH{{\ecfont \char"DE}} % Thorn +\def\th{{\ecfont \char"FE}} % thorn +% +\def\guillemetleft{{\ecfont \char"13}} +\def\guillemotleft{\guillemetleft} +\def\guillemetright{{\ecfont \char"14}} +\def\guillemotright{\guillemetright} +\def\guilsinglleft{{\ecfont \char"0E}} +\def\guilsinglright{{\ecfont \char"0F}} +\def\quotedblbase{{\ecfont \char"12}} +\def\quotesinglbase{{\ecfont \char"0D}} +% +% This positioning is not perfect (see the ogonek LaTeX package), but +% we have the precomposed glyphs for the most common cases. We put the +% tests to use those glyphs in the single \ogonek macro so we have fewer +% dummy definitions to worry about for index entries, etc. +% +% ogonek is also used with other letters in Lithuanian (IOU), but using +% the precomposed glyphs for those is not so easy since they aren't in +% the same EC font. +\def\ogonek#1{{% + \def\temp{#1}% + \ifx\temp\macrocharA\Aogonek + \else\ifx\temp\macrochara\aogonek + \else\ifx\temp\macrocharE\Eogonek + \else\ifx\temp\macrochare\eogonek + \else + \ecfont \setbox0=\hbox{#1}% + \ifdim\ht0=1ex\accent"0C #1% + \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% + \fi + \fi\fi\fi\fi + }% +} +\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} +\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} +\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} +\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} +% +% Use the European Computer Modern fonts (cm-super in outline format) +% for non-CM glyphs. That is ec* for regular text and tc* for the text +% companion symbols (LaTeX TS1 encoding). Both are part of the ec +% package and follow the same conventions. +% +\def\ecfont{\etcfont{e}} +\def\tcfont{\etcfont{t}} +% +\def\etcfont#1{% + % We can't distinguish serif/sans and italic/slanted, but this + % is used for crude hacks anyway (like adding French and German + % quotes to documents typeset with CM, where we lose kerning), so + % hopefully nobody will notice/care. + \edef\ecsize{\csname\curfontsize ecsize\endcsname}% + \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% + \ifmonospace + % typewriter: + \font\thisecfont = #1ctt\ecsize \space at \nominalsize + \else + \ifx\curfontstyle\bfstylename + % bold: + \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize + \else + % regular: + \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \fi + \fi + \thisecfont +} + +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{\switchtolllsize R}% + \hfil\crcr\Orb}}% + }$% +} + +% @textdegree - the normal degrees sign. +% +\def\textdegree{$^\circ$} + +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\thisisundefined +\def\Orb{\mathhexbox20D} +\fi + +% Quotes. +\chardef\quotedblleft="5C +\chardef\quotedblright=`\" +\chardef\quoteleft=`\` +\chardef\quoteright=`\' + \message{page headings,} @@ -1538,93 +3673,112 @@ where each line of input produces a line of output.} \newif\ifseenauthor \newif\iffinishedtitlepage -% Do an implicit @contents or @shortcontents after @end titlepage if the -% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. -% -\newif\ifsetcontentsaftertitlepage - \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue -\newif\ifsetshortcontentsaftertitlepage - \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue +% @setcontentsaftertitlepage used to do an implicit @contents or +% @shortcontents after @end titlepage, but it is now obsolete. +\def\setcontentsaftertitlepage{% + \errmessage{@setcontentsaftertitlepage has been removed as a Texinfo + command; move your @contents command if you want the contents + after the title page.}}% +\def\setshortcontentsaftertitlepage{% + \errmessage{@setshortcontentsaftertitlepage has been removed as a Texinfo + command; move your @shortcontents and @contents commands if you + want the contents after the title page.}}% -\def\shorttitlepage{\parsearg\shorttitlepagezzz} -\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% - \endgroup\page\hbox{}\page} +\parseargdef\shorttitlepage{% + \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} -\def\titlepage{\begingroup \parindent=0pt \textfonts - \let\subtitlerm=\tenrm - \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% - % - \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% - % - % Leave some space at the very top of the page. - \vglue\titlepagetopglue - % - % Now you can print the title using @title. - \def\title{\parsearg\titlezzz}% - \def\titlezzz##1{\leftline{\titlefonts\rm ##1} - % print a rule at the page bottom also. - \finishedtitlepagefalse - \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% - % No rule at page bottom unless we print one at the top with @title. - \finishedtitlepagetrue - % - % Now you can put text using @subtitle. - \def\subtitle{\parsearg\subtitlezzz}% - \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% - % - % @author should come last, but may come many times. - \def\author{\parsearg\authorzzz}% - \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi - {\authorfont \leftline{##1}}}% - % - % Most title ``pages'' are actually two pages long, with space - % at the top of the second. We don't want the ragged left on the second. - \let\oldpage = \page - \def\page{% +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% \iffinishedtitlepage\else - \finishtitlepage + \finishtitlepage \fi - \oldpage \let\page = \oldpage - \hbox{}}% -% \def\page{\oldpage \hbox{}} + \page + \null + }% } \def\Etitlepage{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - % It is important to do the page break before ending the group, - % because the headline and footline are only empty inside the group. - % If we use the new definition of \page, we always get a blank page - % after the title page, which we certainly don't want. - \oldpage - \endgroup - % - % If they want short, they certainly want long too. - \ifsetshortcontentsaftertitlepage - \shortcontents - \contents - \global\let\shortcontents = \relax - \global\let\contents = \relax - \fi - % - \ifsetcontentsaftertitlepage - \contents - \global\let\contents = \relax - \global\let\shortcontents = \relax - \fi - % - \HEADINGSon + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon } \def\finishtitlepage{% - \vskip4pt \hrule height 2pt width \hsize - \vskip\titlepagebottomglue - \finishedtitlepagetrue + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue } -%%% Set up page headings and footings. +% Settings used for typesetting titles: no hyphenation, no indentation, +% don't worry much about spacing, ragged right. This should be used +% inside a \vbox, and fonts need to be set appropriately first. \par should +% be specified before the end of the \vbox, since a vbox is a group. +% +\def\raggedtitlesettings{% + \rm + \hyphenpenalty=10000 + \parindent=0pt + \tolerance=5000 + \ptexraggedright +} + +% Macros to be used within @titlepage: + +\let\subtitlerm=\rmfont +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\parseargdef\title{% + \checkenv\titlepage + \vbox{\titlefonts \raggedtitlesettings #1\par}% + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\secfonts\rm \leftline{#1}}% + \fi +} + + +% Set up page headings and footings. \let\thispage=\folio @@ -1633,7 +3787,7 @@ where each line of input produces a line of output.} \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages -% Now make Tex use those variables +% Now make \makeheadline and \makefootline in Plain TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline @@ -1647,43 +3801,68 @@ where each line of input produces a line of output.} % @evenfooting @thisfile|| % @oddfooting ||@thisfile + \def\evenheading{\parsearg\evenheadingxxx} -\def\oddheading{\parsearg\oddheadingxxx} -\def\everyheading{\parsearg\everyheadingxxx} - -\def\evenfooting{\parsearg\evenfootingxxx} -\def\oddfooting{\parsearg\oddfootingxxx} -\def\everyfooting{\parsearg\everyfootingxxx} - -{\catcode`\@=0 % - -\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} -\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} -\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} -\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} -\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% -\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} -\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} -\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} -\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. - \global\advance\pageheight by -\baselineskip - \global\advance\vsize by -\baselineskip + \global\advance\txipageheight by -12pt + \global\advance\vsize by -12pt } -\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + +% @evenheadingmarks top \thischapter <- chapter at the top of a page +% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page % -}% unbind the catcode of @. +% The same set of arguments for: +% +% @oddheadingmarks +% @evenfootingmarks +% @oddfootingmarks +% @everyheadingmarks +% @everyfootingmarks + +% These define \getoddheadingmarks, \getevenheadingmarks, +% \getoddfootingmarks, and \getevenfootingmarks, each to one of +% \gettopheadingmarks, \getbottomheadingmarks. +% +\def\evenheadingmarks{\headingmarks{even}{heading}} +\def\oddheadingmarks{\headingmarks{odd}{heading}} +\def\evenfootingmarks{\headingmarks{even}{footing}} +\def\oddfootingmarks{\headingmarks{odd}{footing}} +\parseargdef\everyheadingmarks{\headingmarks{even}{heading}{#1} + \headingmarks{odd}{heading}{#1} } +\parseargdef\everyfootingmarks{\headingmarks{even}{footing}{#1} + \headingmarks{odd}{footing}{#1} } +% #1 = even/odd, #2 = heading/footing, #3 = top/bottom. +\def\headingmarks#1#2#3 {% + \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname + \global\expandafter\let\csname get#1#2marks\endcsname \temp +} + +\everyheadingmarks bottom +\everyfootingmarks bottom % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. @@ -1695,35 +3874,39 @@ where each line of input produces a line of output.} % By default, they are off at the start of a document, % and turned `on' after @end titlepage. -\def\headings #1 {\csname HEADINGS#1\endcsname} +\parseargdef\headings{\csname HEADINGS#1\endcsname} + +\def\headingsoff{% non-global headings elimination + \evenheadline={\hfil}\evenfootline={\hfil}% + \oddheadline={\hfil}\oddfootline={\hfil}% +} + +\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting +\HEADINGSoff % it's the default -\def\HEADINGSoff{ -\global\evenheadline={\hfil} \global\evenfootline={\hfil} -\global\oddheadline={\hfil} \global\oddfootline={\hfil}} -\HEADINGSoff % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. -\def\HEADINGSdouble{ +\def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. -\def\HEADINGSsingle{ +\def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\evenheadline={\line{\thischapterheading\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} @@ -1734,7 +3917,7 @@ where each line of input produces a line of output.} \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } @@ -1742,35 +3925,34 @@ where each line of input produces a line of output.} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\evenheadline={\line{\thischapterheading\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings -% Produces Day Month Year style of output. -\def\today{\number\day\space -\ifcase\month\or -January\or February\or March\or April\or May\or June\or -July\or August\or September\or October\or November\or December\fi -\space\number\year} +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\thisisundefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi -% Use this if you want the Month Day, Year style of output. -%\def\today{\ifcase\month\or -%January\or February\or March\or April\or May\or June\or -%July\or August\or September\or October\or November\or December\fi -%\space\number\day, \number\year} - -% @settitle line... specifies the title of the document, for headings -% It generates no output of its own - -\def\thistitle{No Title} -\def\settitle{\parsearg\settitlezzz} -\def\settitlezzz #1{\gdef\thistitle{#1}} +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} -% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). +% Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in @@ -1782,7 +3964,7 @@ July\or August\or September\or October\or November\or December\fi % used internally for \itemindent minus \itemmargin \newdimen\itemmax -% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). @@ -1794,22 +3976,10 @@ July\or August\or September\or October\or November\or December\fi \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} -\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} -\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} - -\def\internalBkitem{\smallbreak \parsearg\kitemzzz} -\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} - -\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% - \itemzzz {#1}} - -\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% - \itemzzz {#1}} - \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent - \setbox0=\hbox{\itemfont{#1}}% + \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % @@ -1825,7 +3995,7 @@ July\or August\or September\or October\or November\or December\fi \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent - \advance\rightskip by0pt plus1fil + \advance\rightskip by0pt plus1fil\relax \leavevmode\unhbox0\par \endgroup % @@ -1833,15 +4003,19 @@ July\or August\or September\or October\or November\or December\fi % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % - % Stop a page break at the \parskip glue coming up. Unfortunately - % we can't prevent a possible page break at the following - % \baselineskip glue. - \nobreak + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted would + % cause the example and the item to crash together. So we use this + % bizarre value of 10001 as a signal to \aboveenvbreak to insert + % \parskip glue after all. Section titles are handled this way also. + % + \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the - % following text (if any) will end up on the same line. + % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and @@ -1855,97 +4029,121 @@ July\or August\or September\or October\or November\or December\fi \fi } -\def\item{\errmessage{@item while not in a table}} -\def\itemx{\errmessage{@itemx while not in a table}} -\def\kitem{\errmessage{@kitem while not in a table}} -\def\kitemx{\errmessage{@kitemx while not in a table}} -\def\xitem{\errmessage{@xitem while not in a table}} -\def\xitemx{\errmessage{@xitemx while not in a table}} - -% Contains a kludge to get @end[description] to work. -\def\description{\tablez{\dontindex}{1}{}{}{}{}} +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. -\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} -{\obeylines\obeyspaces% -\gdef\tablex #1^^M{% -\tabley\dontindex#1 \endtabley}} - -\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} -{\obeylines\obeyspaces% -\gdef\ftablex #1^^M{% -\tabley\fnitemindex#1 \endtabley -\def\Eftable{\endgraf\afterenvbreak\endgroup}% -\let\Etable=\relax}} - -\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} -{\obeylines\obeyspaces% -\gdef\vtablex #1^^M{% -\tabley\vritemindex#1 \endtabley -\def\Evtable{\endgraf\afterenvbreak\endgroup}% -\let\Etable=\relax}} - -\def\dontindex #1{} -\def\fnitemindex #1{\doind {fn}{\code{#1}}}% -\def\vritemindex #1{\doind {vr}{\code{#1}}}% - -{\obeyspaces % -\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% -\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} - -\def\tablez #1#2#3#4#5#6{% -\aboveenvbreak % -\begingroup % -\def\Edescription{\Etable}% Necessary kludge. -\let\itemindex=#1% -\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % -\ifnum 0#4>0 \tableindent=#4\mil \fi % -\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % -\def\itemfont{#2}% -\itemmax=\tableindent % -\advance \itemmax by -\itemmargin % -\advance \leftskip by \tableindent % -\exdentamount=\tableindent -\parindent = 0pt -\parskip = \smallskipamount -\ifdim \parskip=0pt \parskip=2pt \fi% -\def\Etable{\endgraf\afterenvbreak\endgroup}% -\let\item = \internalBitem % -\let\itemx = \internalBitemx % -\let\kitem = \internalBkitem % -\let\kitemx = \internalBkitemx % -\let\xitem = \internalBxitem % -\let\xitemx = \internalBxitemx % +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% } +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley +} +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno -\def\itemize{\parsearg\itemizezzz} +\envdef\itemize{\parsearg\doitemize} -\def\itemizezzz #1{% - \begingroup % ended by the @end itemize - \itemizey {#1}{\Eitemize} +\def\doitemize#1{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + % + % Try typesetting the item mark so that if the document erroneously says + % something like @itemize @samp (intending @table), there's an error + % right away at the @itemize. It's not the best error message in the + % world, but it's better than leaving it to the @item. This means if + % the user wants an empty mark, they have to say @w{} not just @w. + \def\itemcontents{#1}% + \setbox0 = \hbox{\itemcontents}% + % + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + % + \let\item=\itemizeitem } -\def\itemizey #1#2{% -\aboveenvbreak % -\itemmax=\itemindent % -\advance \itemmax by -\itemmargin % -\advance \leftskip by \itemindent % -\exdentamount=\itemindent -\parindent = 0pt % -\parskip = \smallskipamount % -\ifdim \parskip=0pt \parskip=2pt \fi% -\def#2{\endgraf\afterenvbreak\endgroup}% -\def\itemcontents{#1}% -\let\item=\itemizeitem} - -% Set sfcode to normal for the chars that usually have another value. -% These are `.?!:;,' -\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 - \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + % + \ifinner\else + \vadjust{\penalty 1200}% not good to break after first line of item. + \fi + % We can be in inner vertical mode in a footnote, although an + % @itemize looks awful there. + }% + \flushcr +} % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. @@ -1956,11 +4154,8 @@ July\or August\or September\or October\or November\or December\fi % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % -\def\enumerate{\parsearg\enumeratezzz} -\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% - \begingroup % ended by the @end enumerate - % % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi @@ -2031,13 +4226,13 @@ July\or August\or September\or October\or November\or December\fi }% } -% Call itemizey, adding a period to the first argument and supplying the +% Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 - \itemizey{#1.}\Eenumerate\flushcr + \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg @@ -2048,16 +4243,6 @@ July\or August\or September\or October\or November\or December\fi \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} -% Definition of @item while inside @itemize. - -\def\itemizeitem{% -\advance\itemno by 1 -{\let\par=\endgraf \smallbreak}% -\ifhmode \errmessage{In hmode at itemizeitem}\fi -{\parskip=0in \hskip 0pt -\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% -\vadjust{\penalty 1200}}% -\flushcr} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 @@ -2084,24 +4269,14 @@ July\or August\or September\or October\or November\or December\fi % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. -% -% For those who want to use more than one line's worth of words in -% the preamble, break the line within one argument and it -% will parse correctly, i.e., -% -% @multitable {Column 1 template} {Column 2 template} {Column 3 -% template} -% Not: -% @multitable {Column 1 template} {Column 2 template} -% {Column 3 template} % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. -% @item, @tab, @multitable or @end multitable do not need to be on their -% own lines, but it will not hurt if they are. +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. % Sample multitable: @@ -2138,20 +4313,19 @@ July\or August\or September\or October\or November\or December\fi \multitablelinespace=0pt % Macros used to set up halign preamble: -% +% \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent -% #1 is the part of the @columnfraction before the decimal point, which -% is presumably either 0 or the empty string (but we don't check, we -% just throw it away). #2 is the decimal part, which we use as the -% percent of \hsize for this column. -\def\pickupwholefraction#1.#2 {% +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% \global\advance\colcount by 1 - \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } @@ -2168,8 +4342,8 @@ July\or August\or September\or October\or November\or December\fi \let\go\pickupwholefraction \else \global\advance\colcount by 1 - \setbox0=\hbox{#1\unskip }% Add a normal word space as a separator; - % typically that is always in the input, anyway. + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi @@ -2184,17 +4358,44 @@ July\or August\or September\or October\or November\or December\fi \go } -% multitable syntax -\def\tab{&\hskip1sp\relax} % 2/2/96 - % tiny skip here makes sure this column space is - % maintained, even if it is never used. +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. Assignments +% have to be global since we are inside the implicit group of an +% alignment entry. \everycr below resets \everytab so we don't have to +% undo it ourselves. +\def\headitemfont{\b}% for people to use in the template row; not changeable +\def\headitem{% + \checkenv\multitable + \crcr + \gdef\headitemcrhook{\nobreak}% attempt to avoid page break after headings + \global\everytab={\bf}% can't use \headitemfont since the parsing differs + \the\everytab % for the first item +}% +% +% default for tables with no headings. +\let\headitemcrhook=\relax +% +% A \tab used to include \hskip1sp. But then the space in a template +% line is not enough. That is bad. So let's go back to just `&' until +% we again encounter the problem the 1sp was intended to solve. +% --karl, nathan@acm.org, 20apr99. +\def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % -\def\multitable{\parsearg\dotable} -\def\dotable#1{\bgroup +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% \vskip\parskip - \let\item\crcr + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % \tolerance=9500 \hbadness=9500 \setmultitablespacing @@ -2202,428 +4403,1059 @@ July\or August\or September\or October\or November\or December\fi \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 - \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}% % + \everycr = {% + \noalign{% + \global\everytab={}% Reset from possible headitem. + \global\colcount=0 % Reset the column counter. + % + % Check for saved footnotes, etc.: + \checkinserts + % + % Perhaps a \nobreak, then reset: + \headitemcrhook + \global\let\headitemcrhook=\relax + }% + }% + % + \parsearg\domultitable +} +\def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % - % \everycr will reset column counter, \colcount, at the end of - % each line. Every column entry will cause \colcount to advance by one. - % The table preamble - % looks at the current \colcount to find the correct column width. - \everycr{\noalign{% - % - % \filbreak%% keeps underfull box messages off when table breaks over pages. - % Maybe so, but it also creates really weird page breaks when the table - % breaks over pages. Wouldn't \vfil be better? Wait until the problem - % manifests itself, so it can be fixed for real --karl. - \global\colcount=0\relax}}% - % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. - \halign\bgroup&\global\advance\colcount by 1\relax - \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname - % - % In order to keep entries from bumping into each other - % we will add a \leftskip of \multitablecolspace to all columns after - % the first one. - % - % If a template has been used, we will add \multitablecolspace - % to the width of each template entry. - % - % If the user has set preamble in terms of percent of \hsize we will - % use that dimension as the width of the column, and the \leftskip - % will keep entries from bumping into each other. Table will start at - % left margin and final column will justify at right margin. - % - % Make sure we don't inherit \rightskip from the outer environment. - \rightskip=0pt - \ifnum\colcount=1 - % The first column will be indented with the surrounding text. - \advance\hsize by\leftskip - \else - \ifsetpercent \else - % If user has not set preamble in terms of percent of \hsize - % we will advance \hsize by \multitablecolspace. - \advance\hsize by \multitablecolspace - \fi - % In either case we will make \leftskip=\multitablecolspace: - \leftskip=\multitablecolspace - \fi - % Ignoring space at the beginning and end avoids an occasional spurious - % blank line, when TeX decides to break the line at the space before the - % box from the multistrut, so the strut ends up on a line by itself. - % For example: - % @multitable @columnfractions .11 .89 - % @item @code{#} - % @tab Legal holiday which is valid in major parts of the whole country. - % Is automatically provided with highlighting sequences respectively marking - % characters. - \noindent\ignorespaces##\unskip\multistrut}\cr + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively + % marking characters. + \noindent\ignorespaces##\unskip\multistrut + }\cr +} +\def\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse } -\def\setmultitablespacing{% test to see if user has set \multitablelinespace. -% If so, do nothing. If not, give it an appropriate dimension based on -% current baselineskip. +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \ifdim\multitablelinespace=0pt -%% strut to put in table in case some entry doesn't have descenders, -%% to keep lines equally spaced -\let\multistrut = \strut -%% Test to see if parskip is larger than space between lines of -%% table. If not, do nothing. -%% If so, set to same dimension as multitablelinespace. -\else -\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 -width0pt\relax} \fi +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +\fi +% Test to see if parskip is larger than space between lines of +% table. If not, do nothing. +% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. \fi} +\message{conditionals,} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} +\def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% Ignore text until a line `@end #1', keeping track of nested conditionals. +% +% A count to remember the depth of nesting. +\newcount\doignorecount + +\def\doignore#1{\begingroup + % Scan in ``verbatim'' mode: + \obeylines + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \spaceisspace + % + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. + % + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next +} + +% Finish off ignored text. +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} + + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. +% +\parseargdef\set{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% +} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} + +% @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} +{ + \catcode`\-=\active \catcode`\_=\active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... + \catcode`\-=\other \catcode`\_=\other + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\normaldash \let_\normalunderscore + } +} + +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% Like \expandablevalue, but completely expandable (the \message in the +% definition above operates at the execution level of TeX). Used when +% writing to auxiliary files, due to the expansion that \write does. +% If flag is undefined, pass through an unexpanded @value command: maybe it +% will be set by the time it is read back in. +% +% NB flag names containing - or _ may not work here. +\def\dummyvalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \string\value{#1}% + \else + \csname SET#1\endcsname + \fi +} + +% Used for @value's in index entries to form the sort key: expand the @value +% if possible, otherwise sort late. +\def\indexnofontsvalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + ZZZZZZZ% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +% To get the special treatment we need for `@end ifset,' we call +% \makecond and then redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next +} +\def\ifsetfail{\doignore{ifset}} + +% @ifclear VAR ... @end executes the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written +% without the @) is in fact defined. We can only feasibly check at the +% TeX level, so something like `mathcode' is going to considered +% defined even though it is not a Texinfo command. +% +\makecond{ifcommanddefined} +\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} +% +\def\doifcmddefined#1#2{{% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname #2\endcsname\relax + #1% If not defined, \let\next as above. + \fi + \expandafter + }\next +} +\def\ifcmddefinedfail{\doignore{ifcommanddefined}} + +% @ifcommandnotdefined CMD ... handled similar to @ifclear above. +\makecond{ifcommandnotdefined} +\def\ifcommandnotdefined{% + \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} +\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} + +% Set the `txicommandconditionals' variable, so documents have a way to +% test if the @ifcommand...defined conditionals are available. +\set txicommandconditionals + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment + +% @defininfoenclose. +\let\definfoenclose=\comment + + \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite -% except not \outer, so it can be used within \newindex. -{\catcode`\@=11 -\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} -% \newindex {foo} defines an index named foo. -% It automatically defines \fooindex such that -% \fooindex ...rest of line... puts an entry in the index foo. -% It also defines \fooindfile to be the number of the output channel for -% the file that accumulates this index. The file's extension is foo. +% \newindex {foo} defines an index named IX. +% It automatically defines \IXindex such that +% \IXindex ...rest of line... puts an entry in the index IX. +% It also defines \IXindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is IX. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 % Open the file - \fi + \expandafter\chardef\csname#1indfile\endcsname=0 \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} - +% \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. - +% +\def\defcodeindex{\parsearg\newcodeindex} +% \def\newcodeindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 - \fi + \expandafter\chardef\csname#1indfile\endcsname=0 \expandafter\xdef\csname#1index\endcsname{% - \noexpand\docodeindex{#1}} + \noexpand\docodeindex{#1}}% } -\def\defcodeindex{\parsearg\newcodeindex} +% The default indices: +\newindex{cp}% concepts, +\newcodeindex{fn}% functions, +\newcodeindex{vr}% variables, +\newcodeindex{tp}% types, +\newcodeindex{ky}% keys +\newcodeindex{pg}% and programs. + % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. -% The \closeout helps reduce unnecessary open files; the limit on the -% Acorn RISC OS is a mere 16 files. -\def\synindex#1 #2 {% - \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname - \expandafter\closeout\csname#1indfile\endcsname - \expandafter\let\csname#1indfile\endcsname=\synindexfoo - \expandafter\xdef\csname#1index\endcsname{% define \xxxindex - \noexpand\doindex{#2}}% -} - +% % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. -\def\syncodeindex#1 #2 {% - \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname - \expandafter\closeout\csname#1indfile\endcsname - \expandafter\let\csname#1indfile\endcsname=\synindexfoo - \expandafter\xdef\csname#1index\endcsname{% define \xxxindex - \noexpand\docodeindex{#2}}% +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + \requireopenindexfile{#3}% + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } -% Define \doindex, the driver for all \fooindex macros. +% Define \doindex, the driver for all index macros. % Argument #1 is generated by the calling \fooindex macro, -% and it is "foo", the name of the index. +% and it is the two-letter name of the index. -% \doindex just uses \parsearg; it calls \doind for the actual work. -% This is because \doind is more useful to call from other macros. - -% There is also \dosubind {index}{topic}{subtopic} -% which makes an entry in a two-level index such as the operation index. - -\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} -\def\singleindexer #1{\doind{\indexname}{#1}} +\def\doindex#1{\edef\indexname{#1}\parsearg\doindexxxx} +\def\doindexxxx #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. -\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} -\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} +\def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx} +\def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}} -\def\indexdummies{% -\def\ { }% -% Take care of the plain tex accent commands. -\def\"{\realbackslash "}% -\def\`{\realbackslash `}% -\def\'{\realbackslash '}% -\def\^{\realbackslash ^}% -\def\~{\realbackslash ~}% -\def\={\realbackslash =}% -\def\b{\realbackslash b}% -\def\c{\realbackslash c}% -\def\d{\realbackslash d}% -\def\u{\realbackslash u}% -\def\v{\realbackslash v}% -\def\H{\realbackslash H}% -% Take care of the plain tex special European modified letters. -\def\oe{\realbackslash oe}% -\def\ae{\realbackslash ae}% -\def\aa{\realbackslash aa}% -\def\OE{\realbackslash OE}% -\def\AE{\realbackslash AE}% -\def\AA{\realbackslash AA}% -\def\o{\realbackslash o}% -\def\O{\realbackslash O}% -\def\l{\realbackslash l}% -\def\L{\realbackslash L}% -\def\ss{\realbackslash ss}% -% Take care of texinfo commands likely to appear in an index entry. -% (Must be a way to avoid doing expansion at all, and thus not have to -% laboriously list every single command here.) -\def\@{@}% will be @@ when we switch to @ as escape char. -% Need these in case \tex is in effect and \{ is a \delimiter again. -% But can't use \lbracecmd and \rbracecmd because texindex assumes -% braces and backslashes are used only as delimiters. -\let\{ = \mylbrace -\let\} = \myrbrace -\def\_{{\realbackslash _}}% -\def\w{\realbackslash w }% -\def\bf{\realbackslash bf }% -%\def\rm{\realbackslash rm }% -\def\sl{\realbackslash sl }% -\def\sf{\realbackslash sf}% -\def\tt{\realbackslash tt}% -\def\gtr{\realbackslash gtr}% -\def\less{\realbackslash less}% -\def\hat{\realbackslash hat}% -\def\TeX{\realbackslash TeX}% -\def\dots{\realbackslash dots }% -\def\result{\realbackslash result}% -\def\equiv{\realbackslash equiv}% -\def\expansion{\realbackslash expansion}% -\def\print{\realbackslash print}% -\def\error{\realbackslash error}% -\def\point{\realbackslash point}% -\def\copyright{\realbackslash copyright}% -\def\tclose##1{\realbackslash tclose {##1}}% -\def\code##1{\realbackslash code {##1}}% -\def\uref##1{\realbackslash uref {##1}}% -\def\url##1{\realbackslash url {##1}}% -\def\env##1{\realbackslash env {##1}}% -\def\command##1{\realbackslash command {##1}}% -\def\option##1{\realbackslash option {##1}}% -\def\dotless##1{\realbackslash dotless {##1}}% -\def\samp##1{\realbackslash samp {##1}}% -\def\,##1{\realbackslash ,{##1}}% -\def\t##1{\realbackslash t {##1}}% -\def\r##1{\realbackslash r {##1}}% -\def\i##1{\realbackslash i {##1}}% -\def\b##1{\realbackslash b {##1}}% -\def\sc##1{\realbackslash sc {##1}}% -\def\cite##1{\realbackslash cite {##1}}% -\def\key##1{\realbackslash key {##1}}% -\def\file##1{\realbackslash file {##1}}% -\def\var##1{\realbackslash var {##1}}% -\def\kbd##1{\realbackslash kbd {##1}}% -\def\dfn##1{\realbackslash dfn {##1}}% -\def\emph##1{\realbackslash emph {##1}}% -\def\acronym##1{\realbackslash acronym {##1}}% + +% Used for the aux, toc and index files to prevent expansion of Texinfo +% commands. % -% Handle some cases of @value -- where the variable name does not -% contain - or _, and the value does not contain any -% (non-fully-expandable) commands. -\let\value = \expandablevalue -% -\unsepspaces +\def\atdummies{% + \definedummyletter\@% + \definedummyletter\ % + \definedummyletter\{% + \definedummyletter\}% + \definedummyletter\&% + % + % Do the redefinitions. + \definedummies + \otherbackslash } -% If an index command is used in an @example environment, any spaces -% therein should become regular spaces in the raw index file, not the -% expansion of \tie (\\leavevmode \penalty \@M \ ). -{\obeyspaces - \gdef\unsepspaces{\obeyspaces\let =\space}} +% \definedummyword defines \#1 as \string\#1\space, thus effectively +% preventing its expansion. This is used only for control words, +% not control letters, because the \space would be incorrect for +% control characters, but is needed to separate the control word +% from whatever follows. +% +% These can be used both for control words that take an argument and +% those that do not. If it is followed by {arg} in the input, then +% that will dutifully get written to the index (or wherever). +% +% For control letters, we have \definedummyletter, which omits the +% space. +% +\def\definedummyword #1{\def#1{\string#1\space}}% +\def\definedummyletter#1{\def#1{\string#1}}% +\let\definedummyaccent\definedummyletter -% \indexnofonts no-ops all font-change commands. -% This is used when outputting the strings to sort the index by. -\def\indexdummyfont#1{#1} -\def\indexdummytex{TeX} -\def\indexdummydots{...} +% Called from \atdummies to prevent the expansion of commands. +% +\def\definedummies{% + % + \let\commondummyword\definedummyword + \let\commondummyletter\definedummyletter + \let\commondummyaccent\definedummyaccent + \commondummiesnofonts + % + \definedummyletter\_% + \definedummyletter\-% + % + % Non-English letters. + \definedummyword\AA + \definedummyword\AE + \definedummyword\DH + \definedummyword\L + \definedummyword\O + \definedummyword\OE + \definedummyword\TH + \definedummyword\aa + \definedummyword\ae + \definedummyword\dh + \definedummyword\exclamdown + \definedummyword\l + \definedummyword\o + \definedummyword\oe + \definedummyword\ordf + \definedummyword\ordm + \definedummyword\questiondown + \definedummyword\ss + \definedummyword\th + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt + % + \definedummyword\LaTeX + \definedummyword\TeX + % + % Assorted special characters. + \definedummyword\ampchar + \definedummyword\atchar + \definedummyword\arrow + \definedummyword\backslashchar + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\entrybreak + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\expansion + \definedummyword\geq + \definedummyword\guillemetleft + \definedummyword\guillemetright + \definedummyword\guilsinglleft + \definedummyword\guilsinglright + \definedummyword\lbracechar + \definedummyword\leq + \definedummyword\mathopsup + \definedummyword\minus + \definedummyword\ogonek + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\quotedblbase + \definedummyword\quotedblleft + \definedummyword\quotedblright + \definedummyword\quoteleft + \definedummyword\quoteright + \definedummyword\quotesinglbase + \definedummyword\rbracechar + \definedummyword\result + \definedummyword\sub + \definedummyword\sup + \definedummyword\textdegree + % + \definedummyword\subentry + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + \let\value\dummyvalue + % + \normalturnoffactive +} +% \commondummiesnofonts: common to \definedummies and \indexnofonts. +% Define \commondummyletter, \commondummyaccent and \commondummyword before +% using. Used for accents, font commands, and various control letters. +% +\def\commondummiesnofonts{% + % Control letters and accents. + \commondummyletter\!% + \commondummyaccent\"% + \commondummyaccent\'% + \commondummyletter\*% + \commondummyaccent\,% + \commondummyletter\.% + \commondummyletter\/% + \commondummyletter\:% + \commondummyaccent\=% + \commondummyletter\?% + \commondummyaccent\^% + \commondummyaccent\`% + \commondummyaccent\~% + \commondummyword\u + \commondummyword\v + \commondummyword\H + \commondummyword\dotaccent + \commondummyword\ogonek + \commondummyword\ringaccent + \commondummyword\tieaccent + \commondummyword\ubaraccent + \commondummyword\udotaccent + \commondummyword\dotless + % + % Texinfo font commands. + \commondummyword\b + \commondummyword\i + \commondummyword\r + \commondummyword\sansserif + \commondummyword\sc + \commondummyword\slanted + \commondummyword\t + % + % Commands that take arguments. + \commondummyword\abbr + \commondummyword\acronym + \commondummyword\anchor + \commondummyword\cite + \commondummyword\code + \commondummyword\command + \commondummyword\dfn + \commondummyword\dmn + \commondummyword\email + \commondummyword\emph + \commondummyword\env + \commondummyword\file + \commondummyword\image + \commondummyword\indicateurl + \commondummyword\inforef + \commondummyword\kbd + \commondummyword\key + \commondummyword\math + \commondummyword\option + \commondummyword\pxref + \commondummyword\ref + \commondummyword\samp + \commondummyword\strong + \commondummyword\tie + \commondummyword\U + \commondummyword\uref + \commondummyword\url + \commondummyword\var + \commondummyword\verb + \commondummyword\w + \commondummyword\xref +} + +\let\indexlbrace\relax +\let\indexrbrace\relax +\let\indexatchar\relax +\let\indexbackslash\relax + +{\catcode`\@=0 +\catcode`\\=13 + @gdef@backslashdisappear{@def\{}} +} + +{ +\catcode`\<=13 +\catcode`\-=13 +\catcode`\`=13 + \gdef\indexnonalnumdisappear{% + \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax\else + % @set txiindexlquoteignore makes us ignore left quotes in the sort term. + % (Introduced for FSFS 2nd ed.) + \let`=\empty + \fi + % + \expandafter\ifx\csname SETtxiindexbackslashignore\endcsname\relax\else + \backslashdisappear + \fi + % + \expandafter\ifx\csname SETtxiindexhyphenignore\endcsname\relax\else + \def-{}% + \fi + \expandafter\ifx\csname SETtxiindexlessthanignore\endcsname\relax\else + \def<{}% + \fi + \expandafter\ifx\csname SETtxiindexatsignignore\endcsname\relax\else + \def\@{}% + \fi + } + + \gdef\indexnonalnumreappear{% + \let-\normaldash + \let<\normalless + } +} + + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% \def\indexnofonts{% -% Just ignore accents. -\let\,=\indexdummyfont -\let\"=\indexdummyfont -\let\`=\indexdummyfont -\let\'=\indexdummyfont -\let\^=\indexdummyfont -\let\~=\indexdummyfont -\let\==\indexdummyfont -\let\b=\indexdummyfont -\let\c=\indexdummyfont -\let\d=\indexdummyfont -\let\u=\indexdummyfont -\let\v=\indexdummyfont -\let\H=\indexdummyfont -\let\dotless=\indexdummyfont -% Take care of the plain tex special European modified letters. -\def\oe{oe}% -\def\ae{ae}% -\def\aa{aa}% -\def\OE{OE}% -\def\AE{AE}% -\def\AA{AA}% -\def\o{o}% -\def\O{O}% -\def\l{l}% -\def\L{L}% -\def\ss{ss}% -\let\w=\indexdummyfont -\let\t=\indexdummyfont -\let\r=\indexdummyfont -\let\i=\indexdummyfont -\let\b=\indexdummyfont -\let\emph=\indexdummyfont -\let\strong=\indexdummyfont -\let\cite=\indexdummyfont -\let\sc=\indexdummyfont -%Don't no-op \tt, since it isn't a user-level command -% and is used in the definitions of the active chars like <, >, |... -%\let\tt=\indexdummyfont -\let\tclose=\indexdummyfont -\let\code=\indexdummyfont -\let\url=\indexdummyfont -\let\uref=\indexdummyfont -\let\env=\indexdummyfont -\let\command=\indexdummyfont -\let\option=\indexdummyfont -\let\file=\indexdummyfont -\let\samp=\indexdummyfont -\let\kbd=\indexdummyfont -\let\key=\indexdummyfont -\let\var=\indexdummyfont -\let\TeX=\indexdummytex -\let\dots=\indexdummydots -\def\@{@}% + % Accent commands should become @asis. + \def\commondummyaccent##1{\let##1\asis}% + % We can just ignore other control letters. + \def\commondummyletter##1{\let##1\empty}% + % All control words become @asis by default; overrides below. + \let\commondummyword\commondummyaccent + \commondummiesnofonts + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + \def\ { }% + \def\@{@}% + \def\_{\normalunderscore}% + \def\-{}% @- shouldn't affect sorting + % + \uccode`\1=`\{ \uppercase{\def\{{1}}% + \uccode`\1=`\} \uppercase{\def\}{1}}% + \let\lbracechar\{% + \let\rbracechar\}% + % + % Non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\DH{DZZ}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\TH{TH}% + \def\aa{aa}% + \def\ae{ae}% + \def\dh{dzz}% + \def\exclamdown{!}% + \def\l{l}% + \def\oe{oe}% + \def\ordf{a}% + \def\ordm{o}% + \def\o{o}% + \def\questiondown{?}% + \def\ss{ss}% + \def\th{th}% + % + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. \defglyph gives the control sequence a + % definition that removes the {} that follows its use. + \defglyph\atchar{@}% + \defglyph\arrow{->}% + \defglyph\bullet{bullet}% + \defglyph\comma{,}% + \defglyph\copyright{copyright}% + \defglyph\dots{...}% + \defglyph\enddots{...}% + \defglyph\equiv{==}% + \defglyph\error{error}% + \defglyph\euro{euro}% + \defglyph\expansion{==>}% + \defglyph\geq{>=}% + \defglyph\guillemetleft{<<}% + \defglyph\guillemetright{>>}% + \defglyph\guilsinglleft{<}% + \defglyph\guilsinglright{>}% + \defglyph\leq{<=}% + \defglyph\lbracechar{\{}% + \defglyph\minus{-}% + \defglyph\point{.}% + \defglyph\pounds{pounds}% + \defglyph\print{-|}% + \defglyph\quotedblbase{"}% + \defglyph\quotedblleft{"}% + \defglyph\quotedblright{"}% + \defglyph\quoteleft{`}% + \defglyph\quoteright{'}% + \defglyph\quotesinglbase{,}% + \defglyph\rbracechar{\}}% + \defglyph\registeredsymbol{R}% + \defglyph\result{=>}% + \defglyph\textdegree{o}% + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist + \let\value\indexnofontsvalue } +\def\defglyph#1#2{\def#1##1{#2}} % see above -% To define \realbackslash, we must make \ not be an escape. -% We must first make another character (@) an escape -% so we do not become unable to do a definition. -{\catcode`\@=0 \catcode`\\=\other - @gdef@realbackslash{\}} -\let\indexbackslash=0 %overridden during \printindex. -\let\SETmarginindex=\relax % put index entries in margin (undocumented)? -% For \ifx comparisons. -\def\emptymacro{\empty} - -% Most index entries go through here, but \dosubind is the general case. -% -\def\doind#1#2{\dosubind{#1}{#2}\empty} - -% Workhorse for all \fooindexes. -% #1 is name of index, #2 is stuff to put there, #3 is subentry -- -% \empty if called from \doind, as we usually are. The main exception -% is with defuns, which call us directly. -% -\def\dosubind#1#2#3{% - % Put the index entry in the margin if desired. - \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% - \fi +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{% + \iflinks {% - \count255=\lastpenalty - {% - \indexdummies % Must do this here, since \bf, etc expand at this stage - \escapechar=`\\ - {% - \let\folio = 0% We will expand all macros now EXCEPT \folio. - \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now - % so it will be output as is; and it will print as backslash. - % - \def\thirdarg{#3}% - % - % If third arg is present, precede it with space in sort key. - \ifx\thirdarg\emptymacro - \let\subentry = \empty - \else - \def\subentry{ #3}% - \fi - % - % First process the index-string with all font commands turned off - % to get the string to sort by. - {\indexnofonts \xdef\indexsorttmp{#2\subentry}}% - % - % Now produce the complete index entry, with both the sort key and the - % original text, including any font commands. - \toks0 = {#2}% - \edef\temp{% - \write\csname#1indfile\endcsname{% - \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% - }% - % - % If third (subentry) arg is present, add it to the index string. - \ifx\thirdarg\emptymacro \else - \toks0 = {#3}% - \edef\temp{\temp{\the\toks0}}% - \fi - % - % If a skip is the last thing on the list now, preserve it - % by backing up by \lastskip, doing the \write, then inserting - % the skip again. Otherwise, the whatsit generated by the - % \write will make \lastskip zero. The result is that sequences - % like this: - % @end defun - % @tindex whatever - % @defun ... - % will have extra space inserted, because the \medbreak in the - % start of the @defun won't see the skip inserted by the @end of - % the previous defun. - % - % But don't do any of this if we're not in vertical mode. We - % don't want to do a \vskip and prematurely end a paragraph. - % - % Avoid page breaks due to these extra skips, too. - % - \iflinks - \ifvmode - \skip0 = \lastskip - \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi - \fi - % - \temp % do the write - % - % - \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi - \fi - }% - }% - \penalty\count255 + % + \requireopenindexfile{#1}% + \edef\writeto{\csname#1indfile\endcsname}% + % + \def\indextext{#2}% + \safewhatsit\doindwrite }% + \fi } +% Check if an index file has been opened, and if not, open it. +\def\requireopenindexfile#1{% +\ifnum\csname #1indfile\endcsname=0 + \expandafter\newwrite \csname#1indfile\endcsname + \edef\suffix{#1}% + % A .fls suffix would conflict with the file extension for the output + % of -recorder, so use .f1s instead. + \ifx\suffix\indexisfl\def\suffix{f1}\fi + % Open the file + \immediate\openout\csname#1indfile\endcsname \jobname.\suffix + % Using \immediate above here prevents an object entering into the current + % box, which could confound checks such as those in \safewhatsit for + % preceding skips. + \typeout{Writing index file \jobname.\suffix}% +\fi} +\def\indexisfl{fl} + +% Definition for writing index entry sort key. +{ +\catcode`\-=13 +\gdef\indexwritesortas{% + \begingroup + \indexnonalnumreappear + \indexwritesortasxxx} +\gdef\indexwritesortasxxx#1{% + \xdef\indexsortkey{#1}\endgroup} +} + +\def\indexwriteseealso#1{ + \gdef\pagenumbertext{\string\seealso{#1}}% +} +\def\indexwriteseeentry#1{ + \gdef\pagenumbertext{\string\seeentry{#1}}% +} + +% The default definitions +\def\sortas#1{}% +\def\seealso#1{\i{\putwordSeeAlso}\ #1}% for sorted index file only +\def\putwordSeeAlso{See also} +\def\seeentry#1{\i{\putwordSee}\ #1}% for sorted index file only + + +% Given index entry text like "aaa @subentry bbb @sortas{ZZZ}": +% * Set \bracedtext to "{aaa}{bbb}" +% * Set \fullindexsortkey to "aaa @subentry ZZZ" +% * If @seealso occurs, set \pagenumbertext +% +\def\splitindexentry#1{% + \gdef\fullindexsortkey{}% + \xdef\bracedtext{}% + \def\sep{}% + \def\seealso##1{}% + \def\seeentry##1{}% + \expandafter\doindexsegment#1\subentry\finish\subentry +} + +% append the results from the next segment +\def\doindexsegment#1\subentry{% + \def\segment{#1}% + \ifx\segment\isfinish + \else + % + % Fully expand the segment, throwing away any @sortas directives, and + % trim spaces. + \edef\trimmed{\segment}% + \edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% + % + \xdef\bracedtext{\bracedtext{\trimmed}}% + % + % Get the string to sort by. Process the segment with all + % font commands turned off. + \bgroup + \let\sortas\indexwritesortas + \let\seealso\indexwriteseealso + \let\seeentry\indexwriteseeentry + \indexnofonts + % The braces around the commands are recognized by texindex. + \def\lbracechar{{\string\indexlbrace}}% + \def\rbracechar{{\string\indexrbrace}}% + \let\{=\lbracechar + \let\}=\rbracechar + \def\@{{\string\indexatchar}}% + \def\atchar##1{\@}% + \def\backslashchar{{\string\indexbackslash}}% + \uccode`\~=`\\ \uppercase{\let~\backslashchar}% + % + \let\indexsortkey\empty + \global\let\pagenumbertext\empty + % Execute the segment and throw away the typeset output. This executes + % any @sortas or @seealso commands in this segment. + \setbox\dummybox = \hbox{\segment}% + \ifx\indexsortkey\empty{% + \indexnonalnumdisappear + \xdef\trimmed{\segment}% + \xdef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% + \xdef\indexsortkey{\trimmed}% + \ifx\indexsortkey\empty\xdef\indexsortkey{ }\fi + }\fi + % + % Append to \fullindexsortkey. + \edef\tmp{\gdef\noexpand\fullindexsortkey{% + \fullindexsortkey\sep\indexsortkey}}% + \tmp + \egroup + \def\sep{\subentry}% + % + \expandafter\doindexsegment + \fi +} +\def\isfinish{\finish}% +\newbox\dummybox % used above + +\let\subentry\relax + +% Use \ instead of @ in index files. To support old texi2dvi and texindex. +% This works without changing the escape character used in the toc or aux +% files because the index entries are fully expanded here, and \string uses +% the current value of \escapechar. +\def\escapeisbackslash{\escapechar=`\\} + +% Use \ in index files by default. texi2dvi didn't support @ as the escape +% character (as it checked for "\entry" in the files, and not "@entry"). When +% the new version of texi2dvi has had a chance to become more prevalent, then +% the escape character can change back to @ again. This should be an easy +% change to make now because both @ and \ are only used as escape characters in +% index files, never standing for themselves. +% +\set txiindexescapeisbackslash + +% Write the entry in \indextext to the index file. +% +\def\doindwrite{% + \maybemarginindex + % + \atdummies + % + \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax\else + \escapeisbackslash + \fi + % + % For texindex which always views { and } as separators. + \def\{{\lbracechar{}}% + \def\}{\rbracechar{}}% + \uccode`\~=`\\ \uppercase{\def~{\backslashchar{}}}% + % + % Split the entry into primary entry and any subentries, and get the index + % sort key. + \splitindexentry\indextext + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + % + \edef\temp{% + \write\writeto{% + \string\entry{\fullindexsortkey}% + {\ifx\pagenumbertext\empty\noexpand\folio\else\pagenumbertext\fi}% + \bracedtext}% + }% + \temp +} + +% Put the index entry in the margin if desired (undocumented). +\def\maybemarginindex{% + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \relax\indextext}}% + \fi +} +\let\SETmarginindex=\relax + + +% Take care of unwanted page breaks/skips around a whatsit: +% +% If a skip is the last thing on the list now, preserve it +% by backing up by \lastskip, doing the \write, then inserting +% the skip again. Otherwise, the whatsit generated by the +% \write or \pdfdest will make \lastskip zero. The result is that +% sequences like this: +% @end defun +% @tindex whatever +% @defun ... +% will have extra space inserted, because the \medbreak in the +% start of the @defun won't see the skip inserted by the @end of +% the previous defun. +% +% But don't do any of this if we're not in vertical mode. We +% don't want to do a \vskip and prematurely end a paragraph. +% +% Avoid page breaks due to these extra skips, too. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +\newskip\whatsitskip +\newcount\whatsitpenalty +% +% ..., ready, GO: +% +\def\safewhatsit#1{\ifhmode + #1% + \else + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \whatsitskip = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \whatsitpenalty = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\whatsitskip glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\whatsitskip + \fi + % + #1% + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\whatsitskip + \fi +\fi} + % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or @@ -2635,9 +5467,14 @@ width0pt\relax} \fi % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} +% \entry {topic}{} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. +% \secondary {subtopic}{} +% for a subtopic with sub-subtopics +% \tertiary {subtopic}{subsubtopic}{pagelist} +% for each sub-subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. @@ -2649,193 +5486,332 @@ width0pt\relax} \fi \def\tindex {\tpindex} \def\pindex {\pgindex} -\def\cindexsub {\begingroup\obeylines\cindexsub} -{\obeylines % -\gdef\cindexsub "#1" #2^^M{\endgroup % -\dosubind{cp}{#2}{#1}}} - % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % -\def\printindex{\parsearg\doprintindex} -\def\doprintindex#1{\begingroup +\parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % - \indexfonts \rm + \smallfonts \rm \tolerance = 9500 - \indexbreaks + \plainfrenchspacing + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + % + % See comment in \requireopenindexfile. + \def\indexname{#1}\ifx\indexname\indexisfl\def\indexname{f1}\fi % % See if the index file exists and is nonempty. - % Change catcode of @ here so that if the index file contains - % \initial {@} - % as its first line, TeX doesn't complain about mismatched braces - % (because it thinks @} is a control sequence). - \catcode`\@ = 11 - \openin 1 \jobname.#1s + \openin 1 \jobname.\indexname s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. - (Index is nonexistent) + \putwordIndexNonexistent + \typeout{No file \jobname.\indexname s.}% \else - % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. - \read 1 to \temp + \read 1 to \thisline \ifeof 1 - (Index is empty) + \putwordIndexIsEmpty \else - % Index files are almost Texinfo source, but we use \ as the escape - % character. It would be better to use @, but that's too big a change - % to make right now. - \def\indexbackslash{\rawbackslashxx}% - \catcode`\\ = 0 - \escapechar = `\\ - \begindoublecolumns - \input \jobname.#1s - \enddoublecolumns + \expandafter\printindexzz\thisline\relax\relax\finish% \fi \fi \closein 1 \endgroup} +% If the index file starts with a backslash, forgo reading the index +% file altogether. If somebody upgrades texinfo.tex they may still have +% old index files using \ as the escape character. Reading this would +% at best lead to typesetting garbage, at worst a TeX syntax error. +\def\printindexzz#1#2\finish{% + \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax + \uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1 + \expandafter\ifx\csname SETtxiskipindexfileswithbackslash\endcsname\relax +\errmessage{% +ERROR: A sorted index file in an obsolete format was skipped. +To fix this problem, please upgrade your version of 'texi2dvi' +or 'texi2pdf' to that at . +If you are using an old version of 'texindex' (part of the Texinfo +distribution), you may also need to upgrade to a newer version (at least 6.0). +You may be able to typeset the index if you run +'texindex \jobname.\indexname' yourself. +You could also try setting the 'txiindexescapeisbackslash' flag by +running a command like +'texi2dvi -t "@set txiindexescapeisbackslash" \jobname.texi'. If you do +this, Texinfo will try to use index files in the old format. +If you continue to have problems, deleting the index files and starting again +might help (with 'rm \jobname.?? \jobname.??s')% +}% + \else + (Skipped sorted index file in obsolete format) + \fi + \else + \begindoublecolumns + \input \jobname.\indexname s + \enddoublecolumns + \fi + \else + \begindoublecolumns + \catcode`\\=0\relax + \catcode`\@=12\relax + \input \jobname.\indexname s + \enddoublecolumns + \fi +} + % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. -\def\initial#1{{% - % Some minor font changes for the special characters. - \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +{\catcode`\/=13 \catcode`\-=13 \catcode`\^=13 \catcode`\~=13 \catcode`\_=13 +\catcode`\|=13 \catcode`\<=13 \catcode`\>=13 \catcode`\+=13 \catcode`\"=13 +\catcode`\$=3 +\gdef\initialglyphs{% + % special control sequences used in the index sort key + \let\indexlbrace\{% + \let\indexrbrace\}% + \let\indexatchar\@% + \def\indexbackslash{\math{\backslash}}% % + % Some changes for non-alphabetic characters. Using the glyphs from the + % math fonts looks more consistent than the typewriter font used elsewhere + % for these characters. + \uccode`\~=`\\ \uppercase{\def~{\math{\backslash}}} + % + % In case @\ is used for backslash + \uppercase{\let\\=~} + % Can't get bold backslash so don't use bold forward slash + \catcode`\/=13 + \def/{{\secrmnotbold \normalslash}}% + \def-{{\normaldash\normaldash}}% en dash `--' + \def^{{\chapbf \normalcaret}}% + \def~{{\chapbf \normaltilde}}% + \def\_{% + \leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }% + \def|{$\vert$}% + \def<{$\less$}% + \def>{$\gtr$}% + \def+{$\normalplus$}% +}} + +\def\initial{% + \bgroup + \initialglyphs + \initialx +} + +\def\initialx#1{% % Remove any glue we may have, we'll be inserting our own. \removelastskip - % + % % We like breaks before the index initials, so insert a bonus. + % The glue before the bonus allows a little bit of space at the + % bottom of a column to reduce an increase in inter-line spacing. + \nobreak + \vskip 0pt plus 5\baselineskip \penalty -300 + \vskip 0pt plus -5\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. - % - % No shrink because it confuses \balancecolumns. - \vskip 1.67\baselineskip plus .5\baselineskip - \leftline{\secbf #1}% - \vskip .33\baselineskip plus .1\baselineskip % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus 1\baselineskip + \leftline{\secfonts \kern-0.05em \secbf #1}% + % \secfonts is inside the argument of \leftline so that the change of + % \baselineskip will not affect any glue inserted before the vbox that + % \leftline creates. % Do our best not to break after the initial. \nobreak + \vskip .33\baselineskip plus .1\baselineskip + \egroup % \initialglyphs +} + +\newdimen\entryrightmargin +\entryrightmargin=0pt + +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +\def\entry{% + \begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % No extra space above this paragraph. + \parskip = 0in + % + % When reading the text of entry, convert explicit line breaks + % from @* into spaces. The user might give these in long section + % titles, for instance. + \def\*{\unskip\space\ignorespaces}% + \def\entrybreak{\hfil\break}% An undocumented command + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\entrybreak{\unskip\space\ignorespaces}% +\def\doentry{% + % Save the text of the entry + \global\setbox\boxA=\hbox\bgroup + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. + % Not absorbing as a macro argument reduces the chance of problems + % with catcodes occurring. +} +{\catcode`\@=11 +\gdef\finishentry#1{% + \egroup % end box A + \dimen@ = \wd\boxA % Length of text of entry + \global\setbox\boxA=\hbox\bgroup + \unhbox\boxA + % #1 is the page number. + % + % Get the width of the page numbers, and only use + % leaders if they are present. + \global\setbox\boxB = \hbox{#1}% + \ifdim\wd\boxB = 0pt + \null\nobreak\hfill\ % + \else + % + \null\nobreak\indexdotfill % Have leaders before the page number. + % + \ifpdforxetex + \pdfgettoks#1.% + \hskip\skip\thinshrinkable\the\toksA + \else + \hskip\skip\thinshrinkable #1% + \fi + \fi + \egroup % end \boxA + \ifdim\wd\boxB = 0pt + \noindent\unhbox\boxA\par + \nobreak + \else\bgroup + % We want the text of the entries to be aligned to the left, and the + % page numbers to be aligned to the right. + % + \parindent = 0pt + \advance\leftskip by 0pt plus 1fil + \advance\leftskip by 0pt plus -1fill + \rightskip = 0pt plus -1fil + \advance\rightskip by 0pt plus 1fill + % Cause last line, which could consist of page numbers on their own + % if the list of page numbers is long, to be aligned to the right. + \parfillskip=0pt plus -1fill + % + \advance\rightskip by \entryrightmargin + % Determine how far we can stretch into the margin. + % This allows, e.g., "Appendix H GNU Free Documentation License" to + % fit on one line in @letterpaper format. + \ifdim\entryrightmargin>2.1em + \dimen@i=2.1em + \else + \dimen@i=0em + \fi + \advance \parfillskip by 0pt minus 1\dimen@i + % + \dimen@ii = \hsize + \advance\dimen@ii by -1\leftskip + \advance\dimen@ii by -1\entryrightmargin + \advance\dimen@ii by 1\dimen@i + \ifdim\wd\boxA > \dimen@ii % If the entry doesn't fit in one line + \ifdim\dimen@ > 0.8\dimen@ii % due to long index text + % Try to split the text roughly evenly. \dimen@ will be the length of + % the first line. + \dimen@ = 0.7\dimen@ + \dimen@ii = \hsize + \ifnum\dimen@>\dimen@ii + % If the entry is too long (for example, if it needs more than + % two lines), use all the space in the first line. + \dimen@ = \dimen@ii + \fi + \advance\leftskip by 0pt plus 1fill % ragged right + \advance \dimen@ by 1\rightskip + \parshape = 2 0pt \dimen@ 0em \dimen@ii + % Ideally we'd add a finite glue at the end of the first line only, + % instead of using \parshape with explicit line lengths, but TeX + % doesn't seem to provide a way to do such a thing. + % + % Indent all lines but the first one. + \advance\leftskip by 1em + \advance\parindent by -1em + \fi\fi + \indent % start paragraph + \unhbox\boxA + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % Word spacing - no stretch + \spaceskip=\fontdimen2\font minus \fontdimen4\font + % + \linepenalty=1000 % Discourage line breaks. + \hyphenpenalty=5000 % Discourage hyphenation. + % + \par % format the paragraph + \egroup % The \vbox + \fi + \endgroup }} -% This typesets a paragraph consisting of #1, dot leaders, and then #2 -% flush to the right margin. It is used for index and table of contents -% entries. The paragraph is indented by \leftskip. -% -\def\entry#1#2{\begingroup - % - % Start a new paragraph if necessary, so our assignments below can't - % affect previous text. - \par - % - % Do not fill out the last line with white space. - \parfillskip = 0in - % - % No extra space above this paragraph. - \parskip = 0in - % - % Do not prefer a separate line ending with a hyphen to fewer lines. - \finalhyphendemerits = 0 - % - % \hangindent is only relevant when the entry text and page number - % don't both fit on one line. In that case, bob suggests starting the - % dots pretty far over on the line. Unfortunately, a large - % indentation looks wrong when the entry text itself is broken across - % lines. So we use a small indentation and put up with long leaders. - % - % \hangafter is reset to 1 (which is the value we want) at the start - % of each paragraph, so we need not do anything with that. - \hangindent = 2em - % - % When the entry text needs to be broken, just fill out the first line - % with blank space. - \rightskip = 0pt plus1fil - % - % A bit of stretch before each entry for the benefit of balancing columns. - \vskip 0pt plus1pt - % - % Start a ``paragraph'' for the index entry so the line breaking - % parameters we've set above will have an effect. - \noindent - % - % Insert the text of the index entry. TeX will do line-breaking on it. - #1% - % The following is kludged to not output a line of dots in the index if - % there are no page numbers. The next person who breaks this will be - % cursed by a Unix daemon. - \def\tempa{{\rm }}% - \def\tempb{#2}% - \edef\tempc{\tempa}% - \edef\tempd{\tempb}% - \ifx\tempc\tempd\ \else% - % - % If we must, put the page number on a line of its own, and fill out - % this line with blank space. (The \hfil is overwhelmed with the - % fill leaders glue in \indexdotfill if the page number does fit.) - \hfil\penalty50 - \null\nobreak\indexdotfill % Have leaders before the page number. - % - % The `\ ' here is removed by the implicit \unskip that TeX does as - % part of (the primitive) \par. Without it, a spurious underfull - % \hbox ensues. - \ #2% The page number ends the paragraph. - \fi% - \par -\endgroup} +\newskip\thinshrinkable +\skip\thinshrinkable=.15em minus .15em -% Like \dotfill except takes at least 1 em. +% Like plain.tex's \dotfill, except uses up at least 1 em. +% The filll stretch here overpowers both the fil and fill stretch to push +% the page number to the right. \def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1filll} + \def\primary #1{\line{#1\hfil}} -\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary{\indententry{0.5cm}} +\def\tertiary{\indententry{1cm}} -\def\secondary #1#2{ -{\parfillskip=0in \parskip=0in -\hangindent =1in \hangafter=1 -\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par -}} +\def\indententry#1#2#3{% + \bgroup + \leftskip=#1 + \entry{#2}{#3}% + \egroup +} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. -\catcode`\@=11 +\catcode`\@=11 % private names \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % If not much space left on page, start a new page. + \ifdim\pagetotal>0.8\vsize\vfill\eject\fi + % % Grab any single-column material above us. - \output = {\global\setbox\partialpage = \vbox{% - % - % Here is a possibility not foreseen in manmac: if we accumulate a - % whole lot of material, we might end up calling this \output - % routine twice in a row (see the doublecol-lose test, which is - % essentially a couple of indexes with @setchapternewpage off). In - % that case, we must prevent the second \partialpage from - % simply overwriting the first, causing us to lose the page. - % This will preserve it until a real output routine can ship it - % out. Generally, \partialpage will be empty when this runs and - % this will be a no-op. - \unvbox\partialpage + \output = {% + \savetopmark % - % Unvbox the main output page. - \unvbox255 - \kern-\topskip \kern\baselineskip - }}% + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. @@ -2862,94 +5838,190 @@ width0pt\relax} \fi \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) - \advance\vsize by -\ht\partialpage - \vsize = 2\vsize -} - -% The double-column output routine for all double-column pages except -% the last. -% -\def\doublecolumnout{% - \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. + \advance\vsize by -\ht\partialpage + \vsize = 2\vsize + % + % For the benefit of balancing columns + \advance\baselineskip by 0pt plus 0.5pt +} + +% The double-column output routine for all double-column pages except +% the last, which is done by \balancecolumns. +% +\def\doublecolumnout{% + % + \savetopmark + \splittopskip=\topskip \splitmaxdepth=\maxdepth \dimen@ = \vsize \divide\dimen@ by 2 % % box0 will be the left-hand column, box2 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ - \onepageout\pagesofar - \unvbox255 + \setbox0=\vsplit\PAGE to\dimen@ \setbox2=\vsplit\PAGE to\dimen@ + \global\advance\vsize by 2\ht\partialpage + \onepageout\pagesofar % empty except for the first time we are called + \unvbox\PAGE \penalty\outputpenalty } +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% - % Re-output the contents of the output page -- any previous material, - % followed by the two boxes we just split, in box0 and box2. - \advance\vsize by \ht\partialpage \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize - \hbox to\pagewidth{\box0\hfil\box2}% + \hbox to\txipagewidth{\box0\hfil\box2}% } + + +% Finished with double columns. \def\enddoublecolumns{% + % The following penalty ensures that the page builder is exercised + % _before_ we change the output routine. This is necessary in the + % following situation: + % + % The last section of the index consists only of a single entry. + % Before this section, \pagetotal is less than \pagegoal, so no + % break occurs before the last section starts. However, the last + % section, consisting of \initial and the single \entry, does not + % fit on the page and has to be broken off. Without the following + % penalty the page builder will not be exercised until \eject + % below, and by that time we'll already have changed the output + % routine to the \balancecolumns version, so the next-to-last + % double-column page will be processed with \balancecolumns, which + % is wrong: The two columns will go to the main vertical list, with + % the broken-off section in the recent contributions. As soon as + % the output routine finishes, TeX starts reconsidering the page + % break. The two columns and the broken-off section both fit on the + % page, because the two columns now take up only half of the page + % goal. When TeX sees \eject from below which follows the final + % section, it invokes the new output routine that we've set after + % \balancecolumns below; \onepageout will try to fit the two columns + % and the final section into the vbox of \txipageheight (see + % \pagebody), causing an overfull box. + % + % Note that glue won't work here, because glue does not exercise the + % page builder, unlike penalties (see The TeXbook, pp. 280-281). + \penalty0 + % \output = {% - % Split the last of the double-column material. Leave it on the - % current page, no automatic page break. + % Split the last of the double-column material. + \savetopmark \balancecolumns - % - % If we end up splitting too much material for the current page, - % though, there will be another page break right after this \output - % invocation ends. Having called \balancecolumns once, we do not + }% + \eject % call the \output just set + \ifdim\pagetotal=0pt + % Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal - % definition right away. (We hope \balancecolumns will never be - % called on to balance too much material, but if it is, this makes - % the output somewhat more palatable.) - \global\output = {\onepageout{\pagecontents\PAGE}}% - }% - \eject - \endgroup % started in \begindoublecolumns - % - % \pagegoal was set to the doubled \vsize above, since we restarted - % the current page. We're now back to normal single-column - % typesetting, so reset \pagegoal to the normal \vsize (after the - % \endgroup where \vsize got restored). - \pagegoal = \vsize + % definition right away. + \global\output=\expandafter{\the\defaultoutput} + % + \endgroup % started in \begindoublecolumns + % Leave the double-column material on the current page, no automatic + % page break. + \box\balancedcolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize. + \global\vsize = \txipageheight % + \pagegoal = \txipageheight % + \else + % We had some left-over material. This might happen when \doublecolumnout + % is called in \balancecolumns. Try again. + \expandafter\enddoublecolumns + \fi } +\newbox\balancedcolumns +\setbox\balancedcolumns=\vbox{shouldnt see this}% +% +% Only called for the last of the double column material. \doublecolumnout +% does the others. \def\balancecolumns{% - % Called at the end of the double column material. - \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \setbox0 = \vbox{\unvbox\PAGE}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 - \advance\dimen@ by \topskip - \advance\dimen@ by-\baselineskip - \divide\dimen@ by 2 % target to split to - %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% - \splittopskip = \topskip - % Loop until we get a decent breakpoint. - {% - \vbadness = 10000 - \loop - \global\setbox3 = \copy0 - \global\setbox1 = \vsplit3 to \dimen@ - \ifdim\ht3>\dimen@ - \global\advance\dimen@ by 1pt - \repeat - }% - %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% - \setbox0=\vbox to\dimen@{\unvbox1}% - \setbox2=\vbox to\dimen@{\unvbox3}% + \ifdim\dimen@<7\baselineskip + % Don't split a short final column in two. + \setbox2=\vbox{}% + \global\setbox\balancedcolumns=\vbox{\pagesofar}% + \else + % double the leading vertical space + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + \dimen@ii = \dimen@ + \splittopskip = \topskip + % Loop until left column is at least as high as the right column. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht1<\ht3 + \global\advance\dimen@ by 1pt + \repeat + }% + % Now the left column is in box 1, and the right column in box 3. + % + % Check whether the left column has come out higher than the page itself. + % (Note that we have doubled \vsize for the double columns, so + % the actual height of the page is 0.5\vsize). + \ifdim2\ht1>\vsize + % It appears that we have been called upon to balance too much material. + % Output some of it with \doublecolumnout, leaving the rest on the page. + \setbox\PAGE=\box0 + \doublecolumnout + \else + % Compare the heights of the two columns. + \ifdim4\ht1>5\ht3 + % Column heights are too different, so don't make their bottoms + % flush with each other. + \setbox2=\vbox to \ht1 {\unvbox3\vfill}% + \setbox0=\vbox to \ht1 {\unvbox1\vfill}% + \else + % Make column bottoms flush with each other. + \setbox2=\vbox to\ht1{\unvbox3\unskip}% + \setbox0=\vbox to\ht1{\unvbox1\unskip}% + \fi + \global\setbox\balancedcolumns=\vbox{\pagesofar}% + \fi + \fi % - \pagesofar } \catcode`\@ = \other \message{sectioning,} -% Define chapters, sections, etc. +% Chapters, sections, etc. +% Let's start with @part. +\outer\parseargdef\part{\partzzz{#1}} +\def\partzzz#1{% + \chapoddpage + \null + \vskip.3\vsize % move it down on the page a bit + \begingroup + \noindent \titlefonts\rm #1\par % the text + \let\lastnode=\empty % no node to associate with + \writetocentry{part}{#1}{}% but put it in the toc + \headingsoff % no headline or footline on the part page + % This outputs a mark at the end of the page that clears \thischapter + % and \thissection, as is done in \startcontents. + \let\pchapsepmacro\relax + \chapmacro{}{Yomitfromtoc}{}% + \chapoddpage + \endgroup +} + +% \unnumberedno is an oxymoron. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 @@ -2957,354 +6029,374 @@ width0pt\relax} \fi % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ -\def\appendixletter{\char\the\appendixno} +% +% \def\appendixletter{\char\the\appendixno} +% We do the following ugly conditional instead of the above simple +% construct for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +% +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} -% Each @chapter defines this as the name of the chapter. -% page headings and footings can use it. @section does likewise. +% Each @chapter defines these (using marks) as the number+name, number +% and name of the chapter. Page headings and footings can use +% these. @section does likewise. \def\thischapter{} +\def\thischapternum{} +\def\thischaptername{} \def\thissection{} +\def\thissectionnum{} +\def\thissectionname{} \newcount\absseclevel % used to calculate proper heading level -\newcount\secbase\secbase=0 % @raise/lowersections modify this count +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} -\let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} -\let\down=\lowersections % original BFox name -% Choose a numbered-heading macro -% #1 is heading level if unmodified by @raisesections or @lowersections -% #2 is text for heading -\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \chapterzzz{#2} -\or - \seczzz{#2} -\or - \numberedsubseczzz{#2} -\or - \numberedsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \chapterzzz{#2} +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achieve this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unnlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 \else - \numberedsubsubseczzz{#2} + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi \fi -\fi -} - -% like \numhead, but chooses appendix heading levels -\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \appendixzzz{#2} -\or - \appendixsectionzzz{#2} -\or - \appendixsubseczzz{#2} -\or - \appendixsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \appendixzzz{#2} + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unnlevel + \chardef\unnlevel = \absseclevel + \fi \else - \appendixsubsubseczzz{#2} + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unnlevel + \def\headtype{U}% + \else + \chardef\unnlevel = 3 + \fi \fi -\fi -} - -% like \numhead, but chooses numberless heading levels -\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \unnumberedzzz{#2} -\or - \unnumberedseczzz{#2} -\or - \unnumberedsubseczzz{#2} -\or - \unnumberedsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \unnumberedzzz{#2} + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi \else - \unnumberedsubsubseczzz{#2} + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi \fi -\fi + \suppressfirstparagraphindent } -% @chapter, @appendix, @unnumbered. -\def\thischaptername{No Chapter Title} -\outer\def\chapter{\parsearg\chapteryyy} -\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz -\def\chapterzzz #1{% -\secno=0 \subsecno=0 \subsubsecno=0 -\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% -\chapmacro {#1}{\the\chapno}% -\gdef\thissection{#1}% -\gdef\thischaptername{#1}% -% We don't substitute the actual chapter name into \thischapter -% because we don't want its macros evaluated now. -\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% - {\the\chapno}}}% -\temp -\donoderef -\global\let\section = \numberedsec -\global\let\subsection = \numberedsubsec -\global\let\subsubsection = \numberedsubsubsec +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + % \putwordChapter can contain complex things in translations. + \toks0=\expandafter{\putwordChapter}% + \message{\the\toks0 \space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec } -\outer\def\appendix{\parsearg\appendixyyy} -\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz -\def\appendixzzz #1{% -\secno=0 \subsecno=0 \subsubsecno=0 -\global\advance \appendixno by 1 -\message{\putwordAppendix\space \appendixletter}% -\chapmacro {#1}{\putwordAppendix{} \appendixletter}% -\gdef\thissection{#1}% -\gdef\thischaptername{#1}% -\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% - {\putwordAppendix{} \appendixletter}}}% -\temp -\appendixnoderef -\global\let\section = \appendixsec -\global\let\subsection = \appendixsubsec -\global\let\subsubsection = \appendixsubsubsec +\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz +% +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + % \putwordAppendix can contain complex things in translations. + \toks0=\expandafter{\putwordAppendix}% + \message{\the\toks0 \space \appendixletter}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +% normally unnmhead0 calls unnumberedzzz: +\outer\parseargdef\unnumbered{\unnmhead0{#1}} +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the to achieve this: TeX expands \the only once, + % simply yielding the contents of . (We also do this for + % the toc entries.) + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% + % + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. -\outer\def\centerchap{\parsearg\centerchapyyy} -\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} +\outer\parseargdef\centerchap{% + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax +} % @top is like @unnumbered. -\outer\def\top{\parsearg\unnumberedyyy} - -\outer\def\unnumbered{\parsearg\unnumberedyyy} -\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz -\def\unnumberedzzz #1{% -\secno=0 \subsecno=0 \subsubsecno=0 -% -% This used to be simply \message{#1}, but TeX fully expands the -% argument to \message. Therefore, if #1 contained @-commands, TeX -% expanded them. For example, in `@unnumbered The @cite{Book}', TeX -% expanded @cite (which turns out to cause errors because \cite is meant -% to be executed, not expanded). -% -% Anyway, we don't want the fully-expanded definition of @cite to appear -% as a result of the \message, we just want `@cite' itself. We use -% \the to achieve this: TeX expands \the only once, -% simply yielding the contents of . (We also do this for -% the toc entries.) -\toks0 = {#1}\message{(\the\toks0)}% -% -\unnumbchapmacro {#1}% -\gdef\thischapter{#1}\gdef\thissection{#1}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}% -\temp -\unnumbnoderef -\global\let\section = \unnumberedsec -\global\let\subsection = \unnumberedsubsec -\global\let\subsubsection = \unnumberedsubsubsec -} +\let\top\unnumbered % Sections. -\outer\def\numberedsec{\parsearg\secyyy} -\def\secyyy #1{\numhead1{#1}} % normally calls seczzz -\def\seczzz #1{% -\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % -\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% - {\the\chapno}{\the\secno}}}% -\temp -\donoderef -\nobreak +% +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } -\outer\def\appendixsection{\parsearg\appendixsecyyy} -\outer\def\appendixsec{\parsearg\appendixsecyyy} -\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz -\def\appendixsectionzzz #1{% -\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % -\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% - {\appendixletter}{\the\secno}}}% -\temp -\appendixnoderef -\nobreak +% normally calls appendixsectionzzz: +\outer\parseargdef\appendixsection{\apphead1{#1}} +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } +\let\appendixsec\appendixsection -\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} -\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz -\def\unnumberedseczzz #1{% -\plainsecheading {#1}\gdef\thissection{#1}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}% -\temp -\unnumbnoderef -\nobreak +% normally calls unnumberedseczzz: +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. -\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} -\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz -\def\numberedsubseczzz #1{% -\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % -\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% - {\the\chapno}{\the\secno}{\the\subsecno}}}% -\temp -\donoderef -\nobreak +% +% normally calls numberedsubseczzz: +\outer\parseargdef\numberedsubsec{\numhead2{#1}} +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } -\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} -\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz -\def\appendixsubseczzz #1{% -\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % -\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% - {\appendixletter}{\the\secno}{\the\subsecno}}}% -\temp -\appendixnoderef -\nobreak +% normally calls appendixsubseczzz: +\outer\parseargdef\appendixsubsec{\apphead2{#1}} +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% } -\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} -\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz -\def\unnumberedsubseczzz #1{% -\plainsubsecheading {#1}\gdef\thissection{#1}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry% - {\the\toks0}}}% -\temp -\unnumbnoderef -\nobreak +% normally calls unnumberedsubseczzz: +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. -\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} -\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz -\def\numberedsubsubseczzz #1{% -\gdef\thissection{#1}\global\advance \subsubsecno by 1 % -\subsubsecheading {#1} - {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% - {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% -\temp -\donoderef -\nobreak +% +% normally numberedsubsubseczzz: +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } -\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} -\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz -\def\appendixsubsubseczzz #1{% -\gdef\thissection{#1}\global\advance \subsubsecno by 1 % -\subsubsecheading {#1} - {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% - {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% -\temp -\appendixnoderef -\nobreak +% normally appendixsubsubseczzz: +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } -\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} -\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz -\def\unnumberedsubsubseczzz #1{% -\plainsubsubsecheading {#1}\gdef\thissection{#1}% -\toks0 = {#1}% -\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry% - {\the\toks0}}}% -\temp -\unnumbnoderef -\nobreak +% normally unnumberedsubsubseczzz: +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } -% These are variants which are not "outer", so they can appear in @ifinfo. -% Actually, they should now be obsolete; ordinary section commands should work. -\def\infotop{\parsearg\unnumberedzzz} -\def\infounnumbered{\parsearg\unnumberedzzz} -\def\infounnumberedsec{\parsearg\unnumberedseczzz} -\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} -\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} - -\def\infoappendix{\parsearg\appendixzzz} -\def\infoappendixsec{\parsearg\appendixseczzz} -\def\infoappendixsubsec{\parsearg\appendixsubseczzz} -\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} - -\def\infochapter{\parsearg\chapterzzz} -\def\infosection{\parsearg\sectionzzz} -\def\infosubsection{\parsearg\subsectionzzz} -\def\infosubsubsection{\parsearg\subsubsectionzzz} - % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. -\global\let\section = \numberedsec -\global\let\subsection = \numberedsubsec -\global\let\subsubsection = \numberedsubsubsec +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading -% NOTE on use of \vbox for chapter headings, section headings, and such: -% 1) We use \vbox rather than the earlier \line to permit -% overlong headings to fold. -% 2) \hyphenpenalty is set to 10000 because hyphenation in a -% heading is obnoxious; this forbids it. -% 3) Likewise, headings look best if no \parindent is used, and -% if justification is not attempted. Hence \raggedright. +\def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +} - -\def\majorheading{\parsearg\majorheadingzzz} -\def\majorheadingzzz #1{% -{\advance\chapheadingskip by 10pt \chapbreak }% -{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} - -\def\chapheading{\parsearg\chapheadingzzz} -\def\chapheadingzzz #1{\chapbreak % -{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% + \vbox{\chapfonts \raggedtitlesettings #1\par}% + \nobreak\bigskip \nobreak + \suppressfirstparagraphindent +} % @heading, @subheading, @subsubheading. -\def\heading{\parsearg\plainsecheading} -\def\subheading{\parsearg\plainsubsecheading} -\def\subsubheading{\parsearg\plainsubsubsecheading} +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. -%%% Args are the skip and penalty (usually negative) +% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} -\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} - -%%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) - \newskip\chapheadingskip +% Define plain chapter starts, and page on/off switching for it. \def\chapbreak{\dobreak \chapheadingskip {-4000}} -\def\chappager{\par\vfill\supereject} -\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} -\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} +% Start a new page +\def\chappager{\par\vfill\supereject} + +% \chapoddpage - start on an odd page for a new chapter +% Because \domark is called before \chapoddpage, the filler page will +% get the headings for the next chapter, which is wrong. But we don't +% care -- we just disable all headings on the filler page. +\def\chapoddpage{% + \chappager + \ifodd\pageno \else + \begingroup + \headingsoff + \null + \chappager + \endgroup + \fi +} + +\parseargdef\setchapternewpage{\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager @@ -3317,7 +6409,7 @@ width0pt\relax} \fi \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} -\def\CHAPPAGodd{ +\def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage @@ -3325,258 +6417,531 @@ width0pt\relax} \fi \CHAPPAGon -\def\CHAPFplain{ -\global\let\chapmacro=\chfplain -\global\let\unnumbchapmacro=\unnchfplain -\global\let\centerchapmacro=\centerchfplain} - -% Plain chapter opening. -% #1 is the text, #2 the chapter number or empty if unnumbered. -\def\chfplain#1#2{% +% \chapmacro - Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% Not used for @heading series. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yappendixkeyword{Yappendix} +\def\Yomitfromtockeyword{Yomitfromtoc} +% +\def\chapmacro#1#2#3{% + \expandafter\ifx\thisenv\titlepage\else + \checkenv{}% chapters, etc., should not start inside an environment. + \fi + % Insert the first mark before the heading break (see notes for \domark). + \let\prevchapterdefs=\currentchapterdefs + \let\prevsectiondefs=\currentsectiondefs + \gdef\currentsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% + \gdef\thissection{}}% + % + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{\thischaptername}}% + \else\ifx\temptype\Yomitfromtockeyword + \gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{}}% + \else\ifx\temptype\Yappendixkeyword + \toks0={#1}% + \xdef\currentchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\appendixletter}% + % \noexpand\putwordAppendix avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordAppendix{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \else + \toks0={#1}% + \xdef\currentchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\the\chapno}% + % \noexpand\putwordChapter avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordChapter{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \fi\fi\fi + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert the chapter heading break. \pchapsepmacro + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevchapterdefs=\currentchapterdefs + \let\prevsectiondefs=\currentsectiondefs + \domark + % {% \chapfonts \rm - \def\chapnum{#2}% - \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 \centerparametersmaybe + \let\footnote=\errfootnoteheading % give better error message + % + % Have to define \currentsection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\currentsection{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. + \nobreak % Avoid page breaks at the interline glue. + \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } -% Plain opening for unnumbered. -\def\unnchfplain#1{\chfplain{#1}{}} - % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax -\def\centerchfplain#1{{% - \def\centerparametersmaybe{% - \advance\rightskip by 3\rightskip - \leftskip = \rightskip - \parfillskip = 0pt - }% - \chfplain{#1}{}% -}} - -\CHAPFplain % The default - -\def\unnchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\nobreak +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt } -\def\chfopen #1#2{\chapoddpage {\chapfonts -\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% -\par\penalty 5000 % -} -\def\centerchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt - \hfill {\rm #1}\hfill}}\bigskip \par\nobreak -} - -\def\CHAPFopen{ -\global\let\chapmacro=\chfopen -\global\let\unnumbchapmacro=\unnchfopen -\global\let\centerchapmacro=\centerchfopen} - - -% Section titles. +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% \newskip\secheadingskip -\def\secheadingbreak{\dobreak \secheadingskip {-1000}} -\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} -\def\plainsecheading#1{\sectionheading{sec}{}{#1}} +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. -\newskip \subsecheadingskip -\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} -\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} -\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. -\let\subsubsecheadingskip = \subsecheadingskip -\let\subsubsecheadingbreak = \subsecheadingbreak -\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} -\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} -% Print any size section title. +% Print any size, any type, section title. % -% #1 is the section type (sec/subsec/subsubsec), #2 is the section -% number (maybe empty), #3 the text. -\def\sectionheading#1#2#3{% - {% - \expandafter\advance\csname #1headingskip\endcsname by \parskip - \csname #1headingbreak\endcsname - }% +% #1 is the text of the title, +% #2 is the section level (sec/subsec/subsubsec), +% #3 is the section type (Ynumbered, Ynothing, Yappendix, Yomitfromtoc), +% #4 is the section number. +% +\def\seckeyword{sec} +% +\def\sectionheading#1#2#3#4{% {% + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + % It is ok for the @heading series commands to appear inside an + % environment (it's been historically allowed, though the logic is + % dubious), but not the others. + \ifx\temptype\Yomitfromtockeyword\else + \checkenv{}% non-@*heading should not be in an environment. + \fi + \let\footnote=\errfootnoteheading + % % Switch to the right set of fonts. - \csname #1fonts\endcsname \rm + \csname #2fonts\endcsname \rm % - % Only insert the separating space if we have a section number. - \def\secnum{#2}% - \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % Insert first mark before the heading break (see notes for \domark). + \let\prevsectiondefs=\currentsectiondefs + \ifx\temptype\Ynothingkeyword + \ifx\sectionlevel\seckeyword + \gdef\currentsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% + \gdef\thissection{\thissectionname}}% + \fi + \else\ifx\temptype\Yomitfromtockeyword + % Don't redefine \thissection. + \else\ifx\temptype\Yappendixkeyword + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\currentsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \else + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\currentsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \fi\fi\fi % - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 % zero if no section number - \unhbox0 #3}% + % Go into vertical mode. Usually we'll already be there, but we + % don't want the following whatsit to end up in a preceding paragraph + % if the document didn't happen to have a blank line. + \par + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert space above the heading. + \csname #2headingbreak\endcsname + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \global\let\prevsectiondefs=\currentsectiondefs + \domark + % + % Only insert the space after the number if we have a section number. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\currentsection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \currentsection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\currentsection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\currentsection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chapmacro. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chapmacro. + \donoderef{#3}% + % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % + % Output the actual section heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% }% - \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. + \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) However, when a paragraph is not started next + % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out + % or the negative glue will cause weirdly wrong output, typically + % obscuring the section heading with something else. + \vskip-\parskip + % + % This is so the last item on the main vertical list is a known + % \penalty > 10000, so \startdefun, etc., can recognize the situation + % and do the needful. + \penalty 10001 } \message{toc,} +% Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. -% Called from @chapter, etc. We supply {\folio} at the end of the -% argument, which will end up as the last argument to the \...entry macro. -% -% We open the .toc file here instead of at @setfilename or any other -% given time so that @contents can be put in the document anywhere. -% +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. +% +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. +% \newif\iftocfileopened -\def\writetocentry#1{% - \iftocfileopened\else - \immediate\openout\tocfile = \jobname.toc - \global\tocfileopenedtrue +\def\omitkeyword{omit}% +% +\def\writetocentry#1#2#3{% + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% + \fi \fi - \iflinks \write\tocfile{#1{\folio}}\fi + % + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one on every page because the title pages are numbered + % 1 and 2 (the page numbers aren't printed), and so are the first + % two pages of the document. Thus, we'd have two destinations named + % `1', and two named `2'. + \ifpdforxetex + \global\pdfmakepagedesttrue + \fi +} + + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \tocreadfilename } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 -% Finish up the main text and prepare to read what we've written -% to \tocfile. -% +% Prepare to read what we've written to \tocfile. +% \def\startcontents#1{% - % If @setchapternewpage on, and @headings double, the contents should - % start on an odd page, unlike chapters. Thus, we maintain - % \contentsalignmacro in parallel with \pagealignmacro. - % From: Torbjorn Granlund - \contentsalignmacro - \immediate\closeout\tocfile - % - % Don't need to put `Contents' or `Short Contents' in the headline. - % It is abundantly clear what they are. - \unnumbchapmacro{#1}\def\thischapter{}% - \savepageno = \pageno - \begingroup % Set up to handle contents files properly. - \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 - % We can't do this, because then an actual ^ in a section - % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. - %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi - \raggedbottom % Worry more about breakpoints than the bottom. - \advance\hsize by -\contentsrightmargin % Don't use the full line length. - % - % Roman numerals for page numbers. - \ifnum \pageno>0 \pageno = \lastnegativepageno \fi + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \chapmacro{#1}{Yomitfromtoc}{}% + % + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \raggedbottom % Worry more about breakpoints than the bottom. + \entryrightmargin=\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } +% redefined for the two-volume lispref. We always output on +% \jobname.toc even if this is redefined. +% +\def\tocreadfilename{\jobname.toc} % Normal (long) toc. +% \def\contents{% - \startcontents{\putwordTableofContents}% - \openin 1 \jobname.toc - \ifeof 1 \else - \closein 1 - \input \jobname.toc - \fi - \vfill \eject - \endgroup - \lastnegativepageno = \pageno - \pageno = \savepageno + \startcontents{\putwordTOC}% + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% - \startcontents{\putwordShortContents}% - % - \let\chapentry = \shortchapentry - \let\unnumbchapentry = \shortunnumberedentry - % We want a true roman here for the page numbers. - \secfonts - \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl - \rm - \hyphenpenalty = 10000 - \advance\baselineskip by 1pt % Open it up a little. - \def\secentry ##1##2##3##4{} - \def\unnumbsecentry ##1##2{} - \def\subsecentry ##1##2##3##4##5{} - \def\unnumbsubsecentry ##1##2{} - \def\subsubsecentry ##1##2##3##4##5##6{} - \def\unnumbsubsubsecentry ##1##2{} - \openin 1 \jobname.toc - \ifeof 1 \else - \closein 1 - \input \jobname.toc - \fi - \vfill \eject - \endgroup - \lastnegativepageno = \pageno - \pageno = \savepageno + \startcontents{\putwordShortTOC}% + % + \let\partentry = \shortpartentry + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno } \let\shortcontents = \summarycontents +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} + % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... -% Chapter-level things, for both the long and short contents. -\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} - -% See comments in \dochapentry re vbox and related settings -\def\shortchapentry#1#2#3{% - \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +% Parts, in the main contents. Replace the part number, which doesn't +% exist, with an empty box. Let's hope all the numbers have the same width. +% Also ignore the page number, which is conventionally not printed. +\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} +\def\partentry#1#2#3#4{% + % Add stretch and a bonus for breaking the page before the part heading. + % This reduces the chance of the page being broken immediately after the + % part heading, before a following chapter heading. + \vskip 0pt plus 5\baselineskip + \penalty-300 + \vskip 0pt plus -5\baselineskip + \dochapentry{\numeralbox\labelspace#1}{}% +} +% +% Parts, in the short toc. +\def\shortpartentry#1#2#3#4{% + \penalty-300 + \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip + \shortchapentry{{\bf #1}}{\numeralbox}{}{}% } -% Typeset the label for a chapter or appendix for the short contents. -% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. -% We could simplify the code here by writing out an \appendixentry -% command in the toc file for appendices, instead of using \chapentry -% for both, but it doesn't seem worth it. -\setbox0 = \hbox{\shortcontrm \putwordAppendix } -\newdimen\shortappendixwidth \shortappendixwidth = \wd0 +% Chapters, in the main contents. +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} -\def\shortchaplabel#1{% - % We typeset #1 in a box of constant width, regardless of the text of - % #1, so the chapter titles will come out aligned. - \setbox0 = \hbox{#1}% - \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi - % - % This space should be plenty, since a single number is .5em, and the - % widest letter (M) is 1em, at least in the Computer Modern fonts. - % (This space doesn't include the extra space that gets added after - % the label; that gets put in by \shortchapentry above.) - \advance\dimen0 by 1.1em - \hbox to \dimen0{#1\hfil}% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } -\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} -\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} +% Appendices, in the main contents. +% Need the word Appendix, and a fixed-size box. +% +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} +% +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\hskip.7em#1}{#4}} + +% Unnumbered chapters. +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. -\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} -\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. -\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} -\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. -\def\subsubsecentry#1#2#3#4#5#6{% - \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} -\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. -\newdimen\tocindent \tocindent = 3pc +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. @@ -3586,38 +6951,31 @@ width0pt\relax} \fi \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup + % Move the page numbers slightly to the right + \advance\entryrightmargin by -0.05em \chapentryfonts - \tocentry{#1}{\dopageno{#2}}% + \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent - \tocentry{#1}{\dopageno{#2}}% + \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent - \tocentry{#1}{\dopageno{#2}}% + \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent - \tocentry{#1}{\dopageno{#2}}% + \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} -% Final typesetting of a toc entry; we use the same \entry macro as for -% the index entries, but we want to suppress hyphenation here. (We -% can't do that in the \entry macro, since index entries might consist -% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) -\def\tocentry#1#2{\begingroup - \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks - % Do not use \turnoffactive in these arguments. Since the toc is - % typeset in cmr, so characters such as _ would come out wrong; we - % have to do the usual translation tricks. - \entry{#1}{#2}% -\endgroup} +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} @@ -3627,73 +6985,36 @@ width0pt\relax} \fi \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} -\let\subsecentryfonts = \textfonts -\let\subsubsecentryfonts = \textfonts +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} \message{environments,} +% @foo ... @end foo. -% Since these characters are used in examples, it should be an even number of -% \tt widths. Each \tt character is 1en, so two makes it 1em. -% Furthermore, these definitions must come after we define our fonts. -\newbox\dblarrowbox \newbox\longdblarrowbox -\newbox\pushcharbox \newbox\bullbox -\newbox\equivbox \newbox\errorbox - -%{\tentt -%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} -%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} -%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} -%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} -% Adapted from the manmac format (p.420 of TeXbook) -%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex -% depth .1ex\hfil} -%} - -% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. -\def\point{$\star$} -\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} -\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} -\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} -\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} - -% Adapted from the TeXbook's \boxit. -{\tentt \global\dimen0 = 3em}% Width of the box. -\dimen2 = .55pt % Thickness of rules -% The text. (`r' is open on the right, `e' somewhat less so on the left.) -\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} - -\global\setbox\errorbox=\hbox to \dimen0{\hfil - \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. - \advance\hsize by -2\dimen2 % Rules. - \vbox{ - \hrule height\dimen2 - \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. - \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. - \kern3pt\vrule width\dimen2}% Space to right. - \hrule height\dimen2} - \hfil} - -% The @error{} command. -\def\error{\leavevmode\lower.7ex\copy\errorbox} - -% @tex ... @end tex escapes into raw Tex temporarily. +% @tex ... @end tex escapes into raw TeX temporarily. % One exception: @ is still an escape character, so that @end tex works. -% But \@ or @@ will get a plain tex @ character. +% But \@ or @@ will get a plain @ character. -\def\tex{\begingroup +\envdef\tex{% + \setupmarkupstyle{tex}% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 - \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 - \catcode 43=12 % plus - \catcode`\"=12 - \catcode`\==12 - \catcode`\|=12 - \catcode`\<=12 - \catcode`\>=12 - \escapechar=`\\ + \catcode `\+=\other + \catcode `\"=\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \catcode `\`=\other + \catcode `\'=\other % + % ' is active in math mode (mathcode"8000). So reset it, and all our + % other math active characters (just in case), to plain's definitions. + \mathactive + % + % Inverse of the list at the beginning of the file. \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc @@ -3703,20 +7024,28 @@ width0pt\relax} \fi \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi + \let\indent=\ptexindent + \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace + \let\/=\ptexslash + \let\sp=\ptexsp \let\*=\ptexstar + %\let\sup=\ptexsup % do not redefine, we want @sup to work in math mode \let\t=\ptext + \expandafter \let\csname top\endcsname=\ptextop % we've made it outer + \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% -\let\Etex=\endgroup} +} +% There is no need to define \Etex. -% Define @lisp ... @endlisp. -% @lisp does a \begingroup so it can rebind things, -% including the definition of @endlisp (which normally is erroneous). +% Define @lisp ... @end lisp. +% @lisp environment forms a group so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in @@ -3726,43 +7055,55 @@ width0pt\relax} \fi % have any width. \def\lisppar{\null\endgraf} -% Make each space character in the input produce a normal interword -% space in the output. Don't allow a line break at this space, as this -% is used only in environments like @example, where each line of input -% should produce a line of output anyway. -% -{\obeyspaces % -\gdef\sepspaces{\obeyspaces\let =\tie}} - -% Define \obeyedspace to be our active space, whatever it is. This is -% for use in \parsearg. -{\sepspaces% -\global\let\obeyedspace= } - % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the -% start of the next paragraph will insert \parskip +% start of the next paragraph will insert \parskip. % -\def\aboveenvbreak{{\advance\envskipamount by \parskip -\endgraf \ifdim\lastskip<\envskipamount -\removelastskip \penalty-50 \vskip\envskipamount \fi}} +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + \ifnum\lastpenalty<10000 + % Penalize breaking before the environment, because preceding text + % often leads into it. + \penalty100 + \fi + \vskip\envskipamount + \fi + \fi +}} -\let\afterenvbreak = \aboveenvbreak +\def\afterenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty<10000 \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} -% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. -\font\circle=lcircle10 -\newdimen\circthick -\newdimen\cartouter\newdimen\cartinner -\newskip\normbskip\newskip\normpskip\newskip\normlskip -\circthick=\fontdimen8\circle + % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} @@ -3777,731 +7118,935 @@ width0pt\relax} \fi % \newskip\lskip\newskip\rskip -\long\def\cartouche{% -\begingroup - \lskip=\leftskip \rskip=\rightskip - \leftskip=0pt\rightskip=0pt %we want these *outside*. - \cartinner=\hsize \advance\cartinner by-\lskip - \advance\cartinner by-\rskip - \cartouter=\hsize - \advance\cartouter by 18.4pt % allow for 3pt kerns on either -% side, and for 6pt waste from -% each corner char, and rule thickness - \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip - % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing=\comment - \vbox\bgroup - \baselineskip=0pt\parskip=0pt\lineskip=0pt - \carttop - \hbox\bgroup - \hskip\lskip - \vrule\kern3pt - \vbox\bgroup - \hsize=\cartinner - \kern3pt - \begingroup - \baselineskip=\normbskip - \lineskip=\normlskip - \parskip=\normpskip - \vskip -\parskip +% only require the font if @cartouche is actually used +\def\cartouchefontdefs{% + \font\circle=lcircle10\relax + \circthick=\fontdimen8\circle +} +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip + + +\envdef\cartouche{% + \cartouchefontdefs + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt % we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % + % If this cartouche directly follows a sectioning command, we need the + % \parskip glue (backspaced over by default) or the cartouche can + % collide with the section heading. + \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi + % + \setbox\groupbox=\vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of def\group. +} \def\Ecartouche{% - \endgroup - \kern3pt - \egroup - \kern3pt\vrule - \hskip\rskip - \egroup - \cartbot - \egroup -\endgroup -}} + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \addgroupbox + \checkinserts +} % This macro is called at the beginning of all the @example variants, % inside a group. +\newdimen\nonfillparindent \def\nonfillstart{% \aboveenvbreak - \inENV % This group ends at the end of the body - \hfuzz = 12pt % Don't be fussy + \ifdim\hfuzz < 12pt \hfuzz = 12pt \fi % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. - \singlespace \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt + % Turn off paragraph indentation but redefine \indent to emulate + % the normal \indent. + \nonfillparindent=\parindent \parindent = 0pt + \let\indent\nonfillindent + % \emergencystretch = 0pt % don't try to avoid overfull boxes - % @cartouche defines \nonarrowing to inhibit narrowing - % at next level down. \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing - \let\exdent=\nofillexdent - \let\nonarrowing=\relax + \else + \let\nonarrowing = \relax + \fi + \let\exdent=\nofillexdent +} + +\begingroup +\obeyspaces +% We want to swallow spaces (but not other tokens) after the fake +% @indent in our nonfill-environments, where spaces are normally +% active and set to @tie, resulting in them not being ignored after +% @indent. +\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}% +\gdef\nonfillindentcheck{% +\ifx\temp % +\expandafter\nonfillindentgobble% +\else% +\leavevmode\nonfillindentbox% +\fi% +}% +\endgroup +\def\nonfillindentgobble#1{\nonfillindent} +\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}} + +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp +% +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + % end paragraph for sake of leading, in case document has no blank + % line. This is redundant with what happens in \aboveenvbreak, but + % we need to do it before changing the fonts, and it's inconvenient + % to change the fonts afterward. + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm \fi } -% Define the \E... control sequence only if we are inside the particular -% environment, so the error checking in \end will work. -% -% To end an @example-like environment, we first end the paragraph (via -% \afterenvbreak's vertical glue), and then the group. That way we keep -% the zero \parskip that the environments set -- \parskip glue will be -% inserted at the beginning of the next paragraph in the document, after -% the environment. -% -\def\nonfillfinish{\afterenvbreak\endgroup} - -% @lisp: indented, narrowed, typewriter font. -\def\lisp{\begingroup - \nonfillstart - \let\Elisp = \nonfillfinish - \tt - \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. - \gobble % eat return +% We often define two environments, @foo and @smallfoo. +% Let's do it in one command. #1 is the env name, #2 the definition. +\def\makedispenvdef#1#2{% + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}% + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}% + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } -% @example: Same as @lisp. -\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} - -% @small... is usually equivalent to the non-small (@smallbook -% redefines). We must call \example (or whatever) last in the -% definition, since it reads the return following the @example (or -% whatever) command. -% -% This actually allows (for example) @end display inside an -% @smalldisplay. Too bad, but makeinfo will catch the error anyway. +% Define two environment synonyms (#1 and #2) for an environment. +\def\maketwodispenvdef#1#2#3{% + \makedispenvdef{#1}{#3}% + \makedispenvdef{#2}{#3}% +} % -\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display} -\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp} -\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format} -\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp} - -% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts. +% @lisp: indented, narrowed, typewriter font; +% @example: same as @lisp. +% +% @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. -\def\smalllispx{\begingroup - \def\Esmalllisp{\nonfillfinish\endgroup}% - \def\Esmallexample{\nonfillfinish\endgroup}% - \indexfonts - \lisp -} - -% @display: same as @lisp except keep current font. % -\def\display{\begingroup +\maketwodispenvdef{lisp}{example}{% + \nonfillstart + \tt\setupmarkupstyle{example}% + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} +% @display/@smalldisplay: same as @lisp except keep current font. +% +\makedispenvdef{display}{% \nonfillstart - \let\Edisplay = \nonfillfinish \gobble } -% @smalldisplay (when @smallbook): @display plus smaller fonts. +% @format/@smallformat: same as @display except don't narrow margins. % -\def\smalldisplayx{\begingroup - \def\Esmalldisplay{\nonfillfinish\endgroup}% - \indexfonts \rm - \display -} - -% @format: same as @display except don't narrow margins. -% -\def\format{\begingroup - \let\nonarrowing = t +\makedispenvdef{format}{% + \let\nonarrowing = t% \nonfillstart - \let\Eformat = \nonfillfinish \gobble } -% @smallformat (when @smallbook): @format plus smaller fonts. -% -\def\smallformatx{\begingroup - \def\Esmallformat{\nonfillfinish\endgroup}% - \indexfonts \rm - \format +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble } - -% @flushleft (same as @format). -% -\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} +\let\Eflushleft = \afterenvbreak % @flushright. -% -\def\flushright{\begingroup - \let\nonarrowing = t +% +\envdef\flushright{% + \let\nonarrowing = t% \nonfillstart - \let\Eflushright = \nonfillfinish - \advance\leftskip by 0pt plus 1fill + \advance\leftskip by 0pt plus 1fill\relax \gobble } +\let\Eflushright = \afterenvbreak + + +% @raggedright does more-or-less normal line breaking but no right +% justification. From plain.tex. +\envdef\raggedright{% + \rightskip0pt plus2.4em \spaceskip.3333em \xspaceskip.5em\relax +} +\let\Eraggedright\par + +\envdef\raggedleft{% + \parindent=0pt \leftskip0pt plus2em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedleft\par + +\envdef\raggedcenter{% + \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedcenter\par + % @quotation does normal linebreaking (hence we can't use \nonfillstart) -% and narrows the margins. +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. % -\def\quotation{% - \begingroup\inENV %This group ends at the end of the @quotation body +\makedispenvdef{quotation}{\quotationstart} +% +\def\quotationstart{% + \indentedblockstart % same as \indentedblock, but increase right margin too. + \ifx\nonarrowing\relax + \advance\rightskip by \lispnarrowing + \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\thisisundefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} +\def\Esmallquotation{\Equotation} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi +} + +% @indentedblock is like @quotation, but indents only on the left and +% has no optional argument. +% +\makedispenvdef{indentedblock}{\indentedblockstart} +% +\def\indentedblockstart{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip - \singlespace \parindent=0pt - % We have retained a nonzero parskip for the environment, since we're - % doing normal filling. So to avoid extra space below the environment... - \def\Equotation{\parskip = 0pt \nonfillfinish}% % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing - \advance\rightskip by \lispnarrowing \exdentamount = \lispnarrowing + \else \let\nonarrowing = \relax \fi } +% Keep a nonzero parskip for the environment, since we're doing normal filling. +% +\def\Eindentedblock{% + \par + {\parskip=0pt \afterenvbreak}% +} +\def\Esmallindentedblock{\Eindentedblock} + + +% LaTeX-like @verbatim...@end verbatim and @verb{...} +% If we want to allow any as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% + % Don't do the quotes -- if we do, @set txicodequoteundirected and + % @set txicodequotebacktick will not have effect on @verb and + % @verbatim, and ?` and !` ligatures won't get disabled. + %\do\`\do\'% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=\other}\dospecials} +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \setupmarkupstyle{verb}% + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion. +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +% We typeset each line of the verbatim in an \hbox, so we can handle +% tabs. The \global is in case the verbatim line starts with an accent, +% or some other command that starts with a begin-group. Otherwise, the +% entire \verbbox would disappear at the corresponding end-group, before +% it is typeset. Meanwhile, we can't have nested verbatim commands +% (can we?), so the \global won't be overwriting itself. +\newbox\verbbox +\def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} +% +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab + \divide\dimen\verbbox by\tabw + \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw + \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw + \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox + }% + } +\endgroup + +% start the verbatim environment. +\def\setupverbatim{% + \let\nonarrowing = t% + \nonfillstart + \tt % easiest (and conventionally used) font for verbatim + % The \leavevmode here is for blank lines. Otherwise, we would + % never \starttabbox and the \egroup would end verbatim mode. + \def\par{\leavevmode\egroup\box\verbbox\endgraf}% + \tabexpand + \setupmarkupstyle{verbatim}% + % Respect line breaks, + % print special symbols as themselves, and + % make each space count. + % Must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'#1'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. +\endgroup +% +\envdef\verbatim{% + \setupverbatim\doverbatim +} +\let\Everbatim = \afterenvbreak + + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} +% +\def\doverbatiminclude#1{% + {% + \makevalueexpandable + \setupverbatim + {% + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% + \edef\tmp{\noexpand\input #1 } + \expandafter + }\tmp + \afterenvbreak + }% +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is desirable. +% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\copyingtext + \endgroup +} + \message{defuns,} -% Define formatter for defuns -% First, allow user to change definition object font (\df) internally -\def\setdeffont #1 {\csname DEF#1\endcsname} +% @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt -\newskip\deftypemargin \deftypemargin=12pt \newskip\deflastargmargin \deflastargmargin=18pt +\newcount\defunpenalty -\newcount\parencount -% define \functionparens, which makes ( and ) and & do special things. -% \functionparens affects the group it is contained in. +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak + \defunpenalty=10003 % Will keep this @deffn together with the + % following @def command, see below. + \else + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \printdefunline, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + % As a further refinement, we avoid "club" headers by signalling + % with penalty of 10003 after the very first @deffn in the + % sequence (see above), and penalty of 10002 after any following + % @def command. + \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint + \fi + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% + % + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% +} +\def\gobbledefun#1\startdefun{} + +% \printdefunline \deffnheader{text} +% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil\relax + \endgraf + \nobreak\vskip -\parskip + \penalty\defunpenalty % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup +} + +\def\Edefun{\endgraf\medbreak} + +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remaining is to define \deffnheader. +% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp +} + +% \domakedefun \deffn \deffnx \deffnheader { (defn. of \deffnheader) } +% +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. +% +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \doingtypefnfalse % distinguish typed functions from all else + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% +} + +\newif\ifdoingtypefn % doing typed function? +\newif\ifrettypeownline % typeset return type on its own line? + +% @deftypefnnewline on|off says whether the return type of typed functions +% are printed on their own line. This affects @deftypefn, @deftypefun, +% @deftypeop, and @deftypemethod. +% +\parseargdef\deftypefnnewline{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @txideftypefnnl value `\temp', + must be on|off}% + \fi\fi +} + +% \dosubind {index}{topic}{subtopic} +% +% If SUBTOPIC is present, precede it with a space, and call \doind. +% (At some time during the 20th century, this made a two-level entry in an +% index such as the operation index. Nobody seemed to notice the change in +% behaviour though.) +\def\dosubind#1#2#3{% + \def\thirdarg{#3}% + \ifx\thirdarg\empty + \doind{#1}{#2}% + \else + \doind{#1}{#2\space#3}% + \fi +} + +% Untyped functions: + +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} + +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} + +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deffngeneral {subind}category name args +% +\def\deffngeneral#1#2 #3 #4\endheader{% + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +} + +% Typed functions: + +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} + +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} + +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \doingtypefntrue + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +% Typed variables: + +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} + +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} + +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } + +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +% Untyped variables: + +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } + +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} + +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } + +% Types: + +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% +} + +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} + +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. +% +% We are followed by (but not passed) the arguments, if any. +% +\def\defname#1#2#3{% + \par + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % Determine if we are typesetting the return type of a typed function + % on a line by itself. + \rettypeownlinefalse + \ifdoingtypefn % doing a typed function specifically? + % then check user option for putting return type on its own line: + \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else + \rettypeownlinetrue + \fi + \fi + % + % How we'll format the category name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. We'll always have at + % least two. + \tempnum = 2 + % + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % + % If doing a return type on its own line, we'll have another line. + \ifrettypeownline + \advance\tempnum by 1 + \def\maybeshapeline{0in \hsize}% + \else + \def\maybeshapeline{}% + \fi + % + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % + % The final paragraph shape: + \parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2 + % + % Put the category name at the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% text of the return type + \ifx\temp\empty\else + \tclose{\temp}% typeset the return type + \ifrettypeownline + % put return type on its own line; prohibit line break following: + \hfil\vadjust{\nobreak}\break + \else + \space % type on same line, so just followed by a space + \fi + \fi % no return type + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \rmfont + % + \boldbrax + % arguments will be output next, if any. +} + +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. +% +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. We used to recommend @var for that, so + % leave the code in, but it's strange for @var to lead to typewriter. + % Nowadays we recommend @code, since the difference between a ttsl hyphen + % and a tt hyphen is pretty tiny. @code also disables ?` !`. + \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% + #1% + \sl\hyphenchar\font=45 +} + +% We want ()&[] to print specially on the defun line. +% \def\activeparens{% -\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active -\catcode`\[=\active \catcode`\]=\active} + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active +} % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) -{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) - % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. -\global\let(=\lparen \global\let)=\rparen -\global\let[=\lbrack \global\let]=\rbrack +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& -\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } -\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} -% This is used to turn on special parens -% but make & act ordinary (given that it's active). -\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} - -% Definitions of (, ) and & used in args for functions. -% This is the definition of ( outside of all parentheses. -\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested - \global\advance\parencount by 1 + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} } -% -% This is the definition of ( when already inside a level of parens. -\gdef\opnested{\char`\(\global\advance\parencount by 1 } -% -\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. - % also in that case restore the outer-level definition of (. - \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi - \global\advance \parencount by -1 } +\let\ampchar\& + +\newcount\parencount + % If we encounter &foo, then turn on ()-hacking afterwards -\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } -% -\gdef\normalparens{\boldbrax\let&=\ampnr} -} % End of definition inside \activeparens -%% These parens (in \boldbrax) actually are a little bolder than the -%% contained text. This is especially needed for [ and ] -\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } -\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } -\def\ampnr{\&} -\def\lbrb{{\bf\char`\[}} -\def\rbrb{{\bf\char`\]}} +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} -% First, defname, which formats the header line itself. -% #1 should be the function name. -% #2 should be the type of definition, such as "Function". +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi +} +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi +} +\def\bfafterword#1 {#1 \bf} -\def\defname #1#2{% -% Get the values of \leftskip and \rightskip as they were -% outside the @def... -\dimen2=\leftskip -\advance\dimen2 by -\defbodyindent -\noindent -\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% -\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line -\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations -\parshape 2 0in \dimen0 \defargsindent \dimen1 -% Now output arg 2 ("Function" or some such) -% ending at \deftypemargin from the right margin, -% but stuck inside a box of width 0 so it does not interfere with linebreaking -{% Adjust \hsize to exclude the ambient margins, -% so that \rightline will obey them. -\advance \hsize by -\dimen2 -\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}% -% Make all lines underfull and no complaints: -\tolerance=10000 \hbadness=10000 -\advance\leftskip by -\defbodyindent -\exdentamount=\defbodyindent -{\df #1}\enskip % Generate function name +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword +} +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 } -% Actually process the body of a definition -% #1 should be the terminating control sequence, such as \Edefun. -% #2 should be the "another name" control sequence, such as \defunx. -% #3 should be the control sequence that actually processes the header, -% such as \defunheader. - -\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup % -\catcode 61=\active % 61 is `=' -\obeylines\activeparens\spacesplit#3} - -% #1 is the \E... control sequence to end the definition (which we define). -% #2 is the \...x control sequence for consecutive fns (which we define). -% #3 is the control sequence to call to resume processing. -% #4, delimited by the space, is the class name. -% -\def\defmethparsebody#1#2#3#4 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} - -% @deftypemethod has an extra argument that nothing else does. Sigh. -% #1 is the \E... control sequence to end the definition (which we define). -% #2 is the \...x control sequence for consecutive fns (which we define). -% #3 is the control sequence to call to resume processing. -% #4, delimited by the space, is the class name. -% #5 is the method's return type. -% -\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}} - -\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 ##2 {\def#4{##1}% -\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} - -% These parsing functions are similar to the preceding ones -% except that they do not make parens into active characters. -% These are used for "variables" since they have no arguments. - -\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2{\begingroup\obeylines\spacesplit#3}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup % -\catcode 61=\active % -\obeylines\spacesplit#3} - -% This is used for \def{tp,vr}parsebody. It could probably be used for -% some of the others, too, with some judicious conditionals. -% -\def\parsebodycommon#1#2#3{% - \begingroup\inENV % - \medbreak % - % Define the end token that this defining construct specifies - % so that it will exit this group. - \def#1{\endgraf\endgroup\medbreak}% - \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% - \parindent=0in - \advance\leftskip by \defbodyindent - \exdentamount=\defbodyindent - \begingroup\obeylines +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 } -\def\defvrparsebody#1#2#3#4 {% - \parsebodycommon{#1}{#2}{#3}% - \spacesplit{#3{#4}}% +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi } - -% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the -% type is just `struct', because we lose the braces in `{struct -% termios}' when \spacesplit reads its undelimited argument. Sigh. -% \let\deftpparsebody=\defvrparsebody -% -% So, to get around this, we put \empty in with the type name. That -% way, TeX won't find exactly `{...}' as an undelimited argument, and -% won't strip off the braces. -% -\def\deftpparsebody #1#2#3#4 {% - \parsebodycommon{#1}{#2}{#3}% - \spacesplit{\parsetpheaderline{#3{#4}}}\empty +% these should not use \errmessage; the glibc manual, at least, actually +% has such constructs (when documenting function pointers). +\def\badparencount{% + \message{Warning: unbalanced parentheses in @def...}% + \global\parencount=0 } - -% Fine, but then we have to eventually remove the \empty *and* the -% braces (if any). That's what this does. -% -\def\removeemptybraces\empty#1\relax{#1} - -% After \spacesplit has done its work, this is called -- #1 is the final -% thing to call, #2 the type name (which starts with \empty), and #3 -% (which might be empty) the arguments. -% -\def\parsetpheaderline#1#2#3{% - #1{\removeemptybraces#2\relax}{#3}% -}% - -\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 ##2 {\def#4{##1}% -\begingroup\obeylines\spacesplit{#3{##2}}}% -\parindent=0in -\advance\leftskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\spacesplit{#3{#5}}} - -% Split up #2 at the first space token. -% call #1 with two arguments: -% the first is all of #2 before the space token, -% the second is all of #2 after that space token. -% If #2 contains no space token, all of it is passed as the first arg -% and the second is passed as empty. - -{\obeylines -\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% -\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% -\ifx\relax #3% -#1{#2}{}\else #1{#2}{#3#4}\fi}} - -% So much for the things common to all kinds of definitions. - -% Define @defun. - -% First, define the processing that is wanted for arguments of \defun -% Use this to expand the args and terminate the paragraph they make up - -\def\defunargs #1{\functionparens \sl -% Expand, preventing hyphenation at `-' chars. -% Note that groups don't affect changes in \hyphenchar. -\hyphenchar\tensl=0 -#1% -\hyphenchar\tensl=45 -\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% -\interlinepenalty=10000 -\advance\rightskip by 0pt plus 1fil -\endgraf\nobreak\vskip -\parskip\nobreak +\def\badbrackcount{% + \message{Warning: unbalanced square brackets in @def...}% + \global\brackcount=0 } -\def\deftypefunargs #1{% -% Expand, preventing hyphenation at `-' chars. -% Note that groups don't affect changes in \hyphenchar. -% Use \boldbraxnoamp, not \functionparens, so that & is not special. -\boldbraxnoamp -\tclose{#1}% avoid \code because of side effects on active chars -\interlinepenalty=10000 -\advance\rightskip by 0pt plus 1fil -\endgraf\nobreak\vskip -\parskip\nobreak -} - -% Do complete processing of one @defun or @defunx line already parsed. - -% @deffn Command forward-char nchars - -\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} - -\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% -\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defun == @deffn Function - -\def\defun{\defparsebody\Edefun\defunx\defunheader} - -\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Function}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @deftypefun int foobar (int @var{foo}, float @var{bar}) - -\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} - -% #1 is the data type. #2 is the name and args. -\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} -% #1 is the data type, #2 the name, #3 the args. -\def\deftypefunheaderx #1#2 #3\relax{% -\doind {fn}{\code{#2}}% Make entry in function index -\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% -\deftypefunargs {#3}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) - -\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} - -% \defheaderxcond#1\relax$$$ -% puts #1 in @code, followed by a space, but does nothing if #1 is null. -\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} - -% #1 is the classification. #2 is the data type. #3 is the name and args. -\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} -% #1 is the classification, #2 the data type, #3 the name, #4 the args. -\def\deftypefnheaderx #1#2#3 #4\relax{% -\doind {fn}{\code{#3}}% Make entry in function index -\begingroup -\normalparens % notably, turn off `&' magic, which prevents -% at least some C++ text from working -\defname {\defheaderxcond#2\relax$$$#3}{#1}% -\deftypefunargs {#4}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defmac == @deffn Macro - -\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} - -\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Macro}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defspec == @deffn Special Form - -\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} - -\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Special Form}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% This definition is run if you use @defunx -% anywhere other than immediately after a @defun or @defunx. - -\def\deffnx #1 {\errmessage{@deffnx in invalid context}} -\def\defunx #1 {\errmessage{@defunx in invalid context}} -\def\defmacx #1 {\errmessage{@defmacx in invalid context}} -\def\defspecx #1 {\errmessage{@defspecx in invalid context}} -\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} -\def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}} -\def\deftypefunx #1 {\errmessage{@deftypefunx in invalid context}} - -% @defmethod, and so on - -% @defop CATEGORY CLASS OPERATION ARG... - -\def\defop #1 {\def\defoptype{#1}% -\defopparsebody\Edefop\defopx\defopheader\defoptype} - -\def\defopheader #1#2#3{% -\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index -\begingroup\defname {#2}{\defoptype{} on #1}% -\defunargs {#3}\endgroup % -} - -% @deftypemethod CLASS RETURN-TYPE METHOD ARG... -% -\def\deftypemethod{% - \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} -% -% #1 is the class name, #2 the data type, #3 the method name, #4 the args. -\def\deftypemethodheader#1#2#3#4{% - \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index - \begingroup - \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}% - \deftypefunargs{#4}% - \endgroup -} - -% @defmethod == @defop Method -% -\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} -% -% #1 is the class name, #2 the method name, #3 the args. -\def\defmethodheader#1#2#3{% - \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index - \begingroup - \defname{#2}{\putwordMethodon\ \code{#1}}% - \defunargs{#3}% - \endgroup -} - -% @defcv {Class Option} foo-class foo-flag - -\def\defcv #1 {\def\defcvtype{#1}% -\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} - -\def\defcvarheader #1#2#3{% -\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index -\begingroup\defname {#2}{\defcvtype{} of #1}% -\defvarargs {#3}\endgroup % -} - -% @defivar == @defcv {Instance Variable} - -\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} - -\def\defivarheader #1#2#3{% -\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index -\begingroup\defname {#2}{Instance Variable of #1}% -\defvarargs {#3}\endgroup % -} - -% These definitions are run if you use @defmethodx, etc., -% anywhere other than immediately after a @defmethod, etc. - -\def\defopx #1 {\errmessage{@defopx in invalid context}} -\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} -\def\defcvx #1 {\errmessage{@defcvx in invalid context}} -\def\defivarx #1 {\errmessage{@defivarx in invalid context}} - -% Now @defvar - -% First, define the processing that is wanted for arguments of @defvar. -% This is actually simple: just print them in roman. -% This must expand the args and terminate the paragraph they make up -\def\defvarargs #1{\normalparens #1% -\interlinepenalty=10000 -\endgraf\nobreak\vskip -\parskip\nobreak} - -% @defvr Counter foo-count - -\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} - -\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% -\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} - -% @defvar == @defvr Variable - -\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} - -\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index -\begingroup\defname {#1}{Variable}% -\defvarargs {#2}\endgroup % -} - -% @defopt == @defvr {User Option} - -\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} - -\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index -\begingroup\defname {#1}{User Option}% -\defvarargs {#2}\endgroup % -} - -% @deftypevar int foobar - -\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} - -% #1 is the data type. #2 is the name, perhaps followed by text that -% is actually part of the data type, which should not be put into the index. -\def\deftypevarheader #1#2{% -\dovarind#2 \relax% Make entry in variables index -\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% -\interlinepenalty=10000 -\endgraf\nobreak\vskip -\parskip\nobreak -\endgroup} -\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} - -% @deftypevr {Global Flag} int enable - -\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} - -\def\deftypevrheader #1#2#3{\dovarind#3 \relax% -\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} -\interlinepenalty=10000 -\endgraf\nobreak\vskip -\parskip\nobreak -\endgroup} - -% This definition is run if you use @defvarx -% anywhere other than immediately after a @defvar or @defvarx. - -\def\defvrx #1 {\errmessage{@defvrx in invalid context}} -\def\defvarx #1 {\errmessage{@defvarx in invalid context}} -\def\defoptx #1 {\errmessage{@defoptx in invalid context}} -\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} -\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} - -% Now define @deftp -% Args are printed in bold, a slight difference from @defvar. - -\def\deftpargs #1{\bf \defvarargs{#1}} - -% @deftp Class window height width ... - -\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} - -\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% -\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} - -% This definition is run if you use @deftpx, etc -% anywhere other than immediately after a @deftp, etc. - -\def\deftpx #1 {\errmessage{@deftpx in invalid context}} - \message{macros,} % @macro. -% To do this right we need a feature of e-TeX, \scantokens, +% To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. -\ifx\eTeXversion\undefined - \newwrite\macscribble - \def\scanmacro#1{% - \begingroup \newlinechar`\^^M - \immediate\openout\macscribble=\jobname.tmp - \immediate\write\macscribble{#1}% - \immediate\closeout\macscribble - \let\xeatspaces\eatspaces - \input \jobname.tmp - \endgroup -} -\else -\def\scanmacro#1{% -\begingroup \newlinechar`\^^M -\let\xeatspaces\eatspaces\scantokens{#1}\endgroup} +\ifx\eTeXversion\thisisundefined + \newwrite\macscribble + \def\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } \fi +% Used at the time of macro expansion. +% Argument is macro body with arguments substituted +\def\scanmacro#1{% + \newlinechar`\^^M + \def\xeatspaces{\eatspaces}% + % + % Process the macro body under the current catcode regime. + \scantokens{#1@comment}% + % + % The \comment is to remove the \newlinechar added by \scantokens, and + % can be noticed by \parsearg. Note \c isn't used because this means cedilla + % in math mode. +} + +% Used for copying and captions +\def\scanexp#1{% + \expandafter\scanmacro\expandafter{#1}% +} + \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? +% List of all defined macros in the form +% \commondummyword\macro1\commondummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\commondummyword#1}% + \xdef\macrolist{\the\toks0}% +} + % Utility routines. -% Thisdoes \let #1 = #2, except with \csnames. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% \def\cslet#1#2{% -\expandafter\expandafter -\expandafter\let -\expandafter\expandafter -\csname#1\endcsname -\csname#2\endcsname} + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). @@ -4514,7 +8059,7 @@ width0pt\relax} \fi } % Trim a single trailing ^^M off a string. -{\catcode`\^^M=12\catcode`\Q=3% +{\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% @@ -4522,382 +8067,1000 @@ width0pt\relax} \fi % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active -% (as in normal texinfo). It is necessary to change the definition of \. - -% It's necessary to have hard CRs when the macro is executed. This is -% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% (as in normal texinfo). It is necessary to change the definition of \ +% to recognize macro arguments; this is the job of \mbodybackslash. +% +% Non-ASCII encodings make 8-bit characters active, so un-activate +% them to avoid their expansion. Must do this non-globally, to +% confine the change to the current group. +% +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. +% +\def\scanctxt{% used as subroutine + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\~=\other + \passthroughcharstrue +} -\def\macrobodyctxt{% - \catcode`\~=12 - \catcode`\^=12 - \catcode`\_=12 - \catcode`\|=12 - \catcode`\<=12 - \catcode`\>=12 - \catcode`\+=12 - \catcode`\{=12 - \catcode`\}=12 - \catcode`\@=12 - \catcode`\^^M=12 - \usembodybackslash} +\def\scanargctxt{% used for copying and captions, not macros. + \scanctxt + \catcode`\@=\other + \catcode`\\=\other + \catcode`\^^M=\other +} +\def\macrobodyctxt{% used for @macro definitions + \scanctxt + \catcode`\ =\other + \catcode`\@=\other + \catcode`\{=\other + \catcode`\}=\other + \catcode`\^^M=\other + \usembodybackslash +} + +% Used when scanning braced macro arguments. Note, however, that catcode +% changes here are ineffectual if the macro invocation was nested inside +% an argument to another Texinfo command. \def\macroargctxt{% - \catcode`\~=12 - \catcode`\^=12 - \catcode`\_=12 - \catcode`\|=12 - \catcode`\<=12 - \catcode`\>=12 - \catcode`\+=12 - \catcode`\@=12 - \catcode`\\=12} + \scanctxt + \catcode`\ =\active + \catcode`\@=\other + \catcode`\^^M=\other + \catcode`\\=\active +} + +\def\macrolineargctxt{% used for whole-line arguments without braces + \scanctxt + \catcode`\@=\other + \catcode`\{=\other + \catcode`\}=\other +} % \mbodybackslash is the definition of \ in @macro bodies. -% It maps \foo\ => \csname macarg.foo\endcsname => #N +% It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. - +% {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} +\def\margbackslash#1{\char`\#1 } + \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% - \getargs{#1}% now \macname is the macname and \argl the arglist + \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments - \paramno=0% + \paramno=0\relax \else - \expandafter\parsemargdef \argl;% + \expandafter\parsemargdef \argl;% + \if\paramno>256\relax + \ifx\eTeXversion\thisisundefined + \errhelp = \EMsimple + \errmessage{You need eTeX to compile a file with macros with more than 256 arguments} + \fi + \fi \fi - \expandafter\ifx \csname macsave.\the\macname\endcsname \relax - \cslet{macsave.\the\macname}{\the\macname}% - \else + \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + \addtomacrolist{\the\macname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody - \else \expandafter\parsemacbody + \else \expandafter\parsemacbody \fi} -\def\unmacro{\parsearg\unmacroxxx} -\def\unmacroxxx#1{% - \expandafter\ifx \csname macsave.\the\macname\endcsname \relax - \errmessage{Macro \the\macname\ not defined.}% +\parseargdef\unmacro{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\commondummyword\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup \else - \cslet{#1}{macsave.#1}% - \expandafter\let \csname macsave.\the\macname\endcsname \undefined + \errmessage{Macro #1 not defined}% \fi } -% This makes use of the obscure feature that if the last token of a -% is #, then the preceding argument is delimited by -% an opening brace, and that opening brace is not consumed. +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx #1\relax + % remove this + \else + \noexpand\commondummyword \noexpand#1% + \fi +} + +% \getargs -- Parse the arguments to a @macro line. Set \macname to +% the name of the macro, and \argl to the braced argument list. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} -\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacname#1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} +% This made use of the feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. -% Parse the optional {params} list. Set up \paramno and \paramlist -% so \defmacro knows what to do. Define \macarg.blah for each blah -% in the params list, to be ##N where N is the position in that list. -% That gets used by \mbodybackslash (above). - -% We need to get `macro parameter char #' into several definitions. -% The technique used is stolen from LaTeX: let \hash be something -% unexpandable, insert that wherever you need a #, and then redefine -% it to # just before using the token list produced. +% Parse the optional {params} list to @macro or @rmacro. +% Set \paramno to the number of arguments, +% and \paramlist to a parameter text for the macro (e.g. #1,#2,#3 for a +% three-param macro.) Define \macarg.BLAH for each BLAH in the params +% list to some hook where the argument is to be expanded. If there are +% less than 10 arguments that hook is to be replaced by ##N where N +% is the position in that list, that is to say the macro arguments are to be +% defined `a la TeX in the macro body. % -% The same technique is used to protect \eatspaces till just before -% the macro is used. - -\def\parsemargdef#1;{\paramno=0\def\paramlist{}% - \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +% That gets used by \mbodybackslash (above). +% +% If there are 10 or more arguments, a different technique is used: see +% \parsemmanyargdef. +% +\def\parsemargdef#1;{% + \paramno=0\def\paramlist{}% + \let\hash\relax + % \hash is redefined to `#' later to get it into definitions + \let\xeatspaces\relax + \parsemargdefxxx#1,;,% + \ifnum\paramno<10\relax\else + \paramno0\relax + \parsemmanyargdef@@#1,;,% 10 or more arguments + \fi +} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx - \advance\paramno by 1% + \advance\paramno by 1 \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} -% These two commands read recursive and nonrecursive macro bodies. -% (They're different since rec and nonrec macros end differently.) +% \parsemacbody, \parsermacbody +% +% Read recursive and nonrecursive macro bodies. (They're different since +% rec and nonrec macros end differently.) +% +% We are in \macrobodyctxt, and the \xdef causes backslashshes in the macro +% body to be transformed. +% Set \macrobody to the body of the macro, and call \defmacro. +% +{\catcode`\ =\other\long\gdef\parsemacbody#1@end macro{% +\xdef\macrobody{\eatcr{#1}}\endgroup\defmacro}}% +{\catcode`\ =\other\long\gdef\parsermacbody#1@end rmacro{% +\xdef\macrobody{\eatcr{#1}}\endgroup\defmacro}}% -\long\def\parsemacbody#1@end macro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\long\def\parsermacbody#1@end rmacro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +% Make @ a letter, so that we can make private-to-Texinfo macro names. +\edef\texiatcatcode{\the\catcode`\@} +\catcode `@=11\relax -% This defines the macro itself. There are six cases: recursive and -% nonrecursive macros of zero, one, and many arguments. -% Much magic with \expandafter here. +%%%%%%%%%%%%%% Code for > 10 arguments only %%%%%%%%%%%%%%%%%% + +% If there are 10 or more arguments, a different technique is used, where the +% hook remains in the body, and when macro is to be expanded the body is +% processed again to replace the arguments. +% +% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the +% argument N value and then \edef the body (nothing else will expand because of +% the catcode regime under which the body was input). +% +% If you compile with TeX (not eTeX), and you have macros with 10 or more +% arguments, no macro can have more than 256 arguments (else error). +% +% In case that there are 10 or more arguments we parse again the arguments +% list to set new definitions for the \macarg.BLAH macros corresponding to +% each BLAH argument. It was anyhow needed to parse already once this list +% in order to count the arguments, and as macros with at most 9 arguments +% are by far more frequent than macro with 10 or more arguments, defining +% twice the \macarg.BLAH macros does not cost too much processing power. +\def\parsemmanyargdef@@#1,{% + \if#1;\let\next=\relax + \else + \let\next=\parsemmanyargdef@@ + \edef\tempb{\eatspaces{#1}}% + \expandafter\def\expandafter\tempa + \expandafter{\csname macarg.\tempb\endcsname}% + % Note that we need some extra \noexpand\noexpand, this is because we + % don't want \the to be expanded in the \parsermacbody as it uses an + % \xdef . + \expandafter\edef\tempa + {\noexpand\noexpand\noexpand\the\toks\the\paramno}% + \advance\paramno by 1\relax + \fi\next} + + +\let\endargs@\relax +\let\nil@\relax +\def\nilm@{\nil@}% +\long\def\nillm@{\nil@}% + +% This macro is expanded during the Texinfo macro expansion, not during its +% definition. It gets all the arguments' values and assigns them to macros +% macarg.ARGNAME +% +% #1 is the macro name +% #2 is the list of argument names +% #3 is the list of argument values +\def\getargvals@#1#2#3{% + \def\macargdeflist@{}% + \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion. + \def\paramlist{#2,\nil@}% + \def\macroname{#1}% + \begingroup + \macroargctxt + \def\argvaluelist{#3,\nil@}% + \def\@tempa{#3}% + \ifx\@tempa\empty + \setemptyargvalues@ + \else + \getargvals@@ + \fi +} +\def\getargvals@@{% + \ifx\paramlist\nilm@ + % Some sanity check needed here that \argvaluelist is also empty. + \ifx\argvaluelist\nillm@ + \else + \errhelp = \EMsimple + \errmessage{Too many arguments in macro `\macroname'!}% + \fi + \let\next\macargexpandinbody@ + \else + \ifx\argvaluelist\nillm@ + % No more arguments values passed to macro. Set remaining named-arg + % macros to empty. + \let\next\setemptyargvalues@ + \else + % pop current arg name into \@tempb + \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}% + \expandafter\@tempa\expandafter{\paramlist}% + % pop current argument value into \@tempc + \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}% + \expandafter\@tempa\expandafter{\argvaluelist}% + % Here \@tempb is the current arg name and \@tempc is the current arg value. + % First place the new argument macro definition into \@tempd + \expandafter\macname\expandafter{\@tempc}% + \expandafter\let\csname macarg.\@tempb\endcsname\relax + \expandafter\def\expandafter\@tempe\expandafter{% + \csname macarg.\@tempb\endcsname}% + \edef\@tempd{\long\def\@tempe{\the\macname}}% + \push@\@tempd\macargdeflist@ + \let\next\getargvals@@ + \fi + \fi + \next +} + +\def\push@#1#2{% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter#2% + \expandafter\expandafter\expandafter{% + \expandafter#1#2}% +} + +% Replace arguments by their values in the macro body, and place the result +% in macro \@tempa. +% +\def\macvalstoargs@{% + % To do this we use the property that token registers that are \the'ed + % within an \edef expand only once. So we are going to place all argument + % values into respective token registers. + % + % First we save the token context, and initialize argument numbering. + \begingroup + \paramno0\relax + % Then, for each argument number #N, we place the corresponding argument + % value into a new token list register \toks#N + \expandafter\putargsintokens@\saveparamlist@,;,% + % Then, we expand the body so that argument are replaced by their + % values. The trick for values not to be expanded themselves is that they + % are within tokens and that tokens expand only once in an \edef . + \edef\@tempc{\csname mac.\macroname .body\endcsname}% + % Now we restore the token stack pointer to free the token list registers + % which we have used, but we make sure that expanded body is saved after + % group. + \expandafter + \endgroup + \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% + } + +% Define the named-macro outside of this group and then close this group. +% +\def\macargexpandinbody@{% + \expandafter + \endgroup + \macargdeflist@ + % First the replace in body the macro arguments by their values, the result + % is in \@tempa . + \macvalstoargs@ + % Then we point at the \norecurse or \gobble (for recursive) macro value + % with \@tempb . + \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname + % Depending on whether it is recursive or not, we need some tailing + % \egroup . + \ifx\@tempb\gobble + \let\@tempc\relax + \else + \let\@tempc\egroup + \fi + % And now we do the real job: + \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}% + \@tempd +} + +\def\putargsintokens@#1,{% + \if#1;\let\next\relax + \else + \let\next\putargsintokens@ + % First we allocate the new token list register, and give it a temporary + % alias \@tempb . + \toksdef\@tempb\the\paramno + % Then we place the argument value into that token list register. + \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname + \expandafter\@tempb\expandafter{\@tempa}% + \advance\paramno by 1\relax + \fi + \next +} + +% Trailing missing arguments are set to empty. +% +\def\setemptyargvalues@{% + \ifx\paramlist\nilm@ + \let\next\macargexpandinbody@ + \else + \expandafter\setemptyargvaluesparser@\paramlist\endargs@ + \let\next\setemptyargvalues@ + \fi + \next +} + +\def\setemptyargvaluesparser@#1,#2\endargs@{% + \expandafter\def\expandafter\@tempa\expandafter{% + \expandafter\def\csname macarg.#1\endcsname{}}% + \push@\@tempa\macargdeflist@ + \def\paramlist{#2}% +} + +% #1 is the element target macro +% #2 is the list macro +% #3,#4\endargs@ is the list value +\def\pop@#1#2#3,#4\endargs@{% + \def#1{#3}% + \def#2{#4}% +} +\long\def\longpop@#1#2#3,#4\endargs@{% + \long\def#1{#3}% + \long\def#2{#4}% +} + + +%%%%%%%%%%%%%% End of code for > 10 arguments %%%%%%%%%%%%%%%%%% + + +% This defines a Texinfo @macro or @rmacro, called by \parsemacbody. +% \macrobody has the body of the macro in it, with placeholders for +% its parameters, looking like "\xeatspaces{\hash 1}". +% \paramno is the number of parameters +% \paramlist is a TeX parameter text, e.g. "#1,#2,#3," +% There are four cases: macros of zero, one, up to nine, and many arguments. % \xdef is used so that macro definitions will survive the file -% they're defined in; @include reads the file inside a group. +% they're defined in: @include reads the file inside a group. +% \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars - \ifrecursive - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\scanmacro{\temp}}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup\noexpand\scanmacro{\temp}}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname} - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{\egroup\noexpand\scanmacro{\temp}}% - \fi + \ifnum\paramno=1 + \def\xeatspaces##1{##1}% + % This removes the pair of braces around the argument. We don't + % use \eatspaces, because this can cause ends of lines to be lost + % when the argument to \eatspaces is read, leading to line-based + % commands like "@itemize" not being read correctly. \else - \ifcase\paramno - % 0 + \let\xeatspaces\relax % suppress expansion + \fi + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup + \noexpand\spaceisspace + \noexpand\endlineisspace + \noexpand\expandafter % skip any whitespace after the macro name. + \expandafter\noexpand\csname\the\macname @@@\endcsname}% + \expandafter\xdef\csname\the\macname @@@\endcsname{% + \egroup + \noexpand\scanmacro{\macrobody}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname @@@\endcsname}% + \expandafter\xdef\csname\the\macname @@@\endcsname##1{% + \egroup + \noexpand\scanmacro{\macrobody}% + }% + \else % at most 9 + \ifnum\paramno<10\relax + % @MACNAME sets the context for reading the macro argument + % @MACNAME@@ gets the argument, processes backslashes and appends a + % comma. + % @MACNAME@@@ removes braces surrounding the argument list. + % @MACNAME@@@@ scans the macro body with arguments substituted. \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname} - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \csname\the\macname xxx\endcsname ##1,}% + \bgroup + \noexpand\expandafter % This \expandafter skip any spaces after the + \noexpand\macroargctxt % macro before we change the catcode of space. + \noexpand\expandafter + \expandafter\noexpand\csname\the\macname @@\endcsname}% + \expandafter\xdef\csname\the\macname @@\endcsname##1{% + \noexpand\passargtomacro + \expandafter\noexpand\csname\the\macname @@@\endcsname{##1,}}% + \expandafter\xdef\csname\the\macname @@@\endcsname##1{% + \expandafter\noexpand\csname\the\macname @@@@\endcsname ##1}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% + \csname\the\macname @@@@\endcsname\paramlist{% + \egroup\noexpand\scanmacro{\macrobody}}% + \else % 10 or more: + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\macrobody + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble \fi \fi} +\catcode `\@\texiatcatcode\relax % end private-to-Texinfo catcodes + \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} -% \braceorline decides whether the next nonwhitespace character is a -% {. If so it reads up to the closing }, if not, it reads the whole -% line. Whatever was read is then fed to the next control sequence -% as an argument (by \parsebrace or \parsearg) -\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +{\catcode`\@=0 \catcode`\\=13 % We need to manipulate \ so use @ as escape +@catcode`@_=11 % private names +@catcode`@!=11 % used as argument separator + +% \passargtomacro#1#2 - +% Call #1 with a list of tokens #2, with any doubled backslashes in #2 +% compressed to one. +% +% This implementation works by expansion, and not execution (so we cannot use +% \def or similar). This reduces the risk of this failing in contexts where +% complete expansion is done with no execution (for example, in writing out to +% an auxiliary file for an index entry). +% +% State is kept in the input stream: the argument passed to +% @look_ahead, @gobble_and_check_finish and @add_segment is +% +% THE_MACRO ARG_RESULT ! {PENDING_BS} NEXT_TOKEN (... rest of input) +% +% where: +% THE_MACRO - name of the macro we want to call +% ARG_RESULT - argument list we build to pass to that macro +% PENDING_BS - either a backslash or nothing +% NEXT_TOKEN - used to look ahead in the input stream to see what's coming next + +@gdef@passargtomacro#1#2{% + @add_segment #1!{}@relax#2\@_finish\% +} +@gdef@_finish{@_finishx} @global@let@_finishx@relax + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 used to look ahead +% +% If the next token is not a backslash, process the rest of the argument; +% otherwise, remove the next token. +@gdef@look_ahead#1!#2#3#4{% + @ifx#4\% + @expandafter@gobble_and_check_finish + @else + @expandafter@add_segment + @fi#1!{#2}#4#4% +} + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 should be a backslash, which is gobbled. +% #5 looks ahead +% +% Double backslash found. Add a single backslash, and look ahead. +@gdef@gobble_and_check_finish#1!#2#3#4#5{% + @add_segment#1\!{}#5#5% +} + +@gdef@is_fi{@fi} + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 is input stream until next backslash +% +% Input stream is either at the start of the argument, or just after a +% backslash sequence, either a lone backslash, or a doubled backslash. +% NEXT_TOKEN contains the first token in the input stream: if it is \finish, +% finish; otherwise, append to ARG_RESULT the segment of the argument up until +% the next backslash. PENDING_BACKSLASH contains a backslash to represent +% a backslash just before the start of the input stream that has not been +% added to ARG_RESULT. +@gdef@add_segment#1!#2#3#4\{% +@ifx#3@_finish + @call_the_macro#1!% +@else + % append the pending backslash to the result, followed by the next segment + @expandafter@is_fi@look_ahead#1#2#4!{\}@fi + % this @fi is discarded by @look_ahead. + % we can't get rid of it with \expandafter because we don't know how + % long #4 is. +} + +% #1 - THE_MACRO +% #2 - ARG_RESULT +% #3 discards the res of the conditional in @add_segment, and @is_fi ends the +% conditional. +@gdef@call_the_macro#1#2!#3@fi{@is_fi #1{#2}} + +} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% \braceorline MAC is used for a one-argument macro MAC. It checks +% whether the next non-whitespace character is a {. It sets the context +% for reading the argument (slightly different in the two cases). Then, +% to read the argument, in the whole-line case, it then calls the regular +% \parsearg MAC; in the lbrace case, it calls \passargtomacro MAC. +% +\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% - \ifx\nchar\bgroup\else - \expandafter\parsearg - \fi \next} + \ifx\nchar\bgroup + \macroargctxt + \expandafter\passargtomacro + \else + \macrolineargctxt\expandafter\parsearg + \fi \macnamexxx} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Make them active and then expand them all to nothing. +% +\def\alias{\parseargusing\obeyspaces\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} \message{cross references,} -\newwrite\auxfile +\newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} -\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, +\def\inforefzzz #1,#2,#3,#4**{% + \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} -% @node's job is to define \lastnode. -\def\node{\ENVcheck\parsearg\nodezzz} -\def\nodezzz#1{\nodexxx [#1,]} -\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} -\let\nwnode=\node -\let\lastnode=\relax +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}\omittopnode} -% The sectioning commands (@chapter, etc.) call these. -\def\donoderef{% - \ifx\lastnode\relax\else - \expandafter\expandafter\expandafter\setref{\lastnode}% - {Ysectionnumberandtype}% - \global\let\lastnode=\relax - \fi +% Used so that the @top node doesn't have to be wrapped in an @ifnottex +% conditional. +% \doignore goes to more effort to skip nested conditionals but we don't need +% that here. +\def\omittopnode{% + \ifx\lastnode\wordTop + \expandafter\ignorenode\fi } -\def\unnumbnoderef{% - \ifx\lastnode\relax\else - \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% - \global\let\lastnode=\relax - \fi -} -\def\appendixnoderef{% - \ifx\lastnode\relax\else - \expandafter\expandafter\expandafter\setref{\lastnode}% - {Yappendixletterandtype}% - \global\let\lastnode=\relax - \fi +\def\wordTop{Top} + +% Until the next @node or @bye command, divert output to a box that is not +% output. +\def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}% +\ignorenodebye } +{\let\bye\relax +\gdef\ignorenodebye{\let\bye\ignorenodebyedef} +\gdef\ignorenodebyedef{\egroup(`Top' node ignored)\bye}} +% The redefinition of \bye here is because it is declared \outer + +\let\lastnode=\empty + +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty + \fi +} % @anchor{NAME} -- define xref target at arbitrary point. -% -\def\anchor#1{\setref{#1}{Ynothing}} +% +\newcount\savesfregister +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \currentsection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. +% +\def\setref#1#2{% + \pdfmkdest{#1}% + \iflinks + {% + \requireauxfile + \atdummies % preserve commands, but don't expand them + % match definition in \xrdef, \refx, \xrefX. + \def\value##1{##1}% + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\currentsection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout + }% + \fi +} -% \setref{NAME}{SNT} defines a cross-reference point NAME, namely -% NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have -% to set \indexdummies so commands such as @code in a section title -% aren't expanded. It would be nicer not to expand the titles in the -% first place, but there's so many layers that that is hard to do. -% -\def\setref#1#2{{% - \indexdummies - \dosetq{#1-title}{Ytitle}% - \dosetq{#1-pg}{Ypagenumber}% - \dosetq{#1-snt}{#2} -}} +% @xrefautosectiontitle on|off says whether @section(ing) names are used +% automatically in xrefs, if the third arg is not explicitly specified. +% This was provided as a "secret" @set xref-automatic-section-title +% variable, now it's official. +% +\parseargdef\xrefautomaticsectiontitle{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @xrefautomaticsectiontitle value `\temp', + must be on|off}% + \fi\fi +} +% % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % -\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} -\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} -\def\ref#1{\xrefX[#1,,,,,,,]} +\def\pxref{\putwordsee{} \xrefXX} +\def\xref{\putwordSee{} \xrefXX} +\def\ref{\xrefXX} + +\def\xrefXX#1{\def\xrefXXarg{#1}\futurelet\tokenafterxref\xrefXXX} +\def\xrefXXX{\expandafter\xrefX\expandafter[\xrefXXarg,,,,,,,]} +% +\newbox\toprefbox +\newbox\printedrefnamebox +\newbox\infofilenamebox +\newbox\printedmanualbox +% \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + % + % Get args without leading/trailing spaces. + \def\printedrefname{\ignorespaces #3}% + \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% + % + \def\infofilename{\ignorespaces #4}% + \setbox\infofilenamebox = \hbox{\infofilename\unskip}% + % \def\printedmanual{\ignorespaces #5}% - \def\printednodename{\ignorespaces #3}% - \setbox1=\hbox{\printedmanual}% - \setbox0=\hbox{\printednodename}% - \ifdim \wd0 = 0pt + \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% + % + % If the printed reference name (arg #3) was not explicitly given in + % the @xref, figure out what we want to use. + \ifdim \wd\printedrefnamebox = 0pt % No printed node name was explicitly given. - \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax - % Use the node name inside the square brackets. - \def\printednodename{\ignorespaces #1}% + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax + % Not auto section-title: use node name inside the square brackets. + \def\printedrefname{\ignorespaces #1}% \else - % Use the actual chapter/section title appear inside - % the square brackets. Use the real section title if we have it. - \ifdim \wd1 > 0pt - % It is in another manual, so we don't have it. - \def\printednodename{\ignorespaces #1}% + % Auto section-title: use chapter/section title inside + % the square brackets if we have it. + \ifdim \wd\printedmanualbox > 0pt + % It is in another manual, so we don't have it; use node name. + \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs - % We know the real title if we have the xref values. - \def\printednodename{\refx{#1-title}{}}% + % We (should) know the real title if we have the xref values. + \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. - \def\printednodename{\ignorespaces #1}% + \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % - % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not - % insert empty discretionaries after hyphens, which means that it will - % not find a line break at a hyphen in a node names. Since some manuals - % are best written with fairly long node names, containing hyphens, this - % is a loss. Therefore, we give the text of the node name again, so it - % is as if TeX is seeing it for the first time. - \ifdim \wd1 > 0pt - \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% - \else - % _ (for example) has to be the character _ for the purposes of the - % control sequence corresponding to the node, but it has to expand - % into the usual \leavevmode...\vrule stuff for purposes of - % printing. So we \turnoffactive for the \refx-snt, back on for the - % printing, back off for the \refx-pg. - {\normalturnoffactive - % Only output a following space if the -snt ref is nonempty; for - % @unnumbered and @anchor, it won't be. - \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% - \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + % Make link in pdf output. + \ifpdf + % For pdfTeX and LuaTeX + {\indexnofonts + \makevalueexpandable + \turnoffactive + % This expands tokens, so do it after making catcode changes, so _ + % etc. don't get their TeX definitions. This ignores all spaces in + % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % + % This (wrongly) does not take account of leading or trailing + % spaces in #1, which should be ignored. + \setpdfdestname{#1}% + % + \ifx\pdfdestname\empty + \def\pdfdestname{Top}% no empty targets + \fi + % + \leavevmode + \startlink attr{/Border [0 0 0]}% + \ifnum\filenamelength>0 + goto file{\the\filename.pdf} name{\pdfdestname}% + \else + goto name{\pdfmkpgn{\pdfdestname}}% + \fi }% - % [mynode], - [\printednodename],\space - % page 3 - \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \setcolor{\linkcolor}% + \else + \ifx\XeTeXrevision\thisisundefined + \else + % For XeTeX + {\indexnofonts + \makevalueexpandable + \turnoffactive + % This expands tokens, so do it after making catcode changes, so _ + % etc. don't get their TeX definitions. This ignores all spaces in + % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % + % This (wrongly) does not take account of leading or trailing + % spaces in #1, which should be ignored. + \setpdfdestname{#1}% + % + \ifx\pdfdestname\empty + \def\pdfdestname{Top}% no empty targets + \fi + % + \leavevmode + \ifnum\filenamelength>0 + % With default settings, + % XeTeX (xdvipdfmx) replaces link destination names with integers. + % In this case, the replaced destination names of + % remote PDFs are no longer known. In order to avoid a replacement, + % you can use xdvipdfmx's command line option `-C 0x0010'. + % If you use XeTeX 0.99996+ (TeX Live 2016+), + % this command line option is no longer necessary + % because we can use the `dvipdfmx:config' special. + \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A + << /S /GoToR /F (\the\filename.pdf) /D (\pdfdestname) >> >>}% + \else + \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A + << /S /GoTo /D (\pdfdestname) >> >>}% + \fi + }% + \setcolor{\linkcolor}% + \fi \fi + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \def\value##1{##1}% + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". \iffloat distinguishes them by + % \Xthisreftitle being set to a magic string. + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd\printedrefnamebox = 0pt + \refx{#1-snt}{}% + \else + \printedrefname + \fi + % + % If the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd\printedmanualbox > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. + % + % If we use \unhbox to print the node names, TeX does not insert + % empty discretionaries after hyphens, which means that it will not + % find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, + % this is a loss. Therefore, we give the text of the node name + % again, so it is as if TeX is seeing it for the first time. + % + \ifdim \wd\printedmanualbox > 0pt + % Cross-manual reference with a printed manual name. + % + \crossmanualxref{\cite{\printedmanual\unskip}}% + % + \else\ifdim \wd\infofilenamebox > 0pt + % Cross-manual reference with only an info filename (arg 4), no + % printed manual name (arg 5). This is essentially the same as + % the case above; we output the filename, since we have nothing else. + % + \crossmanualxref{\code{\infofilename\unskip}}% + % + \else + % Reference within this manual. + % + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + % + % output the `[mynode]' via the macro below so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + % Add a , if xref followed by a space + \if\space\noexpand\tokenafterxref ,% + \else\ifx\ \tokenafterxref ,% @TAB + \else\ifx\*\tokenafterxref ,% @* + \else\ifx\ \tokenafterxref ,% @SPACE + \else\ifx\ + \tokenafterxref ,% @NL + \else\ifx\tie\tokenafterxref ,% @tie + \fi\fi\fi\fi\fi\fi + \fi\fi + \fi + \endlink \endgroup} -% \dosetq is the interface for calls from other macros - -% Use \normalturnoffactive so that punctuation chars such as underscore -% and backslash work in node names. (\turnoffactive doesn't do \.) -\def\dosetq#1#2{% - {\let\folio=0 - \normalturnoffactive - \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% - \iflinks - \next - \fi - }% +% Output a cross-manual xref to #1. Used just above (twice). +% +% Only include the text "Section ``foo'' in" if the foo is neither +% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply +% "see The Foo Manual", the idea being to refer to the whole manual. +% +% But, this being TeX, we can't easily compare our node name against the +% string "Top" while ignoring the possible spaces before and after in +% the input. By adding the arbitrary 7sp below, we make it much less +% likely that a real node name would have the same width as "Top" (e.g., +% in a monospaced font). Hopefully it will never happen in practice. +% +% For the same basic reason, we retypeset the "Top" at every +% reference, since the current font is indeterminate. +% +\def\crossmanualxref#1{% + \setbox\toprefbox = \hbox{Top\kern7sp}% + \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% + \ifdim \wd2 > 7sp % nonempty? + \ifdim \wd2 = \wd\toprefbox \else % same as Top? + \putwordSection{} ``\printedrefname'' \putwordin{}\space + \fi + \fi + #1% } -% \internalsetq {foo}{page} expands into -% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} -% When the aux file is read, ' is the escape character - -\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} - -% Things to be expanded by \internalsetq - -\def\Ypagenumber{\folio} - -\def\Ytitle{\thissection} - -\def\Ynothing{} - -\def\Ysectionnumberandtype{% -\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % -\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % -\else \ifnum \subsubsecno=0 % -\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % -\else % -\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % -\fi \fi \fi } - -\def\Yappendixletterandtype{% -\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% -\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % -\else \ifnum \subsubsecno=0 % -\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % -\else % -\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % -\fi \fi \fi } - -\gdef\xreftie{'tie} - -% Use TeX 3.0's \inputlineno to get the line number, for better error -% messages, but if we're using an old version of TeX, don't do anything. +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since square brackets don't work well in some documents. Particularly +% one that Bob is working on :). % -\ifx\inputlineno\thisisundefined - \let\linenumber = \empty % Non-3.0. -\else - \def\linenumber{\the\inputlineno:\space} -\fi +\def\xrefprintnodename#1{[#1]} -% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. -% If its value is nonempty, SUFFIX is output afterward. +% Things referred to by \setref. +% +\def\Ynothing{} +\def\Yomitfromtoc{} +\def\Ynumbered{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +\def\Yappendix{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +% \refx{NAME}{SUFFIX} - reference a cross-reference string named NAME. SUFFIX +% is output afterwards if non-empty. \def\refx#1#2{% - \expandafter\ifx\csname X#1\endcsname\relax + \requireauxfile + {% + \indexnofonts + \turnoffactive + \def\value##1{##1}% + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname XR#1\endcsname + }% + \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs - \message{\linenumber Undefined cross reference `#1'.}% + {\toks0 = {#1}% avoid expansion of possibly-complex value + \message{\linenumber Undefined cross reference `\the\toks0'.}}% \else \ifwarnedxrefs\else \global\warnedxrefstrue @@ -4907,22 +9070,84 @@ width0pt\relax} \fi \fi \else % It's defined, so just use it. - \csname X#1\endcsname + \thisrefX \fi #2% Output the suffix in any case. } -% This is the macro invoked by entries in the aux file. -% -\def\xrdef#1{\begingroup - % Reenable \ as an escape while reading the second argument. - \catcode`\\ = 0 - \afterassignment\endgroup - \expandafter\gdef\csname X#1\endcsname +% This is the macro invoked by entries in the aux file. Define a control +% sequence for a cross-reference target (we prepend XR to the control sequence +% name to avoid collisions). The value is the page number. If this is a float +% type, we have more work to do. +% +\def\xrdef#1#2{% + {% Expand the node or anchor name to remove control sequences. + % \turnoffactive stops 8-bit characters being changed to commands + % like @'e. \refx does the same to retrieve the value in the definition. + \indexnofonts + \turnoffactive + \def\value##1{##1}% + \xdef\safexrefname{#1}% + }% + % + \bgroup + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% + \egroup + % We put the \gdef inside a group to avoid the definitions building up on + % TeX's save stack, which can cause it to run out of space for aux files with + % thousands of lines. \gdef doesn't use the save stack, but \csname does + % when it defines an unknown control sequence as \relax. + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR\safexrefname\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 + {\safexrefname}}% + \fi +} + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate at the beginning of the file. +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% Used when writing to the aux file, or when using data from it. +\def\requireauxfile{% + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi + \global\let\requireauxfile=\relax % Only do this once. } % Read the last existing aux file, if any. No error if none exists. -\def\readauxfile{\begingroup +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readdatafile{aux}% + \global\havexrefstrue + \fi + \closein 1 +} + +\def\setupdatafile{% \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other @@ -4950,21 +9175,9 @@ width0pt\relax} \fi \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other - \catcode`\@=\other \catcode`\^=\other - % It was suggested to define this as 7, which would allow ^^e4 etc. - % in xref tags, i.e., node names. But since ^^e4 notation isn't - % supported in the main text, it doesn't seem desirable. Furthermore, - % that is not enough: for node names that actually contain a ^ - % character, we would end up writing a line like this: 'xrdef {'hat - % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first - % argument, and \hat is not an expandable control sequence. It could - % all be worked out, but why? Either we support ^^ or we don't. - % - % The other change necessary for this was to define \auxhat: - % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter - % and then to call \auxhat in \setq. % + % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other @@ -4976,41 +9189,26 @@ width0pt\relax} \fi \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other + \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off - % Make the characters 128-255 be printing characters - {% - \count 1=128 - \def\loop{% - \catcode\count 1=\other - \advance\count 1 by 1 - \ifnum \count 1<256 \loop \fi - }% - }% - % The aux file uses ' as the escape (for now). - % Turn off \ as an escape so we do not lose on - % entries which were dumped with control sequences in their names. - % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ - % Reference to such entries still does not work the way one would wish, - % but at least they do not bomb out when the aux file is read in. + % + \catcode`\\=\active + % + % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 - \catcode`\%=\other - \catcode`\'=0 - \catcode`\\=\other - % - \openin 1 \jobname.aux - \ifeof 1 \else - \closein 1 - \input \jobname.aux - \global\havexrefstrue - \global\warnedobstrue - \fi - % Open the new aux file. TeX will close it automatically at exit. - \openout\auxfile=\jobname.aux + \catcode`\@=0 +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 \endgroup} -% Footnotes. +\message{insertions,} +% including footnotes. \newcount \footnoteno @@ -5021,11 +9219,9 @@ width0pt\relax} \fi % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } -% @footnotestyle is meaningful for info output only. +% @footnotestyle is meaningful for Info output only. \let\footnotestyle=\comment -\let\ptexfootnote=\footnote - {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. @@ -5036,25 +9232,32 @@ width0pt\relax} \fi % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty - \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf - \footnotezzz + \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % -% Oh yes, they do; otherwise, @ifset and anything else that uses -% \parseargline fail inside footnotes because the tokens are fixed when +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % -\long\gdef\footnotezzz{\insert\footins\bgroup +\gdef\dofootnote{% + \insert\footins\bgroup + % + % Nested footnotes are not supported in TeX, that would take a lot + % more work. (\startsavinginserts does not suffice.) + \let\footnote=\errfootnotenest + % % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. + \hsize=\txipagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox @@ -5065,132 +9268,1887 @@ width0pt\relax} \fi \xspaceskip\z@skip \parindent\defaultparindent % - % Hang the footnote text off the number. - \hang + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut + % + % Invoke rest of plain TeX footnote routine. \futurelet\next\fo@t } -\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t - \else\let\next\f@t\fi \next} -\def\f@@t{\bgroup\aftergroup\@foot\let\next} -\def\f@t#1{#1\@foot} -\def\@foot{\strut\egroup} - }%end \catcode `\@=11 -% Set the baselineskip to #1, and the lineskip and strut size -% correspondingly. There is no deep meaning behind these magic numbers -% used as factors; they just match (closely enough) what Knuth defined. -% -\def\lineskipfactor{.08333} -\def\strutheightpercent{.70833} -\def\strutdepthpercent {.29167} -% -\def\setleading#1{% - \normalbaselineskip = #1\relax - \normallineskip = \lineskipfactor\normalbaselineskip - \normalbaselines - \setbox\strutbox =\hbox{% - \vrule width0pt height\strutheightpercent\baselineskip - depth \strutdepthpercent \baselineskip - }% +\def\errfootnotenest{% + \errhelp=\EMsimple + \errmessage{Nested footnotes not supported in texinfo.tex, + even though they work in makeinfo; sorry} } -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% +\def\errfootnoteheading{% + \errhelp=\EMsimple + \errmessage{Footnotes in chapters, sections, etc., are not supported} } -% For a final copy, take out the rectangles -% that mark overfull boxes (in case you have decided -% that the text looks ok even though it passes the margin). +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarly, if a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is finished. +% And the same can be done for other insert classes. --kasal, 16nov03. % -\def\finalout{\overfullrule=0pt} +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi +} + +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. +% +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. -% +% % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else - \closein 1 - % Do not bother showing banner with post-v2.7 epsf.tex (available in - % doc/epsf.tex until it shows up on ctan). + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi +\closein 1 % +% We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get - it from ftp://ftp.tug.org/tex/epsf.tex.} + it from https://ctan.org/texarchive/macros/texinfo/texinfo/doc/epsf.tex.} % -% Only complain once about lack of epsf.tex. \def\image#1{% - \ifx\epsfbox\undefined + \ifx\epsfbox\thisisundefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else - \imagexxx #1,,,\finish + \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. -% #4 is just the usual extra ignored arg for parsing this stuff. -\def\imagexxx#1,#2,#3,#4\finish{% - % \epsfbox itself resets \epsf?size at each figure. - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi - \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + \def\xprocessmacroarg{\eatspaces}% in case we are being used via a macro % If the image is by itself, center it. \ifvmode + \imagevmodetrue + \else \ifx\centersub\centerV + % for @center @image, we need a vbox so we can have our vertical space + \imagevmodetrue + \vbox\bgroup % vbox has better behavior than vtop herev + \fi\fi + % + \ifimagevmode \nobreak\medskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip \nobreak - \centerline{\epsfbox{#1.eps}}% - \bigbreak + \fi + % + % Leave vertical mode so that indentation from an enclosing + % environment such as @quotation is respected. + % However, if we're at the top level, we don't want the + % normal paragraph indentation. + % On the other hand, if we are in the case of @center @image, we don't + % want to start a paragraph, which will create a hsize-width box and + % eradicate the centering. + \ifx\centersub\centerV\else \noindent \fi + % + % Output the image. + \ifpdf + % For pdfTeX and LuaTeX <= 0.80 + \dopdfimage{#1}{#2}{#3}% \else - \epsfbox{#1.eps}% + \ifx\XeTeXrevision\thisisundefined + % For epsf.tex + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \else + % For XeTeX + \doxeteximage{#1}{#2}{#3}% + \fi + \fi + % + \ifimagevmode + \medskip % space after a standalone image + \fi + \ifx\centersub\centerV \egroup \fi +\endgroup} + + +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \currentsection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\currentsection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \requireauxfile + \atdummies + % + \ifx\thisshortcaption\empty + \def\gtemp{\thiscaption}% + \else + \def\gtemp{\thisshortcaption}% + \fi + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \currentsection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup \fi } +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} -\message{paper sizes,} -% And other related parameters. + +\message{localization,} + +% For single-language documents, @documentlanguage is usually given very +% early, just after @documentencoding. Single argument is the language +% (de) or locale (de_DE) abbreviation. +% +{ + \catcode`\_ = \active + \globaldefs=1 +\parseargdef\documentlanguage{% + \tex % read txi-??.tex file in plain TeX. + % Read the file by the name they passed if it exists. + \let_ = \normalunderscore % normal _ character for filename test + \openin 1 txi-#1.tex + \ifeof 1 + \documentlanguagetrywithoutunderscore #1_\finish + \else + \globaldefs = 1 % everything in the txi-LL files needs to persist + \input txi-#1.tex + \fi + \closein 1 + \endgroup % end raw TeX +} +% +% If they passed de_DE, and txi-de_DE.tex doesn't exist, +% try txi-de.tex. +% +\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \globaldefs = 1 % everything in the txi-LL files needs to persist + \input txi-#1.tex + \fi + \closein 1 +} +}% end of special _ catcode +% +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? Putting it in the current +directory should work if nowhere else does.} + +% This macro is called from txi-??.tex files; the first argument is the +% \language name to set (without the "\lang@" prefix), the second and +% third args are \{left,right}hyphenmin. +% +% The language names to pass are determined when the format is built. +% See the etex.log file created at that time, e.g., +% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. +% +% With TeX Live 2008, etex now includes hyphenation patterns for all +% available languages. This means we can support hyphenation in +% Texinfo, at least to some extent. (This still doesn't solve the +% accented characters problem.) +% +\catcode`@=11 +\def\txisetlanguage#1#2#3{% + % do not set the language if the name is undefined in the current TeX. + \expandafter\ifx\csname lang@#1\endcsname \relax + \message{no patterns for #1}% + \else + \global\language = \csname lang@#1\endcsname + \fi + % but there is no harm in adjusting the hyphenmin values regardless. + \global\lefthyphenmin = #2\relax + \global\righthyphenmin = #3\relax +} + +% XeTeX and LuaTeX can handle Unicode natively. +% Their default I/O uses UTF-8 sequences instead of a byte-wise operation. +% Other TeX engines' I/O (pdfTeX, etc.) is byte-wise. +% +\newif\iftxinativeunicodecapable +\newif\iftxiusebytewiseio + +\ifx\XeTeXrevision\thisisundefined + \ifx\luatexversion\thisisundefined + \txinativeunicodecapablefalse + \txiusebytewiseiotrue + \else + \txinativeunicodecapabletrue + \txiusebytewiseiofalse + \fi +\else + \txinativeunicodecapabletrue + \txiusebytewiseiofalse +\fi + +% Set I/O by bytes instead of UTF-8 sequence for XeTeX and LuaTex +% for non-UTF-8 (byte-wise) encodings. +% +\def\setbytewiseio{% + \ifx\XeTeXrevision\thisisundefined + \else + \XeTeXdefaultencoding "bytes" % For subsequent files to be read + \XeTeXinputencoding "bytes" % For document root file + % Unfortunately, there seems to be no corresponding XeTeX command for + % output encoding. This is a problem for auxiliary index and TOC files. + % The only solution would be perhaps to write out @U{...} sequences in + % place of non-ASCII characters. + \fi + + \ifx\luatexversion\thisisundefined + \else + \directlua{ + local utf8_char, byte, gsub = unicode.utf8.char, string.byte, string.gsub + local function convert_char (char) + return utf8_char(byte(char)) + end + + local function convert_line (line) + return gsub(line, ".", convert_char) + end + + callback.register("process_input_buffer", convert_line) + + local function convert_line_out (line) + local line_out = "" + for c in string.utfvalues(line) do + line_out = line_out .. string.char(c) + end + return line_out + end + + callback.register("process_output_buffer", convert_line_out) + } + \fi + + \txiusebytewiseiotrue +} + + +% Helpers for encodings. +% Set the catcode of characters 128 through 255 to the specified number. +% +\def\setnonasciicharscatcode#1{% + \count255=128 + \loop\ifnum\count255<256 + \global\catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +\def\setnonasciicharscatcodenonglobal#1{% + \count255=128 + \loop\ifnum\count255<256 + \catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +% @documentencoding sets the definition of non-ASCII characters +% according to the specified encoding. +% +\def\documentencoding{\parseargusing\filenamecatcodes\documentencodingzzz} +\def\documentencodingzzz#1{% + % + % Encoding being declared for the document. + \def\declaredencoding{\csname #1.enc\endcsname}% + % + % Supported encodings: names converted to tokens in order to be able + % to compare them with \ifx. + \def\ascii{\csname US-ASCII.enc\endcsname}% + \def\latnine{\csname ISO-8859-15.enc\endcsname}% + \def\latone{\csname ISO-8859-1.enc\endcsname}% + \def\lattwo{\csname ISO-8859-2.enc\endcsname}% + \def\utfeight{\csname UTF-8.enc\endcsname}% + % + \ifx \declaredencoding \ascii + \asciichardefs + % + \else \ifx \declaredencoding \lattwo + \iftxinativeunicodecapable + \setbytewiseio + \fi + \setnonasciicharscatcode\active + \lattwochardefs + % + \else \ifx \declaredencoding \latone + \iftxinativeunicodecapable + \setbytewiseio + \fi + \setnonasciicharscatcode\active + \latonechardefs + % + \else \ifx \declaredencoding \latnine + \iftxinativeunicodecapable + \setbytewiseio + \fi + \setnonasciicharscatcode\active + \latninechardefs + % + \else \ifx \declaredencoding \utfeight + \iftxinativeunicodecapable + % For native Unicode handling (XeTeX and LuaTeX) + \nativeunicodechardefs + \else + % For treating UTF-8 as byte sequences (TeX, eTeX and pdfTeX) + \setnonasciicharscatcode\active + % since we already invoked \utfeightchardefs at the top level + % (below), do not re-invoke it, otherwise our check for duplicated + % definitions gets triggered. Making non-ascii chars active is + % sufficient. + \fi + % + \else + \message{Ignoring unknown document encoding: #1.}% + % + \fi % utfeight + \fi % latnine + \fi % latone + \fi % lattwo + \fi % ascii + % + \ifx\XeTeXrevision\thisisundefined + \else + \ifx \declaredencoding \utfeight + \else + \ifx \declaredencoding \ascii + \else + \message{Warning: XeTeX with non-UTF-8 encodings cannot handle % + non-ASCII characters in auxiliary files.}% + \fi + \fi + \fi +} + +% emacs-page +% A message to be logged when using a character that isn't available +% the default font encoding (OT1). +% +\def\missingcharmsg#1{\message{Character missing, sorry: #1.}} + +% Take account of \c (plain) vs. \, (Texinfo) difference. +\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} + +% First, make active non-ASCII characters in order for them to be +% correctly categorized when TeX reads the replacement text of +% macros containing the character definitions. +\setnonasciicharscatcode\active +% + +\def\gdefchar#1#2{% +\gdef#1{% + \ifpassthroughchars + \string#1% + \else + #2% + \fi +}} + +% Latin1 (ISO-8859-1) character definitions. +\def\latonechardefs{% + \gdefchar^^a0{\tie} + \gdefchar^^a1{\exclamdown} + \gdefchar^^a2{{\tcfont \char162}} % cent + \gdefchar^^a3{\pounds{}} + \gdefchar^^a4{{\tcfont \char164}} % currency + \gdefchar^^a5{{\tcfont \char165}} % yen + \gdefchar^^a6{{\tcfont \char166}} % broken bar + \gdefchar^^a7{\S} + \gdefchar^^a8{\"{}} + \gdefchar^^a9{\copyright{}} + \gdefchar^^aa{\ordf} + \gdefchar^^ab{\guillemetleft{}} + \gdefchar^^ac{\ensuremath\lnot} + \gdefchar^^ad{\-} + \gdefchar^^ae{\registeredsymbol{}} + \gdefchar^^af{\={}} + % + \gdefchar^^b0{\textdegree} + \gdefchar^^b1{$\pm$} + \gdefchar^^b2{$^2$} + \gdefchar^^b3{$^3$} + \gdefchar^^b4{\'{}} + \gdefchar^^b5{$\mu$} + \gdefchar^^b6{\P} + \gdefchar^^b7{\ensuremath\cdot} + \gdefchar^^b8{\cedilla\ } + \gdefchar^^b9{$^1$} + \gdefchar^^ba{\ordm} + \gdefchar^^bb{\guillemetright{}} + \gdefchar^^bc{$1\over4$} + \gdefchar^^bd{$1\over2$} + \gdefchar^^be{$3\over4$} + \gdefchar^^bf{\questiondown} + % + \gdefchar^^c0{\`A} + \gdefchar^^c1{\'A} + \gdefchar^^c2{\^A} + \gdefchar^^c3{\~A} + \gdefchar^^c4{\"A} + \gdefchar^^c5{\ringaccent A} + \gdefchar^^c6{\AE} + \gdefchar^^c7{\cedilla C} + \gdefchar^^c8{\`E} + \gdefchar^^c9{\'E} + \gdefchar^^ca{\^E} + \gdefchar^^cb{\"E} + \gdefchar^^cc{\`I} + \gdefchar^^cd{\'I} + \gdefchar^^ce{\^I} + \gdefchar^^cf{\"I} + % + \gdefchar^^d0{\DH} + \gdefchar^^d1{\~N} + \gdefchar^^d2{\`O} + \gdefchar^^d3{\'O} + \gdefchar^^d4{\^O} + \gdefchar^^d5{\~O} + \gdefchar^^d6{\"O} + \gdefchar^^d7{$\times$} + \gdefchar^^d8{\O} + \gdefchar^^d9{\`U} + \gdefchar^^da{\'U} + \gdefchar^^db{\^U} + \gdefchar^^dc{\"U} + \gdefchar^^dd{\'Y} + \gdefchar^^de{\TH} + \gdefchar^^df{\ss} + % + \gdefchar^^e0{\`a} + \gdefchar^^e1{\'a} + \gdefchar^^e2{\^a} + \gdefchar^^e3{\~a} + \gdefchar^^e4{\"a} + \gdefchar^^e5{\ringaccent a} + \gdefchar^^e6{\ae} + \gdefchar^^e7{\cedilla c} + \gdefchar^^e8{\`e} + \gdefchar^^e9{\'e} + \gdefchar^^ea{\^e} + \gdefchar^^eb{\"e} + \gdefchar^^ec{\`{\dotless i}} + \gdefchar^^ed{\'{\dotless i}} + \gdefchar^^ee{\^{\dotless i}} + \gdefchar^^ef{\"{\dotless i}} + % + \gdefchar^^f0{\dh} + \gdefchar^^f1{\~n} + \gdefchar^^f2{\`o} + \gdefchar^^f3{\'o} + \gdefchar^^f4{\^o} + \gdefchar^^f5{\~o} + \gdefchar^^f6{\"o} + \gdefchar^^f7{$\div$} + \gdefchar^^f8{\o} + \gdefchar^^f9{\`u} + \gdefchar^^fa{\'u} + \gdefchar^^fb{\^u} + \gdefchar^^fc{\"u} + \gdefchar^^fd{\'y} + \gdefchar^^fe{\th} + \gdefchar^^ff{\"y} +} + +% Latin9 (ISO-8859-15) encoding character definitions. +\def\latninechardefs{% + % Encoding is almost identical to Latin1. + \latonechardefs + % + \gdefchar^^a4{\euro{}} + \gdefchar^^a6{\v S} + \gdefchar^^a8{\v s} + \gdefchar^^b4{\v Z} + \gdefchar^^b8{\v z} + \gdefchar^^bc{\OE} + \gdefchar^^bd{\oe} + \gdefchar^^be{\"Y} +} + +% Latin2 (ISO-8859-2) character definitions. +\def\lattwochardefs{% + \gdefchar^^a0{\tie} + \gdefchar^^a1{\ogonek{A}} + \gdefchar^^a2{\u{}} + \gdefchar^^a3{\L} + \gdefchar^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdefchar^^a5{\v L} + \gdefchar^^a6{\'S} + \gdefchar^^a7{\S} + \gdefchar^^a8{\"{}} + \gdefchar^^a9{\v S} + \gdefchar^^aa{\cedilla S} + \gdefchar^^ab{\v T} + \gdefchar^^ac{\'Z} + \gdefchar^^ad{\-} + \gdefchar^^ae{\v Z} + \gdefchar^^af{\dotaccent Z} + % + \gdefchar^^b0{\textdegree{}} + \gdefchar^^b1{\ogonek{a}} + \gdefchar^^b2{\ogonek{ }} + \gdefchar^^b3{\l} + \gdefchar^^b4{\'{}} + \gdefchar^^b5{\v l} + \gdefchar^^b6{\'s} + \gdefchar^^b7{\v{}} + \gdefchar^^b8{\cedilla\ } + \gdefchar^^b9{\v s} + \gdefchar^^ba{\cedilla s} + \gdefchar^^bb{\v t} + \gdefchar^^bc{\'z} + \gdefchar^^bd{\H{}} + \gdefchar^^be{\v z} + \gdefchar^^bf{\dotaccent z} + % + \gdefchar^^c0{\'R} + \gdefchar^^c1{\'A} + \gdefchar^^c2{\^A} + \gdefchar^^c3{\u A} + \gdefchar^^c4{\"A} + \gdefchar^^c5{\'L} + \gdefchar^^c6{\'C} + \gdefchar^^c7{\cedilla C} + \gdefchar^^c8{\v C} + \gdefchar^^c9{\'E} + \gdefchar^^ca{\ogonek{E}} + \gdefchar^^cb{\"E} + \gdefchar^^cc{\v E} + \gdefchar^^cd{\'I} + \gdefchar^^ce{\^I} + \gdefchar^^cf{\v D} + % + \gdefchar^^d0{\DH} + \gdefchar^^d1{\'N} + \gdefchar^^d2{\v N} + \gdefchar^^d3{\'O} + \gdefchar^^d4{\^O} + \gdefchar^^d5{\H O} + \gdefchar^^d6{\"O} + \gdefchar^^d7{$\times$} + \gdefchar^^d8{\v R} + \gdefchar^^d9{\ringaccent U} + \gdefchar^^da{\'U} + \gdefchar^^db{\H U} + \gdefchar^^dc{\"U} + \gdefchar^^dd{\'Y} + \gdefchar^^de{\cedilla T} + \gdefchar^^df{\ss} + % + \gdefchar^^e0{\'r} + \gdefchar^^e1{\'a} + \gdefchar^^e2{\^a} + \gdefchar^^e3{\u a} + \gdefchar^^e4{\"a} + \gdefchar^^e5{\'l} + \gdefchar^^e6{\'c} + \gdefchar^^e7{\cedilla c} + \gdefchar^^e8{\v c} + \gdefchar^^e9{\'e} + \gdefchar^^ea{\ogonek{e}} + \gdefchar^^eb{\"e} + \gdefchar^^ec{\v e} + \gdefchar^^ed{\'{\dotless{i}}} + \gdefchar^^ee{\^{\dotless{i}}} + \gdefchar^^ef{\v d} + % + \gdefchar^^f0{\dh} + \gdefchar^^f1{\'n} + \gdefchar^^f2{\v n} + \gdefchar^^f3{\'o} + \gdefchar^^f4{\^o} + \gdefchar^^f5{\H o} + \gdefchar^^f6{\"o} + \gdefchar^^f7{$\div$} + \gdefchar^^f8{\v r} + \gdefchar^^f9{\ringaccent u} + \gdefchar^^fa{\'u} + \gdefchar^^fb{\H u} + \gdefchar^^fc{\"u} + \gdefchar^^fd{\'y} + \gdefchar^^fe{\cedilla t} + \gdefchar^^ff{\dotaccent{}} +} + +% UTF-8 character definitions. +% +% This code to support UTF-8 is based on LaTeX's utf8.def, with some +% changes for Texinfo conventions. It is included here under the GPL by +% permission from Frank Mittelbach and the LaTeX team. +% +\newcount\countUTFx +\newcount\countUTFy +\newcount\countUTFz + +\gdef\UTFviiiTwoOctets#1#2{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\endcsname} +% +\gdef\UTFviiiThreeOctets#1#2#3{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} +% +\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} + +\gdef\UTFviiiDefined#1{% + \ifx #1\relax + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \else + \expandafter #1% + \fi +} + +% Give non-ASCII bytes the active definitions for processing UTF-8 sequences +\begingroup + \catcode`\~13 + \catcode`\$12 + \catcode`\"12 + + % Loop from \countUTFx to \countUTFy, performing \UTFviiiTmp + % substituting ~ and $ with a character token of that value. + \def\UTFviiiLoop{% + \global\catcode\countUTFx\active + \uccode`\~\countUTFx + \uccode`\$\countUTFx + \uppercase\expandafter{\UTFviiiTmp}% + \advance\countUTFx by 1 + \ifnum\countUTFx < \countUTFy + \expandafter\UTFviiiLoop + \fi} + + % For bytes other than the first in a UTF-8 sequence. Not expected to + % be expanded except when writing to auxiliary files. + \countUTFx = "80 + \countUTFy = "C2 + \def\UTFviiiTmp{% + \gdef~{% + \ifpassthroughchars $\fi}}% + \UTFviiiLoop + + \countUTFx = "C2 + \countUTFy = "E0 + \def\UTFviiiTmp{% + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}% + \UTFviiiLoop + + \countUTFx = "E0 + \countUTFy = "F0 + \def\UTFviiiTmp{% + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}% + \UTFviiiLoop + + \countUTFx = "F0 + \countUTFy = "F4 + \def\UTFviiiTmp{% + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiFourOctets\expandafter$\fi + }}% + \UTFviiiLoop +\endgroup + +\def\globallet{\global\let} % save some \expandafter's below + +% @U{xxxx} to produce U+xxxx, if we support it. +\def\U#1{% + \expandafter\ifx\csname uni:#1\endcsname \relax + \iftxinativeunicodecapable + % All Unicode characters can be used if native Unicode handling is + % active. However, if the font does not have the glyph, + % letters are missing. + \begingroup + \uccode`\.="#1\relax + \uppercase{.} + \endgroup + \else + \errhelp = \EMsimple + \errmessage{Unicode character U+#1 not supported, sorry}% + \fi + \else + \csname uni:#1\endcsname + \fi +} + +% These macros are used here to construct the name of a control +% sequence to be defined. +\def\UTFviiiTwoOctetsName#1#2{% + \csname u8:#1\string #2\endcsname}% +\def\UTFviiiThreeOctetsName#1#2#3{% + \csname u8:#1\string #2\string #3\endcsname}% +\def\UTFviiiFourOctetsName#1#2#3#4{% + \csname u8:#1\string #2\string #3\string #4\endcsname}% + +% For UTF-8 byte sequences (TeX, e-TeX and pdfTeX), +% provide a definition macro to replace a Unicode character; +% this gets used by the @U command +% +\begingroup + \catcode`\"=12 + \catcode`\<=12 + \catcode`\.=12 + \catcode`\,=12 + \catcode`\;=12 + \catcode`\!=12 + \catcode`\~=13 + \gdef\DeclareUnicodeCharacterUTFviii#1#2{% + \countUTFz = "#1\relax + \begingroup + \parseXMLCharref + + % Give \u8:... its definition. The sequence of seven \expandafter's + % expands after the \gdef three times, e.g. + % + % 1. \UTFviiTwoOctetsName B1 B2 + % 2. \csname u8:B1 \string B2 \endcsname + % 3. \u8: B1 B2 (a single control sequence token) + % + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\gdef \UTFviiiTmp{#2}% + % + \expandafter\ifx\csname uni:#1\endcsname \relax \else + \message{Internal error, already defined: #1}% + \fi + % + % define an additional control sequence for this code point. + \expandafter\globallet\csname uni:#1\endcsname \UTFviiiTmp + \endgroup} + % + % Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp + % to the corresponding UTF-8 sequence. + \gdef\parseXMLCharref{% + \ifnum\countUTFz < "A0\relax + \errhelp = \EMsimple + \errmessage{Cannot define Unicode char value < 00A0}% + \else\ifnum\countUTFz < "800\relax + \parseUTFviiiA,% + \parseUTFviiiB C\UTFviiiTwoOctetsName.,% + \else\ifnum\countUTFz < "10000\relax + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiB E\UTFviiiThreeOctetsName.{,;}% + \else + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiA!% + \parseUTFviiiB F\UTFviiiFourOctetsName.{!,;}% + \fi\fi\fi + } + + % Extract a byte from the end of the UTF-8 representation of \countUTFx. + % It must be a non-initial byte in the sequence. + % Change \uccode of #1 for it to be used in \parseUTFviiiB as one + % of the bytes. + \gdef\parseUTFviiiA#1{% + \countUTFx = \countUTFz + \divide\countUTFz by 64 + \countUTFy = \countUTFz % Save to be the future value of \countUTFz. + \multiply\countUTFz by 64 + + % \countUTFz is now \countUTFx with the last 5 bits cleared. Subtract + % in order to get the last five bits. + \advance\countUTFx by -\countUTFz + + % Convert this to the byte in the UTF-8 sequence. + \advance\countUTFx by 128 + \uccode `#1\countUTFx + \countUTFz = \countUTFy} + + % Used to put a UTF-8 byte sequence into \UTFviiiTmp + % #1 is the increment for \countUTFz to yield a the first byte of the UTF-8 + % sequence. + % #2 is one of the \UTFviii*OctetsName macros. + % #3 is always a full stop (.) + % #4 is a template for the other bytes in the sequence. The values for these + % bytes is substituted in here with \uppercase using the \uccode's. + \gdef\parseUTFviiiB#1#2#3#4{% + \advance\countUTFz by "#10\relax + \uccode `#3\countUTFz + \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} +\endgroup + +% For native Unicode handling (XeTeX and LuaTeX), +% provide a definition macro that sets a catcode to `other' non-globally +% +\def\DeclareUnicodeCharacterNativeOther#1#2{% + \catcode"#1=\other +} + +% https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_M +% U+0000..U+007F = https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block) +% U+0080..U+00FF = https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block) +% U+0100..U+017F = https://en.wikipedia.org/wiki/Latin_Extended-A +% U+0180..U+024F = https://en.wikipedia.org/wiki/Latin_Extended-B +% +% Many of our renditions are less than wonderful, and all the missing +% characters are available somewhere. Loading the necessary fonts +% awaits user request. We can't truly support Unicode without +% reimplementing everything that's been done in LaTeX for many years, +% plus probably using luatex or xetex, and who knows what else. +% We won't be doing that here in this simple file. But we can try to at +% least make most of the characters not bomb out. +% +\def\unicodechardefs{% + \DeclareUnicodeCharacter{00A0}{\tie}% + \DeclareUnicodeCharacter{00A1}{\exclamdown}% + \DeclareUnicodeCharacter{00A2}{{\tcfont \char162}}% 0242=cent + \DeclareUnicodeCharacter{00A3}{\pounds{}}% + \DeclareUnicodeCharacter{00A4}{{\tcfont \char164}}% 0244=currency + \DeclareUnicodeCharacter{00A5}{{\tcfont \char165}}% 0245=yen + \DeclareUnicodeCharacter{00A6}{{\tcfont \char166}}% 0246=brokenbar + \DeclareUnicodeCharacter{00A7}{\S}% + \DeclareUnicodeCharacter{00A8}{\"{ }}% + \DeclareUnicodeCharacter{00A9}{\copyright{}}% + \DeclareUnicodeCharacter{00AA}{\ordf}% + \DeclareUnicodeCharacter{00AB}{\guillemetleft{}}% + \DeclareUnicodeCharacter{00AC}{\ensuremath\lnot}% + \DeclareUnicodeCharacter{00AD}{\-}% + \DeclareUnicodeCharacter{00AE}{\registeredsymbol{}}% + \DeclareUnicodeCharacter{00AF}{\={ }}% + % + \DeclareUnicodeCharacter{00B0}{\ringaccent{ }}% + \DeclareUnicodeCharacter{00B1}{\ensuremath\pm}% + \DeclareUnicodeCharacter{00B2}{$^2$}% + \DeclareUnicodeCharacter{00B3}{$^3$}% + \DeclareUnicodeCharacter{00B4}{\'{ }}% + \DeclareUnicodeCharacter{00B5}{$\mu$}% + \DeclareUnicodeCharacter{00B6}{\P}% + \DeclareUnicodeCharacter{00B7}{\ensuremath\cdot}% + \DeclareUnicodeCharacter{00B8}{\cedilla{ }}% + \DeclareUnicodeCharacter{00B9}{$^1$}% + \DeclareUnicodeCharacter{00BA}{\ordm}% + \DeclareUnicodeCharacter{00BB}{\guillemetright{}}% + \DeclareUnicodeCharacter{00BC}{$1\over4$}% + \DeclareUnicodeCharacter{00BD}{$1\over2$}% + \DeclareUnicodeCharacter{00BE}{$3\over4$}% + \DeclareUnicodeCharacter{00BF}{\questiondown}% + % + \DeclareUnicodeCharacter{00C0}{\`A}% + \DeclareUnicodeCharacter{00C1}{\'A}% + \DeclareUnicodeCharacter{00C2}{\^A}% + \DeclareUnicodeCharacter{00C3}{\~A}% + \DeclareUnicodeCharacter{00C4}{\"A}% + \DeclareUnicodeCharacter{00C5}{\AA}% + \DeclareUnicodeCharacter{00C6}{\AE}% + \DeclareUnicodeCharacter{00C7}{\cedilla{C}}% + \DeclareUnicodeCharacter{00C8}{\`E}% + \DeclareUnicodeCharacter{00C9}{\'E}% + \DeclareUnicodeCharacter{00CA}{\^E}% + \DeclareUnicodeCharacter{00CB}{\"E}% + \DeclareUnicodeCharacter{00CC}{\`I}% + \DeclareUnicodeCharacter{00CD}{\'I}% + \DeclareUnicodeCharacter{00CE}{\^I}% + \DeclareUnicodeCharacter{00CF}{\"I}% + % + \DeclareUnicodeCharacter{00D0}{\DH}% + \DeclareUnicodeCharacter{00D1}{\~N}% + \DeclareUnicodeCharacter{00D2}{\`O}% + \DeclareUnicodeCharacter{00D3}{\'O}% + \DeclareUnicodeCharacter{00D4}{\^O}% + \DeclareUnicodeCharacter{00D5}{\~O}% + \DeclareUnicodeCharacter{00D6}{\"O}% + \DeclareUnicodeCharacter{00D7}{\ensuremath\times}% + \DeclareUnicodeCharacter{00D8}{\O}% + \DeclareUnicodeCharacter{00D9}{\`U}% + \DeclareUnicodeCharacter{00DA}{\'U}% + \DeclareUnicodeCharacter{00DB}{\^U}% + \DeclareUnicodeCharacter{00DC}{\"U}% + \DeclareUnicodeCharacter{00DD}{\'Y}% + \DeclareUnicodeCharacter{00DE}{\TH}% + \DeclareUnicodeCharacter{00DF}{\ss}% + % + \DeclareUnicodeCharacter{00E0}{\`a}% + \DeclareUnicodeCharacter{00E1}{\'a}% + \DeclareUnicodeCharacter{00E2}{\^a}% + \DeclareUnicodeCharacter{00E3}{\~a}% + \DeclareUnicodeCharacter{00E4}{\"a}% + \DeclareUnicodeCharacter{00E5}{\aa}% + \DeclareUnicodeCharacter{00E6}{\ae}% + \DeclareUnicodeCharacter{00E7}{\cedilla{c}}% + \DeclareUnicodeCharacter{00E8}{\`e}% + \DeclareUnicodeCharacter{00E9}{\'e}% + \DeclareUnicodeCharacter{00EA}{\^e}% + \DeclareUnicodeCharacter{00EB}{\"e}% + \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}% + \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}% + \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}% + \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}% + % + \DeclareUnicodeCharacter{00F0}{\dh}% + \DeclareUnicodeCharacter{00F1}{\~n}% + \DeclareUnicodeCharacter{00F2}{\`o}% + \DeclareUnicodeCharacter{00F3}{\'o}% + \DeclareUnicodeCharacter{00F4}{\^o}% + \DeclareUnicodeCharacter{00F5}{\~o}% + \DeclareUnicodeCharacter{00F6}{\"o}% + \DeclareUnicodeCharacter{00F7}{\ensuremath\div}% + \DeclareUnicodeCharacter{00F8}{\o}% + \DeclareUnicodeCharacter{00F9}{\`u}% + \DeclareUnicodeCharacter{00FA}{\'u}% + \DeclareUnicodeCharacter{00FB}{\^u}% + \DeclareUnicodeCharacter{00FC}{\"u}% + \DeclareUnicodeCharacter{00FD}{\'y}% + \DeclareUnicodeCharacter{00FE}{\th}% + \DeclareUnicodeCharacter{00FF}{\"y}% + % + \DeclareUnicodeCharacter{0100}{\=A}% + \DeclareUnicodeCharacter{0101}{\=a}% + \DeclareUnicodeCharacter{0102}{\u{A}}% + \DeclareUnicodeCharacter{0103}{\u{a}}% + \DeclareUnicodeCharacter{0104}{\ogonek{A}}% + \DeclareUnicodeCharacter{0105}{\ogonek{a}}% + \DeclareUnicodeCharacter{0106}{\'C}% + \DeclareUnicodeCharacter{0107}{\'c}% + \DeclareUnicodeCharacter{0108}{\^C}% + \DeclareUnicodeCharacter{0109}{\^c}% + \DeclareUnicodeCharacter{010A}{\dotaccent{C}}% + \DeclareUnicodeCharacter{010B}{\dotaccent{c}}% + \DeclareUnicodeCharacter{010C}{\v{C}}% + \DeclareUnicodeCharacter{010D}{\v{c}}% + \DeclareUnicodeCharacter{010E}{\v{D}}% + \DeclareUnicodeCharacter{010F}{d'}% + % + \DeclareUnicodeCharacter{0110}{\DH}% + \DeclareUnicodeCharacter{0111}{\dh}% + \DeclareUnicodeCharacter{0112}{\=E}% + \DeclareUnicodeCharacter{0113}{\=e}% + \DeclareUnicodeCharacter{0114}{\u{E}}% + \DeclareUnicodeCharacter{0115}{\u{e}}% + \DeclareUnicodeCharacter{0116}{\dotaccent{E}}% + \DeclareUnicodeCharacter{0117}{\dotaccent{e}}% + \DeclareUnicodeCharacter{0118}{\ogonek{E}}% + \DeclareUnicodeCharacter{0119}{\ogonek{e}}% + \DeclareUnicodeCharacter{011A}{\v{E}}% + \DeclareUnicodeCharacter{011B}{\v{e}}% + \DeclareUnicodeCharacter{011C}{\^G}% + \DeclareUnicodeCharacter{011D}{\^g}% + \DeclareUnicodeCharacter{011E}{\u{G}}% + \DeclareUnicodeCharacter{011F}{\u{g}}% + % + \DeclareUnicodeCharacter{0120}{\dotaccent{G}}% + \DeclareUnicodeCharacter{0121}{\dotaccent{g}}% + \DeclareUnicodeCharacter{0122}{\cedilla{G}}% + \DeclareUnicodeCharacter{0123}{\cedilla{g}}% + \DeclareUnicodeCharacter{0124}{\^H}% + \DeclareUnicodeCharacter{0125}{\^h}% + \DeclareUnicodeCharacter{0126}{\missingcharmsg{H WITH STROKE}}% + \DeclareUnicodeCharacter{0127}{\missingcharmsg{h WITH STROKE}}% + \DeclareUnicodeCharacter{0128}{\~I}% + \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}% + \DeclareUnicodeCharacter{012A}{\=I}% + \DeclareUnicodeCharacter{012B}{\={\dotless{i}}}% + \DeclareUnicodeCharacter{012C}{\u{I}}% + \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}% + \DeclareUnicodeCharacter{012E}{\ogonek{I}}% + \DeclareUnicodeCharacter{012F}{\ogonek{i}}% + % + \DeclareUnicodeCharacter{0130}{\dotaccent{I}}% + \DeclareUnicodeCharacter{0131}{\dotless{i}}% + \DeclareUnicodeCharacter{0132}{IJ}% + \DeclareUnicodeCharacter{0133}{ij}% + \DeclareUnicodeCharacter{0134}{\^J}% + \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}% + \DeclareUnicodeCharacter{0136}{\cedilla{K}}% + \DeclareUnicodeCharacter{0137}{\cedilla{k}}% + \DeclareUnicodeCharacter{0138}{\ensuremath\kappa}% + \DeclareUnicodeCharacter{0139}{\'L}% + \DeclareUnicodeCharacter{013A}{\'l}% + \DeclareUnicodeCharacter{013B}{\cedilla{L}}% + \DeclareUnicodeCharacter{013C}{\cedilla{l}}% + \DeclareUnicodeCharacter{013D}{L'}% should kern + \DeclareUnicodeCharacter{013E}{l'}% should kern + \DeclareUnicodeCharacter{013F}{L\U{00B7}}% + % + \DeclareUnicodeCharacter{0140}{l\U{00B7}}% + \DeclareUnicodeCharacter{0141}{\L}% + \DeclareUnicodeCharacter{0142}{\l}% + \DeclareUnicodeCharacter{0143}{\'N}% + \DeclareUnicodeCharacter{0144}{\'n}% + \DeclareUnicodeCharacter{0145}{\cedilla{N}}% + \DeclareUnicodeCharacter{0146}{\cedilla{n}}% + \DeclareUnicodeCharacter{0147}{\v{N}}% + \DeclareUnicodeCharacter{0148}{\v{n}}% + \DeclareUnicodeCharacter{0149}{'n}% + \DeclareUnicodeCharacter{014A}{\missingcharmsg{ENG}}% + \DeclareUnicodeCharacter{014B}{\missingcharmsg{eng}}% + \DeclareUnicodeCharacter{014C}{\=O}% + \DeclareUnicodeCharacter{014D}{\=o}% + \DeclareUnicodeCharacter{014E}{\u{O}}% + \DeclareUnicodeCharacter{014F}{\u{o}}% + % + \DeclareUnicodeCharacter{0150}{\H{O}}% + \DeclareUnicodeCharacter{0151}{\H{o}}% + \DeclareUnicodeCharacter{0152}{\OE}% + \DeclareUnicodeCharacter{0153}{\oe}% + \DeclareUnicodeCharacter{0154}{\'R}% + \DeclareUnicodeCharacter{0155}{\'r}% + \DeclareUnicodeCharacter{0156}{\cedilla{R}}% + \DeclareUnicodeCharacter{0157}{\cedilla{r}}% + \DeclareUnicodeCharacter{0158}{\v{R}}% + \DeclareUnicodeCharacter{0159}{\v{r}}% + \DeclareUnicodeCharacter{015A}{\'S}% + \DeclareUnicodeCharacter{015B}{\'s}% + \DeclareUnicodeCharacter{015C}{\^S}% + \DeclareUnicodeCharacter{015D}{\^s}% + \DeclareUnicodeCharacter{015E}{\cedilla{S}}% + \DeclareUnicodeCharacter{015F}{\cedilla{s}}% + % + \DeclareUnicodeCharacter{0160}{\v{S}}% + \DeclareUnicodeCharacter{0161}{\v{s}}% + \DeclareUnicodeCharacter{0162}{\cedilla{T}}% + \DeclareUnicodeCharacter{0163}{\cedilla{t}}% + \DeclareUnicodeCharacter{0164}{\v{T}}% + \DeclareUnicodeCharacter{0165}{\v{t}}% + \DeclareUnicodeCharacter{0166}{\missingcharmsg{H WITH STROKE}}% + \DeclareUnicodeCharacter{0167}{\missingcharmsg{h WITH STROKE}}% + \DeclareUnicodeCharacter{0168}{\~U}% + \DeclareUnicodeCharacter{0169}{\~u}% + \DeclareUnicodeCharacter{016A}{\=U}% + \DeclareUnicodeCharacter{016B}{\=u}% + \DeclareUnicodeCharacter{016C}{\u{U}}% + \DeclareUnicodeCharacter{016D}{\u{u}}% + \DeclareUnicodeCharacter{016E}{\ringaccent{U}}% + \DeclareUnicodeCharacter{016F}{\ringaccent{u}}% + % + \DeclareUnicodeCharacter{0170}{\H{U}}% + \DeclareUnicodeCharacter{0171}{\H{u}}% + \DeclareUnicodeCharacter{0172}{\ogonek{U}}% + \DeclareUnicodeCharacter{0173}{\ogonek{u}}% + \DeclareUnicodeCharacter{0174}{\^W}% + \DeclareUnicodeCharacter{0175}{\^w}% + \DeclareUnicodeCharacter{0176}{\^Y}% + \DeclareUnicodeCharacter{0177}{\^y}% + \DeclareUnicodeCharacter{0178}{\"Y}% + \DeclareUnicodeCharacter{0179}{\'Z}% + \DeclareUnicodeCharacter{017A}{\'z}% + \DeclareUnicodeCharacter{017B}{\dotaccent{Z}}% + \DeclareUnicodeCharacter{017C}{\dotaccent{z}}% + \DeclareUnicodeCharacter{017D}{\v{Z}}% + \DeclareUnicodeCharacter{017E}{\v{z}}% + \DeclareUnicodeCharacter{017F}{\missingcharmsg{LONG S}}% + % + \DeclareUnicodeCharacter{01C4}{D\v{Z}}% + \DeclareUnicodeCharacter{01C5}{D\v{z}}% + \DeclareUnicodeCharacter{01C6}{d\v{z}}% + \DeclareUnicodeCharacter{01C7}{LJ}% + \DeclareUnicodeCharacter{01C8}{Lj}% + \DeclareUnicodeCharacter{01C9}{lj}% + \DeclareUnicodeCharacter{01CA}{NJ}% + \DeclareUnicodeCharacter{01CB}{Nj}% + \DeclareUnicodeCharacter{01CC}{nj}% + \DeclareUnicodeCharacter{01CD}{\v{A}}% + \DeclareUnicodeCharacter{01CE}{\v{a}}% + \DeclareUnicodeCharacter{01CF}{\v{I}}% + % + \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}% + \DeclareUnicodeCharacter{01D1}{\v{O}}% + \DeclareUnicodeCharacter{01D2}{\v{o}}% + \DeclareUnicodeCharacter{01D3}{\v{U}}% + \DeclareUnicodeCharacter{01D4}{\v{u}}% + % + \DeclareUnicodeCharacter{01E2}{\={\AE}}% + \DeclareUnicodeCharacter{01E3}{\={\ae}}% + \DeclareUnicodeCharacter{01E6}{\v{G}}% + \DeclareUnicodeCharacter{01E7}{\v{g}}% + \DeclareUnicodeCharacter{01E8}{\v{K}}% + \DeclareUnicodeCharacter{01E9}{\v{k}}% + % + \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}% + \DeclareUnicodeCharacter{01F1}{DZ}% + \DeclareUnicodeCharacter{01F2}{Dz}% + \DeclareUnicodeCharacter{01F3}{dz}% + \DeclareUnicodeCharacter{01F4}{\'G}% + \DeclareUnicodeCharacter{01F5}{\'g}% + \DeclareUnicodeCharacter{01F8}{\`N}% + \DeclareUnicodeCharacter{01F9}{\`n}% + \DeclareUnicodeCharacter{01FC}{\'{\AE}}% + \DeclareUnicodeCharacter{01FD}{\'{\ae}}% + \DeclareUnicodeCharacter{01FE}{\'{\O}}% + \DeclareUnicodeCharacter{01FF}{\'{\o}}% + % + \DeclareUnicodeCharacter{021E}{\v{H}}% + \DeclareUnicodeCharacter{021F}{\v{h}}% + % + \DeclareUnicodeCharacter{0226}{\dotaccent{A}}% + \DeclareUnicodeCharacter{0227}{\dotaccent{a}}% + \DeclareUnicodeCharacter{0228}{\cedilla{E}}% + \DeclareUnicodeCharacter{0229}{\cedilla{e}}% + \DeclareUnicodeCharacter{022E}{\dotaccent{O}}% + \DeclareUnicodeCharacter{022F}{\dotaccent{o}}% + % + \DeclareUnicodeCharacter{0232}{\=Y}% + \DeclareUnicodeCharacter{0233}{\=y}% + \DeclareUnicodeCharacter{0237}{\dotless{j}}% + % + \DeclareUnicodeCharacter{02DB}{\ogonek{ }}% + % + % Greek letters upper case + \DeclareUnicodeCharacter{0391}{{\it A}}% + \DeclareUnicodeCharacter{0392}{{\it B}}% + \DeclareUnicodeCharacter{0393}{\ensuremath{\mit\Gamma}}% + \DeclareUnicodeCharacter{0394}{\ensuremath{\mit\Delta}}% + \DeclareUnicodeCharacter{0395}{{\it E}}% + \DeclareUnicodeCharacter{0396}{{\it Z}}% + \DeclareUnicodeCharacter{0397}{{\it H}}% + \DeclareUnicodeCharacter{0398}{\ensuremath{\mit\Theta}}% + \DeclareUnicodeCharacter{0399}{{\it I}}% + \DeclareUnicodeCharacter{039A}{{\it K}}% + \DeclareUnicodeCharacter{039B}{\ensuremath{\mit\Lambda}}% + \DeclareUnicodeCharacter{039C}{{\it M}}% + \DeclareUnicodeCharacter{039D}{{\it N}}% + \DeclareUnicodeCharacter{039E}{\ensuremath{\mit\Xi}}% + \DeclareUnicodeCharacter{039F}{{\it O}}% + \DeclareUnicodeCharacter{03A0}{\ensuremath{\mit\Pi}}% + \DeclareUnicodeCharacter{03A1}{{\it P}}% + %\DeclareUnicodeCharacter{03A2}{} % none - corresponds to final sigma + \DeclareUnicodeCharacter{03A3}{\ensuremath{\mit\Sigma}}% + \DeclareUnicodeCharacter{03A4}{{\it T}}% + \DeclareUnicodeCharacter{03A5}{\ensuremath{\mit\Upsilon}}% + \DeclareUnicodeCharacter{03A6}{\ensuremath{\mit\Phi}}% + \DeclareUnicodeCharacter{03A7}{{\it X}}% + \DeclareUnicodeCharacter{03A8}{\ensuremath{\mit\Psi}}% + \DeclareUnicodeCharacter{03A9}{\ensuremath{\mit\Omega}}% + % + % Vowels with accents + \DeclareUnicodeCharacter{0390}{\ensuremath{\ddot{\acute\iota}}}% + \DeclareUnicodeCharacter{03AC}{\ensuremath{\acute\alpha}}% + \DeclareUnicodeCharacter{03AD}{\ensuremath{\acute\epsilon}}% + \DeclareUnicodeCharacter{03AE}{\ensuremath{\acute\eta}}% + \DeclareUnicodeCharacter{03AF}{\ensuremath{\acute\iota}}% + \DeclareUnicodeCharacter{03B0}{\ensuremath{\acute{\ddot\upsilon}}}% + % + % Standalone accent + \DeclareUnicodeCharacter{0384}{\ensuremath{\acute{\ }}}% + % + % Greek letters lower case + \DeclareUnicodeCharacter{03B1}{\ensuremath\alpha}% + \DeclareUnicodeCharacter{03B2}{\ensuremath\beta}% + \DeclareUnicodeCharacter{03B3}{\ensuremath\gamma}% + \DeclareUnicodeCharacter{03B4}{\ensuremath\delta}% + \DeclareUnicodeCharacter{03B5}{\ensuremath\epsilon}% + \DeclareUnicodeCharacter{03B6}{\ensuremath\zeta}% + \DeclareUnicodeCharacter{03B7}{\ensuremath\eta}% + \DeclareUnicodeCharacter{03B8}{\ensuremath\theta}% + \DeclareUnicodeCharacter{03B9}{\ensuremath\iota}% + \DeclareUnicodeCharacter{03BA}{\ensuremath\kappa}% + \DeclareUnicodeCharacter{03BB}{\ensuremath\lambda}% + \DeclareUnicodeCharacter{03BC}{\ensuremath\mu}% + \DeclareUnicodeCharacter{03BD}{\ensuremath\nu}% + \DeclareUnicodeCharacter{03BE}{\ensuremath\xi}% + \DeclareUnicodeCharacter{03BF}{{\it o}}% omicron + \DeclareUnicodeCharacter{03C0}{\ensuremath\pi}% + \DeclareUnicodeCharacter{03C1}{\ensuremath\rho}% + \DeclareUnicodeCharacter{03C2}{\ensuremath\varsigma}% + \DeclareUnicodeCharacter{03C3}{\ensuremath\sigma}% + \DeclareUnicodeCharacter{03C4}{\ensuremath\tau}% + \DeclareUnicodeCharacter{03C5}{\ensuremath\upsilon}% + \DeclareUnicodeCharacter{03C6}{\ensuremath\phi}% + \DeclareUnicodeCharacter{03C7}{\ensuremath\chi}% + \DeclareUnicodeCharacter{03C8}{\ensuremath\psi}% + \DeclareUnicodeCharacter{03C9}{\ensuremath\omega}% + % + % More Greek vowels with accents + \DeclareUnicodeCharacter{03CA}{\ensuremath{\ddot\iota}}% + \DeclareUnicodeCharacter{03CB}{\ensuremath{\ddot\upsilon}}% + \DeclareUnicodeCharacter{03CC}{\ensuremath{\acute o}}% + \DeclareUnicodeCharacter{03CD}{\ensuremath{\acute\upsilon}}% + \DeclareUnicodeCharacter{03CE}{\ensuremath{\acute\omega}}% + % + % Variant Greek letters + \DeclareUnicodeCharacter{03D1}{\ensuremath\vartheta}% + \DeclareUnicodeCharacter{03D6}{\ensuremath\varpi}% + \DeclareUnicodeCharacter{03F1}{\ensuremath\varrho}% + % + \DeclareUnicodeCharacter{1E02}{\dotaccent{B}}% + \DeclareUnicodeCharacter{1E03}{\dotaccent{b}}% + \DeclareUnicodeCharacter{1E04}{\udotaccent{B}}% + \DeclareUnicodeCharacter{1E05}{\udotaccent{b}}% + \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}% + \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}% + \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}% + \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}% + \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}% + \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}% + \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}% + \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}% + % + \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}% + \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}% + % + \DeclareUnicodeCharacter{1E20}{\=G}% + \DeclareUnicodeCharacter{1E21}{\=g}% + \DeclareUnicodeCharacter{1E22}{\dotaccent{H}}% + \DeclareUnicodeCharacter{1E23}{\dotaccent{h}}% + \DeclareUnicodeCharacter{1E24}{\udotaccent{H}}% + \DeclareUnicodeCharacter{1E25}{\udotaccent{h}}% + \DeclareUnicodeCharacter{1E26}{\"H}% + \DeclareUnicodeCharacter{1E27}{\"h}% + % + \DeclareUnicodeCharacter{1E30}{\'K}% + \DeclareUnicodeCharacter{1E31}{\'k}% + \DeclareUnicodeCharacter{1E32}{\udotaccent{K}}% + \DeclareUnicodeCharacter{1E33}{\udotaccent{k}}% + \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}% + \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}% + \DeclareUnicodeCharacter{1E36}{\udotaccent{L}}% + \DeclareUnicodeCharacter{1E37}{\udotaccent{l}}% + \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}% + \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}% + \DeclareUnicodeCharacter{1E3E}{\'M}% + \DeclareUnicodeCharacter{1E3F}{\'m}% + % + \DeclareUnicodeCharacter{1E40}{\dotaccent{M}}% + \DeclareUnicodeCharacter{1E41}{\dotaccent{m}}% + \DeclareUnicodeCharacter{1E42}{\udotaccent{M}}% + \DeclareUnicodeCharacter{1E43}{\udotaccent{m}}% + \DeclareUnicodeCharacter{1E44}{\dotaccent{N}}% + \DeclareUnicodeCharacter{1E45}{\dotaccent{n}}% + \DeclareUnicodeCharacter{1E46}{\udotaccent{N}}% + \DeclareUnicodeCharacter{1E47}{\udotaccent{n}}% + \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}% + \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}% + % + \DeclareUnicodeCharacter{1E54}{\'P}% + \DeclareUnicodeCharacter{1E55}{\'p}% + \DeclareUnicodeCharacter{1E56}{\dotaccent{P}}% + \DeclareUnicodeCharacter{1E57}{\dotaccent{p}}% + \DeclareUnicodeCharacter{1E58}{\dotaccent{R}}% + \DeclareUnicodeCharacter{1E59}{\dotaccent{r}}% + \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}% + \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}% + \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}% + \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}% + % + \DeclareUnicodeCharacter{1E60}{\dotaccent{S}}% + \DeclareUnicodeCharacter{1E61}{\dotaccent{s}}% + \DeclareUnicodeCharacter{1E62}{\udotaccent{S}}% + \DeclareUnicodeCharacter{1E63}{\udotaccent{s}}% + \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}% + \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}% + \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}% + \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}% + \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}% + \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}% + % + \DeclareUnicodeCharacter{1E7C}{\~V}% + \DeclareUnicodeCharacter{1E7D}{\~v}% + \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}% + \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}% + % + \DeclareUnicodeCharacter{1E80}{\`W}% + \DeclareUnicodeCharacter{1E81}{\`w}% + \DeclareUnicodeCharacter{1E82}{\'W}% + \DeclareUnicodeCharacter{1E83}{\'w}% + \DeclareUnicodeCharacter{1E84}{\"W}% + \DeclareUnicodeCharacter{1E85}{\"w}% + \DeclareUnicodeCharacter{1E86}{\dotaccent{W}}% + \DeclareUnicodeCharacter{1E87}{\dotaccent{w}}% + \DeclareUnicodeCharacter{1E88}{\udotaccent{W}}% + \DeclareUnicodeCharacter{1E89}{\udotaccent{w}}% + \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}% + \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}% + \DeclareUnicodeCharacter{1E8C}{\"X}% + \DeclareUnicodeCharacter{1E8D}{\"x}% + \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}% + \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}% + % + \DeclareUnicodeCharacter{1E90}{\^Z}% + \DeclareUnicodeCharacter{1E91}{\^z}% + \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}% + \DeclareUnicodeCharacter{1E93}{\udotaccent{z}}% + \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}% + \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}% + \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}% + \DeclareUnicodeCharacter{1E97}{\"t}% + \DeclareUnicodeCharacter{1E98}{\ringaccent{w}}% + \DeclareUnicodeCharacter{1E99}{\ringaccent{y}}% + % + \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}% + \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}% + % + \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}% + \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}% + \DeclareUnicodeCharacter{1EBC}{\~E}% + \DeclareUnicodeCharacter{1EBD}{\~e}% + % + \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}% + \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}% + \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}% + \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}% + % + \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}% + \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}% + % + \DeclareUnicodeCharacter{1EF2}{\`Y}% + \DeclareUnicodeCharacter{1EF3}{\`y}% + \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}% + % + \DeclareUnicodeCharacter{1EF8}{\~Y}% + \DeclareUnicodeCharacter{1EF9}{\~y}% + % + % Punctuation + \DeclareUnicodeCharacter{2013}{--}% + \DeclareUnicodeCharacter{2014}{---}% + \DeclareUnicodeCharacter{2018}{\quoteleft{}}% + \DeclareUnicodeCharacter{2019}{\quoteright{}}% + \DeclareUnicodeCharacter{201A}{\quotesinglbase{}}% + \DeclareUnicodeCharacter{201C}{\quotedblleft{}}% + \DeclareUnicodeCharacter{201D}{\quotedblright{}}% + \DeclareUnicodeCharacter{201E}{\quotedblbase{}}% + \DeclareUnicodeCharacter{2020}{\ensuremath\dagger}% + \DeclareUnicodeCharacter{2021}{\ensuremath\ddagger}% + \DeclareUnicodeCharacter{2022}{\bullet{}}% + \DeclareUnicodeCharacter{202F}{\thinspace}% + \DeclareUnicodeCharacter{2026}{\dots{}}% + \DeclareUnicodeCharacter{2039}{\guilsinglleft{}}% + \DeclareUnicodeCharacter{203A}{\guilsinglright{}}% + % + \DeclareUnicodeCharacter{20AC}{\euro{}}% + % + \DeclareUnicodeCharacter{2192}{\expansion{}}% + \DeclareUnicodeCharacter{21D2}{\result{}}% + % + % Mathematical symbols + \DeclareUnicodeCharacter{2200}{\ensuremath\forall}% + \DeclareUnicodeCharacter{2203}{\ensuremath\exists}% + \DeclareUnicodeCharacter{2208}{\ensuremath\in}% + \DeclareUnicodeCharacter{2212}{\minus{}}% + \DeclareUnicodeCharacter{2217}{\ast}% + \DeclareUnicodeCharacter{221E}{\ensuremath\infty}% + \DeclareUnicodeCharacter{2225}{\ensuremath\parallel}% + \DeclareUnicodeCharacter{2227}{\ensuremath\wedge}% + \DeclareUnicodeCharacter{2229}{\ensuremath\cap}% + \DeclareUnicodeCharacter{2261}{\equiv{}}% + \DeclareUnicodeCharacter{2264}{\ensuremath\leq}% + \DeclareUnicodeCharacter{2265}{\ensuremath\geq}% + \DeclareUnicodeCharacter{2282}{\ensuremath\subset}% + \DeclareUnicodeCharacter{2287}{\ensuremath\supseteq}% + % + \DeclareUnicodeCharacter{2016}{\ensuremath\Vert}% + \DeclareUnicodeCharacter{2032}{\ensuremath\prime}% + \DeclareUnicodeCharacter{210F}{\ensuremath\hbar}% + \DeclareUnicodeCharacter{2111}{\ensuremath\Im}% + \DeclareUnicodeCharacter{2113}{\ensuremath\ell}% + \DeclareUnicodeCharacter{2118}{\ensuremath\wp}% + \DeclareUnicodeCharacter{211C}{\ensuremath\Re}% + \DeclareUnicodeCharacter{2135}{\ensuremath\aleph}% + \DeclareUnicodeCharacter{2190}{\ensuremath\leftarrow}% + \DeclareUnicodeCharacter{2191}{\ensuremath\uparrow}% + \DeclareUnicodeCharacter{2193}{\ensuremath\downarrow}% + \DeclareUnicodeCharacter{2194}{\ensuremath\leftrightarrow}% + \DeclareUnicodeCharacter{2195}{\ensuremath\updownarrow}% + \DeclareUnicodeCharacter{2196}{\ensuremath\nwarrow}% + \DeclareUnicodeCharacter{2197}{\ensuremath\nearrow}% + \DeclareUnicodeCharacter{2198}{\ensuremath\searrow}% + \DeclareUnicodeCharacter{2199}{\ensuremath\swarrow}% + \DeclareUnicodeCharacter{21A6}{\ensuremath\mapsto}% + \DeclareUnicodeCharacter{21A9}{\ensuremath\hookleftarrow}% + \DeclareUnicodeCharacter{21AA}{\ensuremath\hookrightarrow}% + \DeclareUnicodeCharacter{21BC}{\ensuremath\leftharpoonup}% + \DeclareUnicodeCharacter{21BD}{\ensuremath\leftharpoondown}% + \DeclareUnicodeCharacter{21C0}{\ensuremath\rightharpoonup}% + \DeclareUnicodeCharacter{21C1}{\ensuremath\rightharpoondown}% + \DeclareUnicodeCharacter{21CC}{\ensuremath\rightleftharpoons}% + \DeclareUnicodeCharacter{21D0}{\ensuremath\Leftarrow}% + \DeclareUnicodeCharacter{21D1}{\ensuremath\Uparrow}% + \DeclareUnicodeCharacter{21D3}{\ensuremath\Downarrow}% + \DeclareUnicodeCharacter{21D4}{\ensuremath\Leftrightarrow}% + \DeclareUnicodeCharacter{21D5}{\ensuremath\Updownarrow}% + \DeclareUnicodeCharacter{2202}{\ensuremath\partial}% + \DeclareUnicodeCharacter{2205}{\ensuremath\emptyset}% + \DeclareUnicodeCharacter{2207}{\ensuremath\nabla}% + \DeclareUnicodeCharacter{2209}{\ensuremath\notin}% + \DeclareUnicodeCharacter{220B}{\ensuremath\owns}% + \DeclareUnicodeCharacter{220F}{\ensuremath\prod}% + \DeclareUnicodeCharacter{2210}{\ensuremath\coprod}% + \DeclareUnicodeCharacter{2211}{\ensuremath\sum}% + \DeclareUnicodeCharacter{2213}{\ensuremath\mp}% + \DeclareUnicodeCharacter{2218}{\ensuremath\circ}% + \DeclareUnicodeCharacter{221A}{\ensuremath\surd}% + \DeclareUnicodeCharacter{221D}{\ensuremath\propto}% + \DeclareUnicodeCharacter{2220}{\ensuremath\angle}% + \DeclareUnicodeCharacter{2223}{\ensuremath\mid}% + \DeclareUnicodeCharacter{2228}{\ensuremath\vee}% + \DeclareUnicodeCharacter{222A}{\ensuremath\cup}% + \DeclareUnicodeCharacter{222B}{\ensuremath\smallint}% + \DeclareUnicodeCharacter{222E}{\ensuremath\oint}% + \DeclareUnicodeCharacter{223C}{\ensuremath\sim}% + \DeclareUnicodeCharacter{2240}{\ensuremath\wr}% + \DeclareUnicodeCharacter{2243}{\ensuremath\simeq}% + \DeclareUnicodeCharacter{2245}{\ensuremath\cong}% + \DeclareUnicodeCharacter{2248}{\ensuremath\approx}% + \DeclareUnicodeCharacter{224D}{\ensuremath\asymp}% + \DeclareUnicodeCharacter{2250}{\ensuremath\doteq}% + \DeclareUnicodeCharacter{2260}{\ensuremath\neq}% + \DeclareUnicodeCharacter{226A}{\ensuremath\ll}% + \DeclareUnicodeCharacter{226B}{\ensuremath\gg}% + \DeclareUnicodeCharacter{227A}{\ensuremath\prec}% + \DeclareUnicodeCharacter{227B}{\ensuremath\succ}% + \DeclareUnicodeCharacter{2283}{\ensuremath\supset}% + \DeclareUnicodeCharacter{2286}{\ensuremath\subseteq}% + \DeclareUnicodeCharacter{228E}{\ensuremath\uplus}% + \DeclareUnicodeCharacter{2291}{\ensuremath\sqsubseteq}% + \DeclareUnicodeCharacter{2292}{\ensuremath\sqsupseteq}% + \DeclareUnicodeCharacter{2293}{\ensuremath\sqcap}% + \DeclareUnicodeCharacter{2294}{\ensuremath\sqcup}% + \DeclareUnicodeCharacter{2295}{\ensuremath\oplus}% + \DeclareUnicodeCharacter{2296}{\ensuremath\ominus}% + \DeclareUnicodeCharacter{2297}{\ensuremath\otimes}% + \DeclareUnicodeCharacter{2298}{\ensuremath\oslash}% + \DeclareUnicodeCharacter{2299}{\ensuremath\odot}% + \DeclareUnicodeCharacter{22A2}{\ensuremath\vdash}% + \DeclareUnicodeCharacter{22A3}{\ensuremath\dashv}% + \DeclareUnicodeCharacter{22A4}{\ensuremath\ptextop}% + \DeclareUnicodeCharacter{22A5}{\ensuremath\bot}% + \DeclareUnicodeCharacter{22A8}{\ensuremath\models}% + \DeclareUnicodeCharacter{22C0}{\ensuremath\bigwedge}% + \DeclareUnicodeCharacter{22C1}{\ensuremath\bigvee}% + \DeclareUnicodeCharacter{22C2}{\ensuremath\bigcap}% + \DeclareUnicodeCharacter{22C3}{\ensuremath\bigcup}% + \DeclareUnicodeCharacter{22C4}{\ensuremath\diamond}% + \DeclareUnicodeCharacter{22C5}{\ensuremath\cdot}% + \DeclareUnicodeCharacter{22C6}{\ensuremath\star}% + \DeclareUnicodeCharacter{22C8}{\ensuremath\bowtie}% + \DeclareUnicodeCharacter{2308}{\ensuremath\lceil}% + \DeclareUnicodeCharacter{2309}{\ensuremath\rceil}% + \DeclareUnicodeCharacter{230A}{\ensuremath\lfloor}% + \DeclareUnicodeCharacter{230B}{\ensuremath\rfloor}% + \DeclareUnicodeCharacter{2322}{\ensuremath\frown}% + \DeclareUnicodeCharacter{2323}{\ensuremath\smile}% + % + \DeclareUnicodeCharacter{25B3}{\ensuremath\triangle}% + \DeclareUnicodeCharacter{25B7}{\ensuremath\triangleright}% + \DeclareUnicodeCharacter{25BD}{\ensuremath\bigtriangledown}% + \DeclareUnicodeCharacter{25C1}{\ensuremath\triangleleft}% + \DeclareUnicodeCharacter{25C7}{\ensuremath\diamond}% + \DeclareUnicodeCharacter{2660}{\ensuremath\spadesuit}% + \DeclareUnicodeCharacter{2661}{\ensuremath\heartsuit}% + \DeclareUnicodeCharacter{2662}{\ensuremath\diamondsuit}% + \DeclareUnicodeCharacter{2663}{\ensuremath\clubsuit}% + \DeclareUnicodeCharacter{266D}{\ensuremath\flat}% + \DeclareUnicodeCharacter{266E}{\ensuremath\natural}% + \DeclareUnicodeCharacter{266F}{\ensuremath\sharp}% + \DeclareUnicodeCharacter{26AA}{\ensuremath\bigcirc}% + \DeclareUnicodeCharacter{27B9}{\ensuremath\rangle}% + \DeclareUnicodeCharacter{27C2}{\ensuremath\perp}% + \DeclareUnicodeCharacter{27E8}{\ensuremath\langle}% + \DeclareUnicodeCharacter{27F5}{\ensuremath\longleftarrow}% + \DeclareUnicodeCharacter{27F6}{\ensuremath\longrightarrow}% + \DeclareUnicodeCharacter{27F7}{\ensuremath\longleftrightarrow}% + \DeclareUnicodeCharacter{27FC}{\ensuremath\longmapsto}% + \DeclareUnicodeCharacter{29F5}{\ensuremath\setminus}% + \DeclareUnicodeCharacter{2A00}{\ensuremath\bigodot}% + \DeclareUnicodeCharacter{2A01}{\ensuremath\bigoplus}% + \DeclareUnicodeCharacter{2A02}{\ensuremath\bigotimes}% + \DeclareUnicodeCharacter{2A04}{\ensuremath\biguplus}% + \DeclareUnicodeCharacter{2A06}{\ensuremath\bigsqcup}% + \DeclareUnicodeCharacter{2A3F}{\ensuremath\amalg}% + \DeclareUnicodeCharacter{2AAF}{\ensuremath\preceq}% + \DeclareUnicodeCharacter{2AB0}{\ensuremath\succeq}% + % + \global\mathchardef\checkmark="1370% actually the square root sign + \DeclareUnicodeCharacter{2713}{\ensuremath\checkmark}% +}% end of \unicodechardefs + +% UTF-8 byte sequence (pdfTeX) definitions (replacing and @U command) +% It makes the setting that replace UTF-8 byte sequence. +\def\utfeightchardefs{% + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterUTFviii + \unicodechardefs +} + +% Whether the active definitions of non-ASCII characters expand to +% non-active tokens with the same character code. This is used to +% write characters literally, instead of using active definitions for +% printing the correct glyphs. +\newif\ifpassthroughchars +\passthroughcharsfalse + +% For native Unicode handling (XeTeX and LuaTeX), +% provide a definition macro to replace/pass-through a Unicode character +% +\def\DeclareUnicodeCharacterNative#1#2{% + \catcode"#1=\active + \def\dodeclareunicodecharacternative##1##2##3{% + \begingroup + \uccode`\~="##2\relax + \uppercase{\gdef~}{% + \ifpassthroughchars + ##1% + \else + ##3% + \fi + } + \endgroup + } + \begingroup + \uccode`\.="#1\relax + \uppercase{\def\UTFNativeTmp{.}}% + \expandafter\dodeclareunicodecharacternative\UTFNativeTmp{#1}{#2}% + \endgroup +} + +% Native Unicode handling (XeTeX and LuaTeX) character replacing definition. +% It activates the setting that replaces Unicode characters. +\def\nativeunicodechardefs{% + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNative + \unicodechardefs +} + +% For native Unicode handling (XeTeX and LuaTeX), +% make the character token expand +% to the sequences given in \unicodechardefs for printing. +\def\DeclareUnicodeCharacterNativeAtU#1#2{% + \def\UTFAtUTmp{#2} + \expandafter\globallet\csname uni:#1\endcsname \UTFAtUTmp +} + +% @U command definitions for native Unicode handling (XeTeX and LuaTeX). +\def\nativeunicodechardefsatu{% + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNativeAtU + \unicodechardefs +} + +% US-ASCII character definitions. +\def\asciichardefs{% nothing need be done + \relax +} + +% Define all Unicode characters we know about. This makes UTF-8 the default +% input encoding and allows @U to work. +\iftxinativeunicodecapable + \nativeunicodechardefsatu +\else + \utfeightchardefs +\fi + +\message{formatting,} \newdimen\defaultparindent \defaultparindent = 15pt @@ -5201,34 +11159,35 @@ width0pt\relax} \fi % Prevent underfull vbox error messages. \vbadness = 10000 -% Don't be so finicky about underfull hboxes, either. -\hbadness = 2000 +% Don't be very finicky about underfull hboxes, either. +\hbadness = 6666 -% Following George Bush, just get rid of widows and orphans. +% Following George Bush, get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on -% \hsize. This makes it come to about 9pt for the 8.5x11 format. We -% call this whenever the paper size is set. +% \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else - \emergencystretch = \hsize - \divide\emergencystretch by 45 + \emergencystretch = .15\hsize \fi } -% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; -% 4) hoffset; 5) binding offset; 6) topskip. Then whoever calls us can -% set \parskip and call \setleading for \baselineskip. +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. % -\def\internalpagesizes#1#2#3#4#5#6{% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip @@ -5237,16 +11196,35 @@ width0pt\relax} \fi \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin - \pageheight = \vsize + \txipageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in - \pagewidth = \hsize + \txipagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + % if we don't reset these, they will remain at "1 true in" of + % whatever layout pdftex was dumped with. + \pdfhorigin = 1 true in + \pdfvorigin = 1 true in + \else + \ifx\XeTeXrevision\thisisundefined + \special{papersize=#8,#7}% + \else + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + % XeTeX does not have \pdfhorigin and \pdfvorigin. + \fi + \fi + % + \setleading{\textleading} + % \parindent = \defaultparindent \setemergencystretch } @@ -5254,104 +11232,168 @@ width0pt\relax} \fi % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt - \setleading{13.2pt}% + \textleading = 13.2pt % % If page is nothing but text, make it come out even. - \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}% + \internalpagesizes{607.2pt}{6in}% that's 46 lines + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% }} -% Use @smallbook to reset parameters for 7x9.5 (or so) format. +% Use @smallbook to reset parameters for 7x9.25 trim size. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt - \setleading{12pt}% + \textleading = 12pt % - \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}% + \internalpagesizes{7.5in}{5in}% + {-.2in}{0in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt - \deftypemargin = 0pt \defbodyindent = .5cm +}} + +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt % - \let\smalldisplay = \smalldisplayx - \let\smallexample = \smalllispx - \let\smallformat = \smallformatx - \let\smalllisp = \smalllispx + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \contentsrightmargin = 0pt + \defbodyindent = .4cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 - \setleading{12pt}% \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt % - \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}% + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{673.2pt}{160mm}% that's 51 lines + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% % \tolerance = 700 - \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm }} -% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin -% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 - \setleading{13.6pt}% - % \afourpaper - \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}% + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% % + % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} -% Use @afourwide to print on European A4 paper in wide format. -\def\afourwide{% +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 \afourpaper - \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}% - % + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% \globaldefs = 0 -} +}} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. -% -\def\pagesizes{\parsearg\pagesizesxxx} -\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +% +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt - \setleading{13.2pt}% + \setleading{\textleading}% % - \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}% + \dimen0 = #1\relax + \advance\dimen0 by \voffset + \advance\dimen0 by 1in % reference point for DVI is 1 inch from top of page + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + \advance\dimen2 by 1in % reference point is 1 inch from left edge of page + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% }} % Set default to letter. -% +% \letterpaper +% Default value of \hfuzz, for suppressing warnings about overfull hboxes. +\hfuzz = 1pt + + \message{and turning on texinfo input format.} -% Define macros to output various characters with catcode for normal text. -\catcode`\"=\other -\catcode`\~=\other -\catcode`\^=\other -\catcode`\_=\other -\catcode`\|=\other -\catcode`\<=\other -\catcode`\>=\other -\catcode`\+=\other -\def\normaldoublequote{"} -\def\normaltilde{~} -\def\normalcaret{^} -\def\normalunderscore{_} -\def\normalverticalbar{|} -\def\normalless{<} -\def\normalgreater{>} -\def\normalplus{+} +\def^^L{\par} % remove \outer, so ^L can appear in an @comment -% This macro is used to make a character print one way in ttfont -% where it can probably just be output, and another way in other fonts, +% DEL is a comment character, in case @c does not suffice. +\catcode`\^^? = 14 + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other \def\normaldoublequote{"} +\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix +\catcode`\+=\other \def\normalplus{+} +\catcode`\<=\other \def\normalless{<} +\catcode`\>=\other \def\normalgreater{>} +\catcode`\^=\other \def\normalcaret{^} +\catcode`\_=\other \def\normalunderscore{_} +\catcode`\|=\other \def\normalverticalbar{|} +\catcode`\~=\other \def\normaltilde{~} + +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print @@ -5359,126 +11401,214 @@ width0pt\relax} \fi % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % -\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} -% Turn off all special characters except @ -% (and those which the user can use as if they were ordinary). +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Set catcodes for Texinfo file + +% Active characters for printing the wanted glyph. % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. - +% \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote -\catcode`\~=\active -\def~{{\tt\char126}} -\chardef\hat=`\^ -\catcode`\^=\active -\def^{{\tt \hat}} +\catcode`\~=\active \def\activetilde{{\tt\char126}} \let~ = \activetilde +\chardef\hatchar=`\^ +\catcode`\^=\active \def\activehat{{\tt \hatchar}} \let^ = \activehat \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} -% Subroutine for the previous macro. -\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } +\let\realunder=_ + +\catcode`\|=\active \def|{{\tt\char124}} -\catcode`\|=\active -\def|{{\tt\char124}} \chardef \less=`\< -\catcode`\<=\active -\def<{{\tt \less}} +\catcode`\<=\active \def\activeless{{\tt \less}}\let< = \activeless \chardef \gtr=`\> -\catcode`\>=\active -\def>{{\tt \gtr}} -\catcode`\+=\active -\def+{{\tt \char 43}} -%\catcode 27=\active -%\def^^[{$\diamondsuit$} +\catcode`\>=\active \def\activegtr{{\tt \gtr}}\let> = \activegtr +\catcode`\+=\active \def+{{\tt \char 43}} +\catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix +\catcode`\-=\active \let-=\normaldash -% Set up an active definition for =, but don't enable it most of the time. -{\catcode`\==\active -\global\def={{\tt \char 61}}} -\catcode`+=\active -\catcode`\_=\active +% used for headline/footline in the output routine, in case the page +% breaks in the middle of an @tex block. +\def\texinfochars{% + \let< = \activeless + \let> = \activegtr + \let~ = \activetilde + \let^ = \activehat + \markupsetuplqdefault \markupsetuprqdefault + \let\b = \strong + \let\i = \smartitalic + % in principle, all other definitions in \tex have to be undone too. +} -% If a .fmt file is being used, characters that might appear in a file -% name cannot be active until we have parsed the command line. -% So turn them off again, and have \everyjob (or @setfilename) turn them on. -% \otherifyactive is called near the end of this file. -\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} \catcode`\@=0 -% \rawbackslashxx output one backslash character in current font -\global\chardef\rawbackslashxx=`\\ -%{\catcode`\\=\other -%@gdef@rawbackslashxx{\}} +% \backslashcurfont outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\backslashcurfont=`\\ -% \rawbackslash redefines \ as input to do \rawbackslashxx. -{\catcode`\\=\active -@gdef@rawbackslash{@let\=@rawbackslashxx }} +% \realbackslash is an actual character `\' with catcode other. +{\catcode`\\=\other @gdef@realbackslash{\}} -% \normalbackslash outputs one backslash in fixed width font. -\def\normalbackslash{{\tt\rawbackslashxx}} +% In Texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active % @ for escape char from now on. -% Say @foo, not \foo, in error messages. -\escapechar=`\@ +% Print a typewriter backslash. For math mode, we can't simply use +% \backslashcurfont: the story here is that in math mode, the \char +% of \backslashcurfont ends up printing the roman \ from the math symbol +% font (because \char in math mode uses the \mathcode, and plain.tex +% sets \mathcode`\\="026E). Hence we use an explicit \mathchar, +% which is the decimal equivalent of "715c (class 7, e.g., use \fam; +% ignored family value; char position "5C). We can't use " for the +% usual hex value because it has already been made active. -% \catcode 17=0 % Define control-q -\catcode`\\=\active +@def@ttbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} +@let@backslashchar = @ttbackslash % @backslashchar{} is for user documents. -% Used sometimes to turn off (effectively) the active characters -% even after parsing them. -@def@turnoffactive{@let"=@normaldoublequote -@let\=@realbackslash -@let~=@normaltilde -@let^=@normalcaret -@let_=@normalunderscore -@let|=@normalverticalbar -@let<=@normalless -@let>=@normalgreater -@let+=@normalplus} +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +@gdef@otherbackslash{@let\=@realbackslash} -@def@normalturnoffactive{@let"=@normaldoublequote -@let\=@normalbackslash -@let~=@normaltilde -@let^=@normalcaret -@let_=@normalunderscore -@let|=@normalverticalbar -@let<=@normalless -@let>=@normalgreater -@let+=@normalplus} +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. +% +{@catcode`- = @active + @gdef@normalturnoffactive{% + @passthroughcharstrue + @let-=@normaldash + @let"=@normaldoublequote + @let$=@normaldollar %$ font-lock fix + @let+=@normalplus + @let<=@normalless + @let>=@normalgreater + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let~=@normaltilde + @let\=@ttbackslash + @markupsetuplqdefault + @markupsetuprqdefault + @unsepspaces + } +} -% Make _ and + \other characters, temporarily. -% This is canceled by @fixbackslash. -@otherifyactive +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have @fixbackslash turn them back on. +@catcode`+=@other @catcode`@_=@other +% \enablebackslashhack - allow file to begin `\input texinfo' +% % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. -% -@gdef@eatinput input texinfo{@fixbackslash} -@global@let\ = @eatinput +% If the file did not have a `\input texinfo', then it is turned off after +% the first line; otherwise the first `\' in the file would cause an error. +% This is used on the very last line of this file, texinfo.tex. +% We also use @c to call @fixbackslash, in case ends of lines are hidden. +{ +@catcode`@^=7 +@catcode`@^^M=13@gdef@enablebackslashhack{% + @global@let\ = @eatinput% + @catcode`@^^M=13% + @def@c{@fixbackslash@c}% + % Definition for the newline at the end of this file. + @def ^^M{@let^^M@secondlinenl}% + % Definition for a newline in the main Texinfo file. + @gdef @secondlinenl{@fixbackslash}% + % In case the first line has a whole-line command on it + @let@originalparsearg@parsearg + @def@parsearg{@fixbackslash@originalparsearg} +}} -% On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\{ in the file would cause an error. This macro tries to fix -% that, assuming it is called before the first `\' could plausibly occur. -% Also back turn on active characters that might appear in the input -% file name, in case not using a pre-dumped format. -% -@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi - @catcode`+=@active @catcode`@_=@active} +{@catcode`@^=7 @catcode`@^^M=13% +@gdef@eatinput input texinfo#1^^M{@fixbackslash}} -% These look ok in all fonts, so just make them not special. The @rm below -% makes sure that the current font starts out as the newly loaded cmr10 -@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other +% Emergency active definition of newline, in case an active newline token +% appears by mistake. +{@catcode`@^=7 @catcode13=13% +@gdef@enableemergencynewline{% + @gdef^^M{% + @par% + %@par% +}}} -@textfonts -@rm + +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @ttbackslash @fi + @catcode13=5 % regular end of line + @enableemergencynewline + @let@c=@comment + @let@parsearg@originalparsearg + % Also turn back on active characters that might appear in the input + % file name, in case not using a pre-dumped format. + @catcode`+=@active + @catcode`@_=@active + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. This macro, @fixbackslash, gets + % called at the beginning of every Texinfo file. Not opening texinfo.cnf + % directly in this file, texinfo.tex, makes it possible to make a format + % file for Texinfo. + % + @openin 1 texinfo.cnf + @ifeof 1 @else @input texinfo.cnf @fi + @closein 1 +} + + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These (along with & and #) are made active for url-breaking, so need +% active definitions as the normal characters. +@def@normaldot{.} +@def@normalquest{?} +@def@normalslash{/} + +% These look ok in all fonts, so just make them not special. +% @hashchar{} gets its own user-level command, because of #line. +@catcode`@& = @other @def@normalamp{&} +@catcode`@# = @other @def@normalhash{#} +@catcode`@% = @other @def@normalpercent{%} + +@let @hashchar = @normalhash + +@c Finally, make ` and ' active, so that txicodequoteundirected and +@c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we +@c don't make ` and ' active, @code will not get them as active chars. +@c Do this last of all since we use ` in the previous @catcode assignments. +@catcode`@'=@active +@catcode`@`=@active +@markupsetuplqdefault +@markupsetuprqdefault @c Local variables: -@c eval: (add-hook 'write-file-hooks 'time-stamp) -@c page-delimiter: "^\\\\message" +@c eval: (add-hook 'before-save-hook 'time-stamp) +@c page-delimiter: "^\\\\message\\|emacs-page" @c time-stamp-start: "def\\\\texinfoversion{" -@c time-stamp-format: "%:y-%02m-%02d" +@c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: + +@c vim:sw=2: + +@enablebackslashhack diff --git a/doc/tinc.conf.5 b/doc/tinc.conf.5 deleted file mode 100644 index 2dfdf07..0000000 --- a/doc/tinc.conf.5 +++ /dev/null @@ -1,340 +0,0 @@ -.Dd 2002-04-09 -.Dt TINC.CONF 5 -.\" Manual page created by: -.\" Ivo Timmermans -.\" Guus Sliepen -.Sh NAME -.Nm tinc.conf -.Nd tinc daemon configuration -.Sh DESCRIPTION -The files in the -.Pa /etc/tinc/ -directory contain runtime and security information for the tinc daemon. -.Sh NETWORKS -It is perfectly ok for you to run more than one tinc daemon. -However, in its default form, -you will soon notice that you can't use two different configuration files without the -.Fl c -option. -.Pp -We have thought of another way of dealing with this: network names. -This means that you call -.Nm -with the -.Fl n -option, which will assign a name to this daemon. -.Pp -The effect of this is that the daemon will set its configuration root to -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa / , -where -.Ar NETNAME -is your argument to the -.Fl n -option. -You'll notice that messages appear in syslog as coming from -.Nm tincd. Ns Ar NETNAME . -.Pp -However, it is not strictly necessary that you call tinc with the -.Fl n -option. -In this case, the network name would just be empty, -and it will be used as such. -.Nm tinc -now looks for files in -.Pa /etc/tinc/ , -instead of -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa / ; -the configuration file should be -.Pa /etc/tinc/tinc.conf , -and the host configuration files are now expected to be in -.Pa /etc/tinc/hosts/ . -.Pp -But it is highly recommended that you use this feature of -.Nm tinc , -because it will be so much clearer whom your daemon talks to. -Hence, we will assume that you use it. -.Sh NAMES -Each tinc daemon should have a name that is unique in the network which it will be part of. -The name will be used by other tinc daemons for identification. -The name has to be declared in the -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf -file. -.Pp -To make things easy, -choose something that will give unique and easy to remember names to your tinc daemon(s). -You could try things like hostnames, owner surnames or location names. -.Sh PUBLIC/PRIVATE KEYS -You should use -.Ic tincd -K -to generate public/private keypairs. -It will generate two keys. -The private key should be stored in a separate file -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv -\-\- where -.Ar NETNAME -stands for the network (see -.Sx NETWORKS ) -above. -The public key should be stored in the host configuration file -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME -\-\- where -.Va NAME -stands for the name of the local tinc daemon (see -.Sx NAMES ) . -.Sh SERVER CONFIGURATION -The server configuration of the daemon is done in the file -.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf . -This file consists of comments (lines started with a -.Li # ) -or assignments in the form of: -.Pp -.Va Variable Li = Ar Value . -.Pp -The variable names are case insensitive, and any spaces, tabs, -newlines and carriage returns are ignored. -Note: it is not required that you put in the -.Li = -sign, but doing so improves readability. -If you leave it out, remember to replace it with at least one space character. -.Pp -Here are all valid variables, listed in alphabetical order. -The default value is given between parentheses. -.Bl -tag -width indent -.It Va AddressFamily Li = ipv4 | ipv6 | any Po ipv4 Pc Bq experimental -This option affects the address family of listening and outgoing sockets. -If -.Qq any -is selected, then depending on the operating system both IPv4 and IPv6 or just -IPv6 listening sockets will be created. -.It Va BindToInterface Li = Ar interface Bq experimental -If your computer has more than one network interface, -.Nm tinc -will by default listen on all of them for incoming connections. -It is possible to bind only to a single interface with this variable. -.Pp -This option may not work on all platforms. -.It Va ConnectTo Li = Ar name -Specifies which other tinc daemon to connect to on startup. -Multiple -.Va ConnectTo -variables may be specified, -in which case outgoing connections to each specified tinc daemon are made. -The names should be known to this tinc daemon -(i.e., there should be a host configuration file for the name on the -.Va ConnectTo -line). -.Pp -If you don't specify a host with -.Va ConnectTo , -.Nm tinc -won't try to connect to other daemons at all, -and will instead just listen for incoming connections. -.It Va Device Li = Ar device Po /dev/tap0 or /dev/misc/net/tun Pc -The virtual network device to use. -.Nm tinc -will automatically detect what kind of device it is. -Note that you can only use one device per daemon. -The info pages of the tinc package contain more information -about configuring the virtual network device. -.It Va Hostnames Li = yes | no Pq no -This option selects whether IP addresses (both real and on the VPN) should -be resolved. Since DNS lookups are blocking, it might affect tinc's -efficiency, even stopping the daemon for a few seconds every time it does -a lookup if your DNS server is not responding. -.Pp -This does not affect resolving hostnames to IP addresses from the -host configuration files. -.It Va Interface Li = Ar interface -Defines the name of the interface corresponding to the virtual network device. -Depending on the operating system and the type of device this may or may not actually set the name. -Currently this option only affects the Linux tun/tap device. -.It Va KeyExpire Li = Ar period Pq 3600 -This option controls the period the encryption keys used to encrypt the data are valid. -It is common practice to change keys at regular intervals to make it even harder for crackers, -even though it is thought to be nearly impossible to crack a single key. -.It Va MACExpire Li = Ar period Pq 600 -This option controls the amount of time MAC addresses are kept before they are removed. -This only has effect when -.Va Mode -is set to -.Qq switch . -.It Va MaxTimeout Li = Ar period Pq 900 -This is the maximum delay before trying to reconnect to other tinc daemons. -.It Va Mode Li = router | switch | hub Pq router -This option selects the way packets are routed to other daemons. -.Bl -tag -width indent -.It router -In this mode -.Va Subnet -variables in the host configuration files will be used to form a routing table. -Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. -.It switch -In this mode the MAC addresses of the packets on the VPN will be used to -dynamically create a routing table just like an Ethernet switch does. -Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode -at the cost of frequent broadcast ARP requests and routing table updates. -.It hub -This mode is almost the same as the switch mode, but instead -every packet will be broadcast to the other daemons -while no routing table is managed. -.El -.It Va Name Li = Ar name Bq required -This is the name which identifies this tinc daemon. -It must be unique for the virtual private network this daemon will connect to. -.It Va PingTimeout Li = Ar period Pq 60 -The number of seconds of inactivity that -.Nm tinc -will wait before sending a probe to the other end. -If that other end doesn't answer within that same amount of time, -the connection is terminated, -and the others will be notified of this. -.It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental -When this option is enabled the value of the TOS field of tunneled IPv4 packets -will be inherited by the UDP packets that are sent out. -.It Va PrivateKey Li = Ar key Bq obsolete -The private RSA key of this tinc daemon. -It will allow this tinc daemon to authenticate itself to other daemons. -.It Va PrivateKeyFile Li = Ar filename Bq recommended -The file in which the private RSA key of this tinc daemon resides. -Note that there must be exactly one of -.Va PrivateKey -or -.Va PrivateKeyFile -specified in the configuration file. -.El -.Sh HOST CONFIGURATION FILES -The host configuration files contain all information needed -to establish a connection to those hosts. -A host configuration file is also required for the local tinc daemon, -it will use it to read in it's listen port, public key and subnets. -.Pp -The idea is that these files are portable. -You can safely mail your own host configuration file to someone else. -That other person can then copy it to his own hosts directory, -and now his tinc daemon will be able to connect to your tinc daemon. -Since host configuration files only contain public keys, -no secrets are revealed by sending out this information. -.Bl -tag -width indent -.It Va Address Li = Ar address Bq recommended -The IP address or hostname of this tinc daemon on the real network. -This wil only be used when trying to make an outgoing connection to this tinc daemon. -Multiple -.Va Address -variables can be specified, in which case each address will be tried until a working -connection has been established. -.It Va Cipher Li = Ar cipher Pq blowfish -The symmetric cipher algorithm used to encrypt UDP packets. -Any cipher supported by OpenSSL is recognised. -Furthermore, specifying -.Qq none -will turn off packet encryption. -.It Va Compression Li = Ar level Pq 0 -This option sets the level of compression used for UDP packets. -Possible values are 0 (off), 1 (fast) and any integer up to 9 (best). -.It Va Digest Li = Ar digest Pq sha1 -The digest algorithm used to authenticate UDP packets. -Any digest supported by OpenSSL is recognised. -Furthermore, specifying -.Qq none -will turn off packet authentication. -.It Va IndirectData Li = yes | no Pq no -This option specifies whether other tinc daemons besides the one you specified with -.Va ConnectTo -can make a direct connection to you. -This is especially useful if you are behind a firewall -and it is impossible to make a connection from the outside to your tinc daemon. -Otherwise, it is best to leave this option out or set it to no. -.It Va MACLength Li = Ar length Pq 4 -The length of the message authentication code used to authenticate UDP packets. -Can be anything from -.Qq 0 -up to the length of the digest produced by the digest algorithm. -.It Va Port Li = Ar port Pq 655 -The port number on which this tinc daemon is listening for incoming connections. -.It Va PublicKey Li = Ar key Bq obsolete -The public RSA key of this tinc daemon. -It will be used to cryptographically verify it's identity and to set up a secure connection. -.It Va PublicKeyFile Li = Ar filename Bq obsolete -The file in which the public RSA key of this tinc daemon resides. -.Pp -From version 1.0pre4 on -.Nm tinc -will store the public key directly into the host configuration file in PEM format, -the above two options then are not necessary. -Either the PEM format is used, or exactly one of the above two options must be specified -in each host configuration file, -if you want to be able to establish a connection with that host. -.It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength -The subnet which this tinc daemon will serve. -.Nm tinc -tries to look up which other daemon it should send a packet to by searching the appropriate subnet. -If the packet matches a subnet, -it will be sent to the daemon who has this subnet in his host configuration file. -Multiple -.Va Subnet -variables can be specified. -.Pp -Subnets can either be single MAC, IPv4 or IPv6 addresses, -in which case a subnet consisting of only that single address is assumed, -or they can be a IPv4 or IPv6 network address with a prefixlength. -Shorthand notations are not supported. -For example, IPv4 subnets must be in a form like 192.168.1.0/24, -where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask. -Note that subnets like 192.168.1.1/24 are invalid! -Read a networking HOWTO/FAQ/guide if you don't understand this. -IPv6 subnets are notated like fec0:0:0:1:0:0:0:0/64. -MAC addresses are notated like 0:1a:2b:3c:4d:5e. -.It Va TCPOnly Li = yes | no Pq no -If this variable is set to yes, -then the packets are tunnelled over the TCP connection instead of a UDP connection. -This is especially useful for those who want to run a tinc daemon -from behind a masquerading firewall, -or if UDP packet routing is disabled somehow. -Setting this options also implicitly sets IndirectData. -.El -.Sh FILES -.Bl -tag -width indent -.It Pa /etc/tinc/ -The top directory for configuration files. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf -The default name of the server configuration file for net -.Ar NETNAME . -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ -Host configuration files are kept in this directory. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-up -If an executable file with this name exists, -it will be executed right after the tinc daemon has connected to the virtual network device. -It can be used to set up the corresponding network interface. -.Pp -The environment variable -.Ev $NETNAME -will be passed to the executable. -If specified with the -.Va Interface -configuration variable, -or if the virtual network device is a Linux tun/tap device, -the environment variable -.Ev $INTERFACE -will be set to the name of the network interface. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-down -If an executable file with this name exists, -it will be executed right before the tinc daemon is going to close -its connection to the virtual network device. -The same environment variables will be passed as mentioned above. -.El -.Sh SEE ALSO -.Xr tincd 8 , -.Pa http://tinc.nl.linux.org/ , -.Pa http://www.linuxdoc.org/LDP/nag2/ . -.Pp -The full documentation for -.Nm tinc -is maintained as a Texinfo manual. -If the info and tinc programs are properly installed at your site, the command -.Ic info tinc -should give you access to the complete manual. -.Pp -.Nm tinc -comes with ABSOLUTELY NO WARRANTY. -This is free software, and you are welcome to redistribute it under certain conditions; -see the file COPYING for details. diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in new file mode 100644 index 0000000..cd7d1a0 --- /dev/null +++ b/doc/tinc.conf.5.in @@ -0,0 +1,673 @@ +.Dd 2016-10-29 +.Dt TINC.CONF 5 +.\" Manual page created by: +.\" Ivo Timmermans +.\" Guus Sliepen +.Sh NAME +.Nm tinc.conf +.Nd tinc daemon configuration +.Sh DESCRIPTION +The files in the +.Pa @sysconfdir@/tinc/ +directory contain runtime and security information for the tinc daemon. +.Sh NETWORKS +It is perfectly ok for you to run more than one tinc daemon. +However, in its default form, +you will soon notice that you can't use two different configuration files without the +.Fl c +option. +.Pp +We have thought of another way of dealing with this: network names. +This means that you call +.Nm +with the +.Fl n +option, which will assign a name to this daemon. +.Pp +The effect of this is that the daemon will set its configuration root to +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / , +where +.Ar NETNAME +is your argument to the +.Fl n +option. +You'll notice that messages appear in syslog as coming from +.Nm tincd. Ns Ar NETNAME . +.Pp +However, it is not strictly necessary that you call tinc with the +.Fl n +option. +In this case, the network name would just be empty, +and it will be used as such. +.Nm tinc +now looks for files in +.Pa @sysconfdir@/tinc/ , +instead of +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ; +the configuration file should be +.Pa @sysconfdir@/tinc/tinc.conf , +and the host configuration files are now expected to be in +.Pa @sysconfdir@/tinc/hosts/ . +.Pp +But it is highly recommended that you use this feature of +.Nm tinc , +because it will be so much clearer whom your daemon talks to. +Hence, we will assume that you use it. +.Sh NAMES +Each tinc daemon must have a name that is unique in the network which it will be part of. +The name will be used by other tinc daemons for identification. +The name has to be declared in the +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf +file. +.Pp +To make things easy, +choose something that will give unique and easy to remember names to your tinc daemon(s). +You could try things like hostnames, owner surnames or location names. +.Sh PUBLIC/PRIVATE KEYS +You should use +.Ic tincd -K +to generate public/private keypairs. +It will generate two keys. +The private key should be stored in a separate file +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv +\-\- where +.Ar NETNAME +stands for the network (see +.Sx NETWORKS ) +above. +The public key should be stored in the host configuration file +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME +\-\- where +.Va NAME +stands for the name of the local tinc daemon (see +.Sx NAMES ) . +.Sh SERVER CONFIGURATION +The server configuration of the daemon is done in the file +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf . +This file consists of comments (lines started with a +.Li # ) +or assignments in the form of: +.Pp +.Va Variable Li = Ar Value . +.Pp +The variable names are case insensitive, and any spaces, tabs, +newlines and carriage returns are ignored. +Note: it is not required that you put in the +.Li = +sign, but doing so improves readability. +If you leave it out, remember to replace it with at least one space character. +.Pp +The server configuration is complemented with host specific configuration (see the next section). +Although all configuration options for the local host listed in this document can also be put in +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf , +it is recommended to put host specific configuration options in the host configuration file, +as this makes it easy to exchange with other nodes. +.Pp +Here are all valid variables, listed in alphabetical order. +The default value is given between parentheses. +.Bl -tag -width indent +.It Va AddressFamily Li = ipv4 | ipv6 | any Pq any +This option affects the address family of listening and outgoing sockets. +If +.Qq any +is selected, then depending on the operating system both IPv4 and IPv6 or just +IPv6 listening sockets will be created. +.It Va BindToAddress Li = Ar address Oo Ar port Oc Bq experimental +If your computer has more than one IPv4 or IPv6 address, +.Nm tinc +will by default listen on all of them for incoming connections. +Multiple +.Va BindToAddress +variables may be specified, +in which case listening sockets for each specified address are made. +.Pp +If no +.Ar port +is specified, the socket will be bound to the port specified by the +.Va Port +option, or to port 655 if neither is given. +To only bind to a specific port but not to a specific address, use +.Li * +for the +.Ar address . +.Pp +This option may not work on all platforms. +.It Va BindToInterface Li = Ar interface Bq experimental +If your computer has more than one network interface, +.Nm tinc +will by default listen on all of them for incoming connections. +It is possible to bind only to a single interface with this variable. +.Pp +This option may not work on all platforms. +Also, on some platforms it will not actually bind to an interface, +but rather to the address that the interface has at the moment a socket is created. +.It Va Broadcast Li = no | mst | direct Po mst Pc Bq experimental +This option selects the way broadcast packets are sent to other daemons. +NOTE: all nodes in a VPN must use the same +.Va Broadcast +mode, otherwise routing loops can form. +.Bl -tag -width indent +.It no +Broadcast packets are never sent to other nodes. +.It mst +Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree. +This ensures broadcast packets reach all nodes. +.It direct +Broadcast packets are sent directly to all nodes that can be reached directly. +Broadcast packets received from other nodes are never forwarded. +If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. +.El +.It Va ConnectTo Li = Ar name +Specifies which other tinc daemon to connect to on startup. +Multiple +.Va ConnectTo +variables may be specified, +in which case outgoing connections to each specified tinc daemon are made. +The names should be known to this tinc daemon +(i.e., there should be a host configuration file for the name on the +.Va ConnectTo +line). +.Pp +If you don't specify a host with +.Va ConnectTo , +.Nm tinc +won't try to connect to other daemons at all, +and will instead just listen for incoming connections. +.It Va DecrementTTL Li = yes | no Po no Pc Bq experimental +When enabled, +.Nm tinc +will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets, +before forwarding a received packet to the virtual network device or to another node, +and will drop packets that have a TTL value of zero, +in which case it will send an ICMP Time Exceeded packet back. +.Pp +Do not use this option if you use switch mode and want to use IPv6. +.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc +The virtual network device to use. +.Nm tinc +will automatically detect what kind of device it is. +Note that you can only use one device per daemon. +Under Windows, use +.Va Interface +instead of +.Va Device . +The info pages of the tinc package contain more information +about configuring the virtual network device. +.It Va DeviceType Li = Ar type Pq platform dependent +The type of the virtual network device. +Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. +However, this option can be used to select one of the special interface types, if support for them is compiled in. +.Bl -tag -width indent +.It dummy +Use a dummy interface. +No packets are ever read or written to a virtual network device. +Useful for testing, or when setting up a node that only forwards packets for other nodes. +.It raw_socket +Open a raw socket, and bind it to a pre-existing +.Va Interface +(eth0 by default). +All packets are read from this interface. +Packets received for the local node are written to the raw socket. +However, at least on Linux, the operating system does not process IP packets destined for the local host. +.It multicast +Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using +.Va Device . +Packets are read from and written to this multicast socket. +This can be used to connect to UML, QEMU or KVM instances listening on the same multicast address. +Do NOT connect multiple +.Nm tinc +daemons to the same multicast address, this will very likely cause routing loops. +Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. +.It uml Pq not compiled in by default +Create a UNIX socket with the filename specified by +.Va Device , +or +.Pa @runstatedir@/ Ns Ar NETNAME Ns Pa .umlsocket +if not specified. +.Nm tinc +will wait for a User Mode Linux instance to connect to this socket. +.It vde Pq not compiled in by default +Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, +using the UNIX socket specified by +.Va Device , +or +.Pa @runstatedir@/vde.ctl +if not specified. +.El +Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, +it can be used to change the way packets are interpreted: +.Bl -tag -width indent +.It tun Pq BSD and Linux +Set type to tun. +Depending on the platform, this can either be with or without an address family header (see below). +.It tunnohead Pq BSD +Set type to tun without an address family header. +Tinc will expect packets read from the virtual network device to start with an IP header. +On some platforms IPv6 packets cannot be read from or written to the device in this mode. +.It tunifhead Pq BSD +Set type to tun with an address family header. +Tinc will expect packets read from the virtual network device +to start with a four byte header containing the address family, +followed by an IP header. +This mode should support both IPv4 and IPv6 packets. +.It utun Pq OS X +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +This mode should support both IPv4 and IPv6 packets. +.It tap Pq BSD and Linux +Set type to tap. +Tinc will expect packets read from the virtual network device +to start with an Ethernet header. +.El +.It Va DirectOnly Li = yes | no Po no Pc Bq experimental +When this option is enabled, packets that cannot be sent directly to the destination node, +but which would have to be forwarded by an intermediate node, are dropped instead. +When combined with the IndirectData option, +packets for nodes for which we do not have a meta connection with are also dropped. +.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental +This option selects the way indirect packets are forwarded. +.Bl -tag -width indent +.It off +Incoming packets that are not meant for the local node, +but which should be forwarded to another node, are dropped. +.It internal +Incoming packets that are meant for another node are forwarded by tinc internally. +.Pp +This is the default mode, and unless you really know you need another forwarding mode, don't change it. +.It kernel +Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. +This is less efficient, but allows the kernel to apply its routing and firewall rules on them, +and can also help debugging. +.El +.It Va GraphDumpFile Li = Ar filename Bq experimental +If this option is present, +.Nm tinc +will dump the current network graph to the file +.Ar filename +every minute, unless there were no changes to the graph. +The file is in a format that can be read by graphviz tools. +If +.Ar filename +starts with a pipe symbol |, +then the rest of the filename is interpreted as a shell command +that is executed, the graph is then sent to stdin. +.It Va Hostnames Li = yes | no Pq no +This option selects whether IP addresses (both real and on the VPN) should +be resolved. Since DNS lookups are blocking, it might affect tinc's +efficiency, even stopping the daemon for a few seconds every time it does +a lookup if your DNS server is not responding. +.Pp +This does not affect resolving hostnames to IP addresses from the +host configuration files, but whether hostnames should be resolved while logging. +.It Va IffOneQueue Li = yes | no Po no Pc Bq experimental +(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. +.It Va Interface Li = Ar interface +Defines the name of the interface corresponding to the virtual network device. +Depending on the operating system and the type of device this may or may not actually set the name of the interface. +Under Windows, this variable is used to select which network interface will be used. +If you specified a +.Va Device , +this variable is almost always already correctly set. +.It Va KeyExpire Li = Ar seconds Pq 3600 +This option controls the period the encryption keys used to encrypt the data are valid. +It is common practice to change keys at regular intervals to make it even harder for crackers, +even though it is thought to be nearly impossible to crack a single key. +.It Va LocalDiscovery Li = yes | no Po no Pc Bq experimental +When enabled, +.Nm tinc +will try to detect peers that are on the same local network. +This will allow direct communication using LAN addresses, even if both peers are behind a NAT +and they only ConnectTo a third node outside the NAT, +which normally would prevent the peers from learning each other's LAN address. +.Pp +Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. +This feature may not work in all possible situations. +.It Va MACExpire Li = Ar seconds Pq 600 +This option controls the amount of time MAC addresses are kept before they are removed. +This only has effect when +.Va Mode +is set to +.Qq switch . +.It Va MaxTimeout Li = Ar seconds Pq 900 +This is the maximum delay before trying to reconnect to other tinc daemons. +.It Va Mode Li = router | switch | hub Pq router +This option selects the way packets are routed to other daemons. +.Bl -tag -width indent +.It router +In this mode +.Va Subnet +variables in the host configuration files will be used to form a routing table. +Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. +.Pp +This is the default mode, and unless you really know you need another mode, don't change it. +.It switch +In this mode the MAC addresses of the packets on the VPN will be used to +dynamically create a routing table just like an Ethernet switch does. +Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode +at the cost of frequent broadcast ARP requests and routing table updates. +.Pp +This mode is primarily useful if you want to bridge Ethernet segments. +.It hub +This mode is almost the same as the switch mode, but instead +every packet will be broadcast to the other daemons +while no routing table is managed. +.El +.It Va Name Li = Ar name Bq required +This is the name which identifies this tinc daemon. +It must be unique for the virtual private network this daemon will connect to. +The Name may only consist of alphanumeric and underscore characters. +If +.Va Name +starts with a +.Li $ , +then the contents of the environment variable that follows will be used. +In that case, invalid characters will be converted to underscores. +If +.Va Name +is +.Li $HOST , +but no such environment variable exist, the hostname will be read using the gethostname() system call. +.It Va PingInterval Li = Ar seconds Pq 60 +The number of seconds of inactivity that +.Nm tinc +will wait before sending a probe to the other end. +.It Va PingTimeout Li = Ar seconds Pq 5 +The number of seconds to wait for a response to pings or to allow meta +connections to block. If the other end doesn't respond within this time, +the connection is terminated, +and the others will be notified of this. +.It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental +When this option is enabled the value of the TOS field of tunneled IPv4 packets +will be inherited by the UDP packets that are sent out. +.It Va PrivateKey Li = Ar key Bq obsolete +The private RSA key of this tinc daemon. +It will allow this tinc daemon to authenticate itself to other daemons. +.It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc +The file in which the private RSA key of this tinc daemon resides. +.It Va ProcessPriority Li = low | normal | high +When this option is used the priority of the tincd process will be adjusted. +Increasing the priority may help to reduce latency and packet loss on the VPN. +.It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental +Use a proxy when making outgoing connections. +The following proxy types are currently supported: +.Bl -tag -width indent +.It socks4 Ar address Ar port Op Ar username +Connects to the proxy using the SOCKS version 4 protocol. +Optionally, a +.Ar username +can be supplied which will be passed on to the proxy server. +Only IPv4 connections can be proxied using SOCKS 4. +.It socks5 Ar address Ar port Op Ar username Ar password +Connect to the proxy using the SOCKS version 5 protocol. +If a +.Ar username +and +.Ar password +are given, basic username/password authentication will be used, +otherwise no authentication will be used. +.It http Ar address Ar port +Connects to the proxy and sends a HTTP CONNECT request. +.It exec Ar command +Executes the given +.Ar command +which should set up the outgoing connection. +The environment variables +.Ev NAME , +.Ev NODE , +.Ev REMOTEADDRES +and +.Ev REMOTEPORT +are available. +.El +.It Va ReplayWindow Li = Ar bytes Pq 16 +This is the size of the replay tracking window for each remote node, in bytes. +The window is a bitfield which tracks 1 packet per bit, so for example +the default setting of 16 will track up to 128 packets in the window. In high +bandwidth scenarios, setting this to a higher value can reduce packet loss from +the interaction of replay tracking with underlying real packet loss and/or +reordering. Setting this to zero will disable replay tracking completely and +pass all traffic, but leaves tinc vulnerable to replay-based attacks on your +traffic. +.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental +When this option is enabled tinc will only use Subnet statements which are +present in the host config files in the local +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ +directory. Subnets learned via connections to other nodes and which are not +present in the local host config files are ignored. +.It Va TunnelServer Li = yes | no Po no Pc Bq experimental +When this option is enabled tinc will no longer forward information between other tinc daemons, +and will only allow connections with nodes for which host config files are present in the local +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ +directory. +Setting this options also implicitly sets StrictSubnets. +.It Va UDPRcvBuf Li = Ar bytes Pq OS default +Sets the socket receive buffer size for the UDP socket, in bytes. +If unset, the default buffer size will be used by the operating system. +.It Va UDPSndBuf Li = Ar bytes Pq OS default +Sets the socket send buffer size for the UDP socket, in bytes. +If unset, the default buffer size will be used by the operating system. +.El +.Sh HOST CONFIGURATION FILES +The host configuration files contain all information needed +to establish a connection to those hosts. +A host configuration file is also required for the local tinc daemon, +it will use it to read in it's listen port, public key and subnets. +.Pp +The idea is that these files are portable. +You can safely mail your own host configuration file to someone else. +That other person can then copy it to his own hosts directory, +and now his tinc daemon will be able to connect to your tinc daemon. +Since host configuration files only contain public keys, +no secrets are revealed by sending out this information. +.Bl -tag -width indent +.It Va Address Li = Ar address Oo Ar port Oc Bq recommended +The IP address or hostname of this tinc daemon on the real network. +This will only be used when trying to make an outgoing connection to this tinc daemon. +Optionally, a port can be specified to use for this address. +Multiple +.Va Address +variables can be specified, in which case each address will be tried until a working +connection has been established. +.It Va Cipher Li = Ar cipher Pq aes-256-cbc +The symmetric cipher algorithm used to encrypt UDP packets. +Any cipher supported by LibreSSL or OpenSSL is recognised. +Furthermore, specifying +.Qq none +will turn off packet encryption. +It is best to use only those ciphers which support CBC mode. +.It Va ClampMSS Li = yes | no Pq yes +This option specifies whether tinc should clamp the maximum segment size (MSS) +of TCP packets to the path MTU. This helps in situations where ICMP +Fragmentation Needed or Packet too Big messages are dropped by firewalls. +.It Va Compression Li = Ar level Pq 0 +This option sets the level of compression used for UDP packets. +Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), +10 (fast lzo) and 11 (best lzo). +.It Va Digest Li = Ar digest Pq sha256 +The digest algorithm used to authenticate UDP packets. +Any digest supported by LibreSSL or OpenSSL is recognised. +Furthermore, specifying +.Qq none +will turn off packet authentication. +.It Va IndirectData Li = yes | no Pq no +When set to yes, only nodes which already have a meta connection to you +will try to establish direct communication with you. +It is best to leave this option out or set it to no. +.It Va MACLength Li = Ar length Pq 4 +The length of the message authentication code used to authenticate UDP packets. +Can be anything from +.Qq 0 +up to the length of the digest produced by the digest algorithm. +.It Va PMTU Li = Ar mtu Po 1514 Pc +This option controls the initial path MTU to this node. +.It Va PMTUDiscovery Li = yes | no Po yes Pc +When this option is enabled, tinc will try to discover the path MTU to this node. +After the path MTU has been discovered, it will be enforced on the VPN. +.It Va Port Li = Ar port Pq 655 +The port number on which this tinc daemon is listening for incoming connections, +which is used if no port number is specified in an +.Va Address +statement. +.It Va PublicKey Li = Ar key Bq obsolete +The public RSA key of this tinc daemon. +It will be used to cryptographically verify it's identity and to set up a secure connection. +.It Va PublicKeyFile Li = Ar filename Bq obsolete +The file in which the public RSA key of this tinc daemon resides. +.Pp +From version 1.0pre4 on +.Nm tinc +will store the public key directly into the host configuration file in PEM format, +the above two options then are not necessary. +Either the PEM format is used, or exactly one of the above two options must be specified +in each host configuration file, +if you want to be able to establish a connection with that host. +.It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength Ns Op Li # Ns Ar weight +The subnet which this tinc daemon will serve. +.Nm tinc +tries to look up which other daemon it should send a packet to by searching the appropriate subnet. +If the packet matches a subnet, +it will be sent to the daemon who has this subnet in his host configuration file. +Multiple +.Va Subnet +variables can be specified. +.Pp +Subnets can either be single MAC, IPv4 or IPv6 addresses, +in which case a subnet consisting of only that single address is assumed, +or they can be a IPv4 or IPv6 network address with a prefixlength. +For example, IPv4 subnets must be in a form like 192.168.1.0/24, +where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask. +Note that subnets like 192.168.1.1/24 are invalid! +Read a networking HOWTO/FAQ/guide if you don't understand this. +IPv6 subnets are notated like fec0:0:0:1::/64. +MAC addresses are notated like 0:1a:2b:3c:4d:5e. +.Pp +A Subnet can be given a weight to indicate its priority over identical Subnets +owned by different nodes. The default weight is 10. Lower values indicate +higher priority. Packets will be sent to the node with the highest priority, +unless that node is not reachable, in which case the node with the next highest +priority will be tried, and so on. +.It Va TCPOnly Li = yes | no Pq no Bq obsolete +If this variable is set to yes, +then the packets are tunnelled over the TCP connection instead of a UDP connection. +This is especially useful for those who want to run a tinc daemon +from behind a masquerading firewall, +or if UDP packet routing is disabled somehow. +Setting this options also implicitly sets IndirectData. +.Pp +Since version 1.0.10, tinc will automatically detect whether communication via +UDP is possible or not. +.El +.Sh SCRIPTS +Apart from reading the server and host configuration files, +tinc can also run scripts at certain moments. +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. +.Pp +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. +.Pp +Under Windows (not Cygwin), the scripts must have the extension +.Pa .bat . +.Bl -tag -width indent +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up +This is the most important script. +If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. +It should be used to set up the corresponding network interface, +but can also be used to start other things. +.Pp +Under Windows you can use the Network Connections control panel instead of creating this script. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down +This script is started right before the tinc daemon quits. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up +This script is started when the tinc daemon with name +.Ar HOST +becomes reachable. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -down +This script is started when the tinc daemon with name +.Ar HOST +becomes unreachable. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-up +This script is started when any host becomes reachable. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-down +This script is started when any host becomes unreachable. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-up +This script is started when a Subnet becomes reachable. +The Subnet and the node it belongs to are passed in environment variables. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down +This script is started when a Subnet becomes unreachable. +.El +.Pp +The scripts are started without command line arguments, but can make use of certain environment variables. +Under UNIX like operating systems the names of environment variables must be preceded by a +.Li $ +in scripts. +Under Windows, in +.Pa .bat +files, they have to be put between +.Li % +signs. +.Bl -tag -width indent +.It Ev NETNAME +If a netname was specified, this environment variable contains it. +.It Ev NAME +Contains the name of this tinc daemon. +.It Ev DEVICE +Contains the name of the virtual network device that tinc uses. +.It Ev INTERFACE +Contains the name of the virtual network interface that tinc uses. +This should be used for commands like +.Pa ifconfig . +.It Ev NODE +When a host becomes (un)reachable, this is set to its name. +If a subnet becomes (un)reachable, this is set to the owner of that subnet. +.It Ev REMOTEADDRESS +When a host becomes (un)reachable, this is set to its real address. +.It Ev REMOTEPORT +When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons. +.It Ev SUBNET +When a subnet becomes (un)reachable, this is set to the subnet. +.It Ev WEIGHT +When a subnet becomes (un)reachable, this is set to the subnet weight. +.El +.Pp +Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command +.Nm chmod Li a+x Pa script . +.Sh FILES +The most important files are: +.Bl -tag -width indent +.It Pa @sysconfdir@/tinc/ +The top directory for configuration files. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf +The default name of the server configuration file for net +.Ar NETNAME . +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/ +Optional directory from which any *.conf file will be loaded +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ +Host configuration files are kept in this directory. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up +If an executable file with this name exists, +it will be executed right after the tinc daemon has connected to the virtual network device. +It can be used to set up the corresponding network interface. +.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down +If an executable file with this name exists, +it will be executed right before the tinc daemon is going to close +its connection to the virtual network device. +.El +.Sh SEE ALSO +.Xr tincd 8 , +.Pa https://www.tinc-vpn.org/ , +.Pa http://www.tldp.org/LDP/nag2/ . +.Pp +The full documentation for +.Nm tinc +is maintained as a Texinfo manual. +If the info and tinc programs are properly installed at your site, the command +.Ic info tinc +should give you access to the complete manual. +.Pp +.Nm tinc +comes with ABSOLUTELY NO WARRANTY. +This is free software, and you are welcome to redistribute it under certain conditions; +see the file COPYING for details. diff --git a/doc/tinc.info b/doc/tinc.info index 71dcb80..7ee4d91 100644 --- a/doc/tinc.info +++ b/doc/tinc.info @@ -1,17 +1,15 @@ -This is tinc.info, produced by makeinfo version 4.1 from tinc.texi. +This is tinc.info, produced by makeinfo version 6.7 from tinc.texi. INFO-DIR-SECTION Networking tools START-INFO-DIR-ENTRY * tinc: (tinc). The tinc Manual. END-INFO-DIR-ENTRY - This is the info manual for tinc, a Virtual Private Network daemon. +This is the info manual for tinc version 1.0.36, a Virtual Private +Network daemon. - Copyright (C) 1998-2002 Ivo Timmermans , -Guus Sliepen and Wessel Dankers -. - - $Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ + Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen + and Wessel Dankers . Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -23,57 +21,2770 @@ entire resulting derived work is distributed under the terms of a permission notice identical to this one.  -Indirect: -tinc.info-1: 888 -tinc.info-2: 49234 +File: tinc.info, Node: Top, Next: Introduction, Up: (dir) + +Top +*** + +* Menu: + +* Introduction:: +* Preparations:: +* Installation:: +* Configuration:: +* Running tinc:: +* Technical information:: +* Platform specific information:: +* About us:: +* Concept Index:: All used terms explained + + +File: tinc.info, Node: Introduction, Next: Preparations, Prev: Top, Up: Top + +1 Introduction +************** + +Tinc is a Virtual Private Network (VPN) daemon that uses tunneling and +encryption to create a secure private network between hosts on the +Internet. + + Because the tunnel appears to the IP level network code as a normal +network device, there is no need to adapt any existing software. The +encrypted tunnels allows VPN sites to share information with each other +over the Internet without exposing any information to others. + + This document is the manual for tinc. Included are chapters on how +to configure your computer to use tinc, as well as the configuration +process of tinc itself. + +* Menu: + +* Virtual Private Networks:: +* tinc:: About tinc +* Supported platforms:: + + +File: tinc.info, Node: Virtual Private Networks, Next: tinc, Up: Introduction + +1.1 Virtual Private Networks +============================ + +A Virtual Private Network or VPN is a network that can only be accessed +by a few elected computers that participate. This goal is achievable in +more than just one way. + + Private networks can consist of a single stand-alone Ethernet LAN. Or +even two computers hooked up using a null-modem cable. In these cases, +it is obvious that the network is _private_, no one can access it from +the outside. But if your computers are linked to the Internet, the +network is not private anymore, unless one uses firewalls to block all +private traffic. But then, there is no way to send private data to +trusted computers on the other end of the Internet. + + This problem can be solved by using _virtual_ networks. Virtual +networks can live on top of other networks, but they use encapsulation +to keep using their private address space so they do not interfere with +the Internet. Mostly, virtual networks appear like a single LAN, even +though they can span the entire world. But virtual networks can't be +secured by using firewalls, because the traffic that flows through it +has to go through the Internet, where other people can look at it. + + As is the case with either type of VPN, anybody could eavesdrop. Or +worse, alter data. Hence it's probably advisable to encrypt the data +that flows over the network. + + When one introduces encryption, we can form a true VPN. Other people +may see encrypted traffic, but if they don't know how to decipher it +(they need to know the key for that), they cannot read the information +that flows through the VPN. This is what tinc was made for. + + +File: tinc.info, Node: tinc, Next: Supported platforms, Prev: Virtual Private Networks, Up: Introduction + +1.2 tinc +======== + +I really don't quite remember what got us started, but it must have been +Guus' idea. He wrote a simple implementation (about 50 lines of C) that +used the ethertap device that Linux knows of since somewhere about +kernel 2.1.60. It didn't work immediately and he improved it a bit. At +this stage, the project was still simply called "vpnd". + + Since then, a lot has changed--to say the least. + + Tinc now supports encryption, it consists of a single daemon (tincd) +for both the receiving and sending end, it has become largely +runtime-configurable--in short, it has become a full-fledged +professional package. + + Tinc also allows more than two sites to connect to each other and +form a single VPN. Traditionally VPNs are created by making tunnels, +which only have two endpoints. Larger VPNs with more sites are created +by adding more tunnels. Tinc takes another approach: only endpoints are +specified, the software itself will take care of creating the tunnels. +This allows for easier configuration and improved scalability. + + A lot can--and will be--changed. We have a number of things that we +would like to see in the future releases of tinc. Not everything will +be available in the near future. Our first objective is to make tinc +work perfectly as it stands, and then add more advanced features. + + Meanwhile, we're always open-minded towards new ideas. And we're +available too. + + +File: tinc.info, Node: Supported platforms, Prev: tinc, Up: Introduction + +1.3 Supported platforms +======================= + +Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, +Mac OS X (Darwin), Solaris, and Windows (both natively and in a Cygwin +environment), with various hardware architectures. These are some of +the platforms that are supported by the universal tun/tap device driver +or other virtual network device drivers. Without such a driver, tinc +will most likely compile and run, but it will not be able to send or +receive data packets. + + For an up to date list of supported platforms, please check the list +on our website: . + + +File: tinc.info, Node: Preparations, Next: Installation, Prev: Introduction, Up: Top + +2 Preparations +************** + +This chapter contains information on how to prepare your system to +support tinc. + +* Menu: + +* Configuring the kernel:: +* Libraries:: + + +File: tinc.info, Node: Configuring the kernel, Next: Libraries, Up: Preparations + +2.1 Configuring the kernel +========================== + +* Menu: + +* Configuration of Linux kernels:: +* Configuration of FreeBSD kernels:: +* Configuration of OpenBSD kernels:: +* Configuration of NetBSD kernels:: +* Configuration of Solaris kernels:: +* Configuration of Darwin (Mac OS X) kernels:: +* Configuration of Windows:: + + +File: tinc.info, Node: Configuration of Linux kernels, Next: Configuration of FreeBSD kernels, Up: Configuring the kernel + +2.1.1 Configuration of Linux kernels +------------------------------------ + +For tinc to work, you need a kernel that supports the Universal tun/tap +device. Most distributions come with kernels that already support this. +Here are the options you have to turn on when configuring a new kernel: + + Code maturity level options + [*] Prompt for development and/or incomplete code/drivers + Network device support + Universal tun/tap device driver support + + It's not necessary to compile this driver as a module, even if you +are going to run more than one instance of tinc. + + If you decide to build the tun/tap driver as a kernel module, add +these lines to '/etc/modules.conf': + + alias char-major-10-200 tun + + +File: tinc.info, Node: Configuration of FreeBSD kernels, Next: Configuration of OpenBSD kernels, Prev: Configuration of Linux kernels, Up: Configuring the kernel + +2.1.2 Configuration of FreeBSD kernels +-------------------------------------- + +For FreeBSD version 4.1 and higher, tun and tap drivers are included in +the default kernel configuration. The tap driver can be loaded with +'kldload if_tap', or by adding 'if_tap_load="YES"' to +'/boot/loader.conf'. + + +File: tinc.info, Node: Configuration of OpenBSD kernels, Next: Configuration of NetBSD kernels, Prev: Configuration of FreeBSD kernels, Up: Configuring the kernel + +2.1.3 Configuration of OpenBSD kernels +-------------------------------------- + +Recent versions of OpenBSD come with both tun and tap devices enabled in +the default kernel configuration. + + +File: tinc.info, Node: Configuration of NetBSD kernels, Next: Configuration of Solaris kernels, Prev: Configuration of OpenBSD kernels, Up: Configuring the kernel + +2.1.4 Configuration of NetBSD kernels +------------------------------------- + +For NetBSD version 1.5.2 and higher, the tun driver is included in the +default kernel configuration. + + Tunneling IPv6 may not work on NetBSD's tun device. + + +File: tinc.info, Node: Configuration of Solaris kernels, Next: Configuration of Darwin (Mac OS X) kernels, Prev: Configuration of NetBSD kernels, Up: Configuring the kernel + +2.1.5 Configuration of Solaris kernels +-------------------------------------- + +For Solaris 8 (SunOS 5.8) and higher, the tun driver may or may not be +included in the default kernel configuration. If it isn't, the source +can be downloaded from . For x86 and +sparc64 architectures, precompiled versions can be found at +. If the 'net/if_tun.h' +header file is missing, install it from the source package. + + +File: tinc.info, Node: Configuration of Darwin (Mac OS X) kernels, Next: Configuration of Windows, Prev: Configuration of Solaris kernels, Up: Configuring the kernel + +2.1.6 Configuration of Darwin (Mac OS X) kernels +------------------------------------------------ + +Tinc on Darwin relies on a tunnel driver for its data acquisition from +the kernel. OS X version 10.6.8 and later have a built-in tun driver +called "utun". Tinc also supports the driver from +, which supports both tun and tap +style devices. + + By default, tinc expects the tuntaposx driver to be installed. To +use the utun driver, set add 'Device = utunX' to 'tinc.conf', where X is +the desired number for the utun interface. You can also omit the +number, in which case the first free number will be chosen. + + +File: tinc.info, Node: Configuration of Windows, Prev: Configuration of Darwin (Mac OS X) kernels, Up: Configuring the kernel + +2.1.7 Configuration of Windows +------------------------------ + +You will need to install the latest TAP-Win32 driver from OpenVPN. You +can download it from +. Using the +Network Connections control panel, configure the TAP-Win32 network +interface in the same way as you would do from the tinc-up script, as +explained in the rest of the documentation. + + +File: tinc.info, Node: Libraries, Prev: Configuring the kernel, Up: Preparations + +2.2 Libraries +============= + +Before you can configure or build tinc, you need to have the LibreSSL or +OpenSSL, zlib and lzo libraries installed on your system. If you try to +configure tinc without having them installed, configure will give you an +error message, and stop. + +* Menu: + +* LibreSSL/OpenSSL:: +* zlib:: +* lzo:: + + +File: tinc.info, Node: LibreSSL/OpenSSL, Next: zlib, Up: Libraries + +2.2.1 LibreSSL/OpenSSL +---------------------- + +For all cryptography-related functions, tinc uses the functions provided +by the LibreSSL or the OpenSSL library. + + If this library is not installed, you will get an error when +configuring tinc for build. Support for running tinc with other +cryptographic libraries installed _may_ be added in the future. + + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. + + If your operating system comes neither with LibreSSL or OpenSSL, you +have to install one manually. It is recommended that you get the latest +version of LibreSSL from . Instructions on +how to configure, build and install this package are included within the +package. Please make sure you build development and runtime libraries +(which is the default). + + If you installed the LibreSSL or OpenSSL libraries from source, it +may be necessary to let configure know where they are, by passing +configure one of the -with-openssl-* parameters. Note that you even +have to use -with-openssl-* if you are using LibreSSL. + + --with-openssl=DIR LibreSSL/OpenSSL library and headers prefix + --with-openssl-include=DIR LibreSSL/OpenSSL headers directory + (Default is OPENSSL_DIR/include) + --with-openssl-lib=DIR LibreSSL/OpenSSL library directory + (Default is OPENSSL_DIR/lib) + +License +....... + +The complete source code of tinc is covered by the GNU GPL version 2. +Since the license under which OpenSSL is distributed is not directly +compatible with the terms of the GNU GPL +, we include an +exemption to the GPL (see also the file COPYING.README) to allow +everyone to create a statically or dynamically linked executable: + + This program is released under the GPL with the additional + exemption that compiling, linking, and/or using OpenSSL is allowed. + You may provide binary packages linked to the OpenSSL libraries, + provided that all other requirements of the GPL are met. + + Since the LZO library used by tinc is also covered by the GPL, we +also present the following exemption: + + Hereby I grant a special exception to the tinc VPN project + (https://www.tinc-vpn.org/) to link the LZO library with the + OpenSSL library (https://www.openssl.org). + + Markus F.X.J. Oberhumer + + +File: tinc.info, Node: zlib, Next: lzo, Prev: LibreSSL/OpenSSL, Up: Libraries + +2.2.2 zlib +---------- + +For the optional compression of UDP packets, tinc uses the functions +provided by the zlib library. + + If this library is not installed, you will get an error when running +the configure script. You can either install the zlib library, or +disable support for zlib compression by using the "-disable-zlib" option +when running the configure script. Note that if you disable support for +zlib, the resulting binary will not work correctly on VPNs where zlib +compression is used. + + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. + + If you have to install zlib manually, you can get the source code +from . Instructions on how to configure, build and +install this package are included within the package. Please make sure +you build development and runtime libraries (which is the default). + + +File: tinc.info, Node: lzo, Prev: zlib, Up: Libraries + +2.2.3 lzo +--------- + +Another form of compression is offered using the LZO library. + + If this library is not installed, you will get an error when running +the configure script. You can either install the LZO library, or +disable support for LZO compression by using the "-disable-lzo" option +when running the configure script. Note that if you disable support for +LZO, the resulting binary will not work correctly on VPNs where LZO +compression is used. + + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. + + If you have to install lzo manually, you can get the source code from +. Instructions on how to +configure, build and install this package are included within the +package. Please make sure you build development and runtime libraries +(which is the default). + + +File: tinc.info, Node: Installation, Next: Configuration, Prev: Preparations, Up: Top + +3 Installation +************** + +If you use Debian, you may want to install one of the precompiled +packages for your system. These packages are equipped with system +startup scripts and sample configurations. + + If you cannot use one of the precompiled packages, or you want to +compile tinc for yourself, you can use the source. The source is +distributed under the GNU General Public License (GPL). Download the +source from the download page (https://www.tinc-vpn.org/download/). + + Tinc comes in a convenient autoconf/automake package, which you can +just treat the same as any other package. Which is just untar it, type +'./configure' and then 'make'. More detailed instructions are in the +file 'INSTALL', which is included in the source distribution. + +* Menu: + +* Building and installing tinc:: +* System files:: + + +File: tinc.info, Node: Building and installing tinc, Next: System files, Up: Installation + +3.1 Building and installing tinc +================================ + +Detailed instructions on configuring the source, building tinc and +installing tinc can be found in the file called 'INSTALL'. + + If you happen to have a binary package for tinc for your +distribution, you can use the package management tools of that +distribution to install tinc. The documentation that comes along with +your distribution will tell you how to do that. + +* Menu: + +* Darwin (Mac OS X) build environment:: +* Cygwin (Windows) build environment:: +* MinGW (Windows) build environment:: + + +File: tinc.info, Node: Darwin (Mac OS X) build environment, Next: Cygwin (Windows) build environment, Up: Building and installing tinc + +3.1.1 Darwin (Mac OS X) build environment +----------------------------------------- + +In order to build tinc on Darwin, you need to install Xcode from +. It might also help to install a +recent version of Fink from . + + You need to download and install LibreSSL (or OpenSSL) and LZO, +either directly from their websites (see *note Libraries::) or using +Fink. + + +File: tinc.info, Node: Cygwin (Windows) build environment, Next: MinGW (Windows) build environment, Prev: Darwin (Mac OS X) build environment, Up: Building and installing tinc + +3.1.2 Cygwin (Windows) build environment +---------------------------------------- + +If Cygwin hasn't already been installed, install it directly from +. + + When tinc is compiled in a Cygwin environment, it can only be run in +this environment, but all programs, including those started outside the +Cygwin environment, will be able to use the VPN. It will also support +all features. + + +File: tinc.info, Node: MinGW (Windows) build environment, Prev: Cygwin (Windows) build environment, Up: Building and installing tinc + +3.1.3 MinGW (Windows) build environment +--------------------------------------- + +You will need to install the MinGW environment from +. You also need to download and install LibreSSL +(or OpenSSL) and LZO. + + When tinc is compiled using MinGW it runs natively under Windows, it +is not necessary to keep MinGW installed. + + When detaching, tinc will install itself as a service, which will be +restarted automatically after reboots. + + +File: tinc.info, Node: System files, Prev: Building and installing tinc, Up: Installation + +3.2 System files +================ + +Before you can run tinc, you must make sure you have all the needed +files on your system. + +* Menu: + +* Device files:: +* Other files:: + + +File: tinc.info, Node: Device files, Next: Other files, Up: System files + +3.2.1 Device files +------------------ + +Most operating systems nowadays come with the necessary device files by +default, or they have a mechanism to create them on demand. + + If you use Linux and do not have udev installed, you may need to +create the following device file if it does not exist: + + mknod -m 600 /dev/net/tun c 10 200 + + +File: tinc.info, Node: Other files, Prev: Device files, Up: System files + +3.2.2 Other files +----------------- + +'/etc/networks' +............... + +You may add a line to '/etc/networks' so that your VPN will get a +symbolic name. For example: + + myvpn 10.0.0.0 + +'/etc/services' +............... + +You may add this line to '/etc/services'. The effect is that you may +supply a 'tinc' as a valid port number to some programs. The number 655 +is registered with the IANA. + + tinc 655/tcp TINC + tinc 655/udp TINC + # Ivo Timmermans + + +File: tinc.info, Node: Configuration, Next: Running tinc, Prev: Installation, Up: Top + +4 Configuration +*************** + +* Menu: + +* Configuration introduction:: +* Multiple networks:: +* How connections work:: +* Configuration files:: +* Generating keypairs:: +* Network interfaces:: +* Example configuration:: + + +File: tinc.info, Node: Configuration introduction, Next: Multiple networks, Up: Configuration + +4.1 Configuration introduction +============================== + +Before actually starting to configure tinc and editing files, make sure +you have read this entire section so you know what to expect. Then, +make it clear to yourself how you want to organize your VPN: What are +the nodes (computers running tinc)? What IP addresses/subnets do they +have? What is the network mask of the entire VPN? Do you need special +firewall rules? Do you have to set up masquerading or forwarding rules? +Do you want to run tinc in router mode or switch mode? These questions +can only be answered by yourself, you will not find the answers in this +documentation. Make sure you have an adequate understanding of networks +in general. A good resource on networking is the Linux Network +Administrators Guide (http://www.tldp.org/LDP/nag2/). + + If you have everything clearly pictured in your mind, proceed in the +following order: First, generate the configuration files ('tinc.conf', +your host configuration file, 'tinc-up' and perhaps 'tinc-down'). Then +generate the keypairs. Finally, distribute the host configuration +files. These steps are described in the subsections below. + + +File: tinc.info, Node: Multiple networks, Next: How connections work, Prev: Configuration introduction, Up: Configuration + +4.2 Multiple networks +===================== + +In order to allow you to run more than one tinc daemon on one computer, +for instance if your computer is part of more than one VPN, you can +assign a NETNAME to your VPN. It is not required if you only run one +tinc daemon, it doesn't even have to be the same on all the sites of +your VPN, but it is recommended that you choose one anyway. + + We will assume you use a netname throughout this document. This +means that you call tincd with the -n argument, which will assign a +netname to this daemon. + + The effect of this is that the daemon will set its configuration root +to '/etc/tinc/NETNAME/', where NETNAME is your argument to the -n +option. You'll notice that it appears in syslog as 'tinc.NETNAME'. + + However, it is not strictly necessary that you call tinc with the -n +option. In this case, the network name would just be empty, and it will +be used as such. tinc now looks for files in '/etc/tinc/', instead of +'/etc/tinc/NETNAME/'; the configuration file should be +'/etc/tinc/tinc.conf', and the host configuration files are now expected +to be in '/etc/tinc/hosts/'. + + But it is highly recommended that you use this feature of tinc, +because it will be so much clearer whom your daemon talks to. Hence, we +will assume that you use it. + + +File: tinc.info, Node: How connections work, Next: Configuration files, Prev: Multiple networks, Up: Configuration + +4.3 How connections work +======================== + +When tinc starts up, it parses the command-line options and then reads +in the configuration file tinc.conf. If it sees one or more 'ConnectTo' +values pointing to other tinc daemons in that file, it will try to +connect to those other daemons. Whether this succeeds or not and +whether 'ConnectTo' is specified or not, tinc will listen for incoming +connection from other daemons. If you did specify a 'ConnectTo' value +and the other side is not responding, tinc will keep retrying. This +means that once started, tinc will stay running until you tell it to +stop, and failures to connect to other tinc daemons will not stop your +tinc daemon for trying again later. This means you don't have to +intervene if there are temporary network problems. + + There is no real distinction between a server and a client in tinc. +If you wish, you can view a tinc daemon without a 'ConnectTo' value as a +server, and one which does specify such a value as a client. It does +not matter if two tinc daemons have a 'ConnectTo' value pointing to each +other however. + + +File: tinc.info, Node: Configuration files, Next: Generating keypairs, Prev: How connections work, Up: Configuration + +4.4 Configuration files +======================= + +The actual configuration of the daemon is done in the file +'/etc/tinc/NETNAME/tinc.conf' and at least one other file in the +directory '/etc/tinc/NETNAME/hosts/'. + + An optional directory '/etc/tinc/NETNAME/conf.d' can be added from +which any .conf file will be read. + + These file consists of comments (lines started with a #) or +assignments in the form of + + Variable = Value. + + The variable names are case insensitive, and any spaces, tabs, +newlines and carriage returns are ignored. Note: it is not required +that you put in the '=' sign, but doing so improves readability. If you +leave it out, remember to replace it with at least one space character. + + The server configuration is complemented with host specific +configuration (see the next section). Although all host configuration +options for the local node listed in this document can also be put in +'/etc/tinc/NETNAME/tinc.conf', it is recommended to put host specific +configuration options in the host configuration file, as this makes it +easy to exchange with other nodes. + + In this section all valid variables are listed in alphabetical order. +The default value is given between parentheses, other comments are +between square brackets. + +* Menu: + +* Main configuration variables:: +* Host configuration variables:: +* Scripts:: +* How to configure:: + + +File: tinc.info, Node: Main configuration variables, Next: Host configuration variables, Up: Configuration files + +4.4.1 Main configuration variables +---------------------------------- + +AddressFamily = (any) + This option affects the address family of listening and outgoing + sockets. If any is selected, then depending on the operating + system both IPv4 and IPv6 or just IPv6 listening sockets will be + created. + +BindToAddress =
[] [experimental] + If your computer has more than one IPv4 or IPv6 address, tinc will + by default listen on all of them for incoming connections. + Multiple BindToAddress variables may be specified, in which case + listening sockets for each specified address are made. + + If no PORT is specified, the socket will be bound to the port + specified by the Port option, or to port 655 if neither is given. + To only bind to a specific port but not to a specific address, use + "*" for the ADDRESS. + + This option may not work on all platforms. + +BindToInterface = [experimental] + If you have more than one network interface in your computer, tinc + will by default listen on all of them for incoming connections. It + is possible to bind tinc to a single interface like eth0 or ppp0 + with this variable. + + This option may not work on all platforms. + +Broadcast = (mst) [experimental] + This option selects the way broadcast packets are sent to other + daemons. _NOTE: all nodes in a VPN must use the same Broadcast + mode, otherwise routing loops can form._ + + no + Broadcast packets are never sent to other nodes. + + mst + Broadcast packets are sent and forwarded via the VPN's Minimum + Spanning Tree. This ensures broadcast packets reach all + nodes. + + direct + Broadcast packets are sent directly to all nodes that can be + reached directly. Broadcast packets received from other nodes + are never forwarded. If the IndirectData option is also set, + broadcast packets will only be sent to nodes which we have a + meta connection to. + +ConnectTo = + Specifies which other tinc daemon to connect to on startup. + Multiple ConnectTo variables may be specified, in which case + outgoing connections to each specified tinc daemon are made. The + names should be known to this tinc daemon (i.e., there should be a + host configuration file for the name on the ConnectTo line). + + If you don't specify a host with ConnectTo, tinc won't try to + connect to other daemons at all, and will instead just listen for + incoming connections. + +DecrementTTL = (no) [experimental] + When enabled, tinc will decrement the Time To Live field in IPv4 + packets, or the Hop Limit field in IPv6 packets, before forwarding + a received packet to the virtual network device or to another node, + and will drop packets that have a TTL value of zero, in which case + it will send an ICMP Time Exceeded packet back. + + Do not use this option if you use switch mode and want to use IPv6. + +Device = ('/dev/tap0', '/dev/net/tun' or other depending on platform) + The virtual network device to use. Tinc will automatically detect + what kind of device it is. Under Windows, use INTERFACE instead of + DEVICE. Note that you can only use one device per daemon. See + also *note Device files::. + +DeviceType = (platform dependent) + The type of the virtual network device. Tinc will normally + automatically select the right type of tun/tap interface, and this + option should not be used. However, this option can be used to + select one of the special interface types, if support for them is + compiled in. + + dummy + Use a dummy interface. No packets are ever read or written to + a virtual network device. Useful for testing, or when setting + up a node that only forwards packets for other nodes. + + raw_socket + Open a raw socket, and bind it to a pre-existing INTERFACE + (eth0 by default). All packets are read from this interface. + Packets received for the local node are written to the raw + socket. However, at least on Linux, the operating system does + not process IP packets destined for the local host. + + multicast + Open a multicast UDP socket and bind it to the address and + port (separated by spaces) and optionally a TTL value + specified using DEVICE. Packets are read from and written to + this multicast socket. This can be used to connect to UML, + QEMU or KVM instances listening on the same multicast address. + Do NOT connect multiple tinc daemons to the same multicast + address, this will very likely cause routing loops. Also note + that this can cause decrypted VPN packets to be sent out on a + real network if misconfigured. + + uml (not compiled in by default) + Create a UNIX socket with the filename specified by DEVICE, or + '/run/NETNAME.umlsocket' if not specified. Tinc will wait for + a User Mode Linux instance to connect to this socket. + + vde (not compiled in by default) + Uses the libvdeplug library to connect to a Virtual + Distributed Ethernet switch, using the UNIX socket specified + by DEVICE, or '/run/vde.ctl' if not specified. + + Also, in case tinc does not seem to correctly interpret packets + received from the virtual network device, it can be used to change + the way packets are interpreted: + + tun (BSD and Linux) + Set type to tun. Depending on the platform, this can either + be with or without an address family header (see below). + + tunnohead (BSD) + Set type to tun without an address family header. Tinc will + expect packets read from the virtual network device to start + with an IP header. On some platforms IPv6 packets cannot be + read from or written to the device in this mode. + + tunifhead (BSD) + Set type to tun with an address family header. Tinc will + expect packets read from the virtual network device to start + with a four byte header containing the address family, + followed by an IP header. This mode should support both IPv4 + and IPv6 packets. + + utun (OS X) + Set type to utun. This is only supported on OS X version + 10.6.8 and higher, but doesn't require the tuntaposx module. + This mode should support both IPv4 and IPv6 packets. + + tap (BSD and Linux) + Set type to tap. Tinc will expect packets read from the + virtual network device to start with an Ethernet header. + +DirectOnly = (no) [experimental] + When this option is enabled, packets that cannot be sent directly + to the destination node, but which would have to be forwarded by an + intermediate node, are dropped instead. When combined with the + IndirectData option, packets for nodes for which we do not have a + meta connection with are also dropped. + +Forwarding = (internal) [experimental] + This option selects the way indirect packets are forwarded. + + off + Incoming packets that are not meant for the local node, but + which should be forwarded to another node, are dropped. + + internal + Incoming packets that are meant for another node are forwarded + by tinc internally. + + This is the default mode, and unless you really know you need + another forwarding mode, don't change it. + + kernel + Incoming packets are always sent to the TUN/TAP device, even + if the packets are not for the local node. This is less + efficient, but allows the kernel to apply its routing and + firewall rules on them, and can also help debugging. + +GraphDumpFile = [experimental] + If this option is present, tinc will dump the current network graph + to the file FILENAME every minute, unless there were no changes to + the graph. The file is in a format that can be read by graphviz + tools. If FILENAME starts with a pipe symbol |, then the rest of + the filename is interpreted as a shell command that is executed, + the graph is then sent to stdin. + +Hostnames = (no) + This option selects whether IP addresses (both real and on the VPN) + should be resolved. Since DNS lookups are blocking, it might + affect tinc's efficiency, even stopping the daemon for a few + seconds every time it does a lookup if your DNS server is not + responding. + + This does not affect resolving hostnames to IP addresses from the + configuration file, but whether hostnames should be resolved while + logging. + +IffOneQueue = (no) [experimental] + (Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. + +Interface = + Defines the name of the interface corresponding to the virtual + network device. Depending on the operating system and the type of + device this may or may not actually set the name of the interface. + Under Windows, this variable is used to select which network + interface will be used. If you specified a Device, this variable + is almost always already correctly set. + +KeyExpire = (3600) + This option controls the time the encryption keys used to encrypt + the data are valid. It is common practice to change keys at + regular intervals to make it even harder for crackers, even though + it is thought to be nearly impossible to crack a single key. + +LocalDiscovery = (no) [experimental] + When enabled, tinc will try to detect peers that are on the same + local network. This will allow direct communication using LAN + addresses, even if both peers are behind a NAT and they only + ConnectTo a third node outside the NAT, which normally would + prevent the peers from learning each other's LAN address. + + Currently, local discovery is implemented by sending broadcast + packets to the LAN during path MTU discovery. This feature may not + work in all possible situations. + +MACExpire = (600) + This option controls the amount of time MAC addresses are kept + before they are removed. This only has effect when Mode is set to + "switch". + +MaxTimeout = (900) + This is the maximum delay before trying to reconnect to other tinc + daemons. + +Mode = (router) + This option selects the way packets are routed to other daemons. + + router + In this mode Subnet variables in the host configuration files + will be used to form a routing table. Only unicast packets of + routable protocols (IPv4 and IPv6) are supported in this mode. + + This is the default mode, and unless you really know you need + another mode, don't change it. + + switch + In this mode the MAC addresses of the packets on the VPN will + be used to dynamically create a routing table just like an + Ethernet switch does. Unicast, multicast and broadcast + packets of every protocol that runs over Ethernet are + supported in this mode at the cost of frequent broadcast ARP + requests and routing table updates. + + This mode is primarily useful if you want to bridge Ethernet + segments. + + hub + This mode is almost the same as the switch mode, but instead + every packet will be broadcast to the other daemons while no + routing table is managed. + +Name = [required] + This is a symbolic name for this connection. The name must consist + only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and + _). + + If Name starts with a $, then the contents of the environment + variable that follows will be used. In that case, invalid + characters will be converted to underscores. If Name is $HOST, but + no such environment variable exist, the hostname will be read using + the gethostname() system call. + +PingInterval = (60) + The number of seconds of inactivity that tinc will wait before + sending a probe to the other end. + +PingTimeout = (5) + The number of seconds to wait for a response to pings or to allow + meta connections to block. If the other end doesn't respond within + this time, the connection is terminated, and the others will be + notified of this. + +PriorityInheritance = (no) [experimental] + When this option is enabled the value of the TOS field of tunneled + IPv4 packets will be inherited by the UDP packets that are sent + out. + +PrivateKey = [obsolete] + This is the RSA private key for tinc. However, for safety reasons + it is advised to store private keys of any kind in separate files. + This prevents accidental eavesdropping if you are editing the + configuration file. + +PrivateKeyFile = ('/etc/tinc/NETNAME/rsa_key.priv') + This is the full path name of the RSA private key file that was + generated by 'tincd --generate-keys'. It must be a full path, not + a relative directory. + +ProcessPriority = + When this option is used the priority of the tincd process will be + adjusted. Increasing the priority may help to reduce latency and + packet loss on the VPN. + +Proxy = socks4 | socks5 | http | exec ... [experimental] + Use a proxy when making outgoing connections. The following proxy + types are currently supported: + + socks4
[] + Connects to the proxy using the SOCKS version 4 protocol. + Optionally, a USERNAME can be supplied which will be passed on + to the proxy server. + + socks5
[ ] + Connect to the proxy using the SOCKS version 5 protocol. If a + USERNAME and PASSWORD are given, basic username/password + authentication will be used, otherwise no authentication will + be used. + + http
+ Connects to the proxy and sends a HTTP CONNECT request. + + exec + Executes the given command which should set up the outgoing + connection. The environment variables 'NAME', 'NODE', + 'REMOTEADDRES' and 'REMOTEPORT' are available. + +ReplayWindow = (16) + This is the size of the replay tracking window for each remote + node, in bytes. The window is a bitfield which tracks 1 packet per + bit, so for example the default setting of 16 will track up to 128 + packets in the window. In high bandwidth scenarios, setting this + to a higher value can reduce packet loss from the interaction of + replay tracking with underlying real packet loss and/or reordering. + Setting this to zero will disable replay tracking completely and + pass all traffic, but leaves tinc vulnerable to replay-based + attacks on your traffic. + +StrictSubnets = (no) [experimental] + When this option is enabled tinc will only use Subnet statements + which are present in the host config files in the local + '/etc/tinc/NETNAME/hosts/' directory. Subnets learned via + connections to other nodes and which are not present in the local + host config files are ignored. + +TunnelServer = (no) [experimental] + When this option is enabled tinc will no longer forward information + between other tinc daemons, and will only allow connections with + nodes for which host config files are present in the local + '/etc/tinc/NETNAME/hosts/' directory. Setting this options also + implicitly sets StrictSubnets. + +UDPRcvBuf = (OS default) + Sets the socket receive buffer size for the UDP socket, in bytes. + If unset, the default buffer size will be used by the operating + system. + +UDPSndBuf = Pq OS default + Sets the socket send buffer size for the UDP socket, in bytes. If + unset, the default buffer size will be used by the operating + system. + + +File: tinc.info, Node: Host configuration variables, Next: Scripts, Prev: Main configuration variables, Up: Configuration files + +4.4.2 Host configuration variables +---------------------------------- + +Address = [] [recommended] + This variable is only required if you want to connect to this host. + It must resolve to the external IP address where the host can be + reached, not the one that is internal to the VPN. If no port is + specified, the default Port is used. Multiple Address variables + can be specified, in which case each address will be tried until a + working connection has been established. + +Cipher = (aes-256-cbc) + The symmetric cipher algorithm used to encrypt UDP packets. Any + cipher supported by LibreSSL or OpenSSL is recognized. + Furthermore, specifying "none" will turn off packet encryption. It + is best to use only those ciphers which support CBC mode. + +ClampMSS = (yes) + This option specifies whether tinc should clamp the maximum segment + size (MSS) of TCP packets to the path MTU. This helps in situations + where ICMP Fragmentation Needed or Packet too Big messages are + dropped by firewalls. + +Compression = (0) + This option sets the level of compression used for UDP packets. + Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 + (best zlib), 10 (fast lzo) and 11 (best lzo). + +Digest = (sha256) + The digest algorithm used to authenticate UDP packets. Any digest + supported by LibreSSL or OpenSSL is recognized. Furthermore, + specifying "none" will turn off packet authentication. + +IndirectData = (no) + This option specifies whether other tinc daemons besides the one + you specified with ConnectTo can make a direct connection to you. + This is especially useful if you are behind a firewall and it is + impossible to make a connection from the outside to your tinc + daemon. Otherwise, it is best to leave this option out or set it + to no. + +MACLength = (4) + The length of the message authentication code used to authenticate + UDP packets. Can be anything from 0 up to the length of the digest + produced by the digest algorithm. + +PMTU = (1514) + This option controls the initial path MTU to this node. + +PMTUDiscovery = (yes) + When this option is enabled, tinc will try to discover the path MTU + to this node. After the path MTU has been discovered, it will be + enforced on the VPN. + +Port = (655) + This is the port this tinc daemon listens on. You can use decimal + portnumbers or symbolic names (as listed in '/etc/services'). + +PublicKey = [obsolete] + This is the RSA public key for this host. + +PublicKeyFile = [obsolete] + This is the full path name of the RSA public key file that was + generated by 'tincd --generate-keys'. It must be a full path, not + a relative directory. + + From version 1.0pre4 on tinc will store the public key directly + into the host configuration file in PEM format, the above two + options then are not necessary. Either the PEM format is used, or + exactly *one of the above two options* must be specified in each + host configuration file, if you want to be able to establish a + connection with that host. + +Subnet = + The subnet which this tinc daemon will serve. Tinc tries to look + up which other daemon it should send a packet to by searching the + appropriate subnet. If the packet matches a subnet, it will be + sent to the daemon who has this subnet in his host configuration + file. Multiple subnet lines can be specified for each daemon. + + Subnets can either be single MAC, IPv4 or IPv6 addresses, in which + case a subnet consisting of only that single address is assumed, or + they can be a IPv4 or IPv6 network address with a prefixlength. + For example, IPv4 subnets must be in a form like 192.168.1.0/24, + where 192.168.1.0 is the network address and 24 is the number of + bits set in the netmask. Note that subnets like 192.168.1.1/24 are + invalid! Read a networking HOWTO/FAQ/guide if you don't understand + this. IPv6 subnets are notated like fec0:0:0:1::/64. MAC + addresses are notated like 0:1a:2b:3c:4d:5e. + + Prefixlength is the number of bits set to 1 in the netmask part; + for example: netmask 255.255.255.0 would become /24, 255.255.252.0 + becomes /22. This conforms to standard CIDR notation as described + in RFC1519 (https://www.ietf.org/rfc/rfc1519.txt) + + A Subnet can be given a weight to indicate its priority over + identical Subnets owned by different nodes. The default weight is + 10. Lower values indicate higher priority. Packets will be sent + to the node with the highest priority, unless that node is not + reachable, in which case the node with the next highest priority + will be tried, and so on. + +TCPonly = (no) [deprecated] + If this variable is set to yes, then the packets are tunnelled over + a TCP connection instead of a UDP connection. This is especially + useful for those who want to run a tinc daemon from behind a + masquerading firewall, or if UDP packet routing is disabled + somehow. Setting this options also implicitly sets IndirectData. + + Since version 1.0.10, tinc will automatically detect whether + communication via UDP is possible or not. + + +File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configuration variables, Up: Configuration files + +4.4.3 Scripts +------------- + +Apart from reading the server and host configuration files, tinc can +also run scripts at certain moments. Below is a list of filenames of +scripts and a description of when they are run. A script is only run if +it exists and if it is executable. + + Scripts are run synchronously; this means that tinc will temporarily +stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the +events that trigger them. If you need to run commands asynchronously, +you have to ensure yourself that they are being run in the background. + + Under Windows (not Cygwin), the scripts must have the extension .bat. + +'/etc/tinc/NETNAME/tinc-up' + This is the most important script. If it is present it will be + executed right after the tinc daemon has been started and has + connected to the virtual network device. It should be used to set + up the corresponding network interface, but can also be used to + start other things. + + Under Windows you can use the Network Connections control panel + instead of creating this script. + +'/etc/tinc/NETNAME/tinc-down' + This script is started right before the tinc daemon quits. + +'/etc/tinc/NETNAME/hosts/HOST-up' + This script is started when the tinc daemon with name HOST becomes + reachable. + +'/etc/tinc/NETNAME/hosts/HOST-down' + This script is started when the tinc daemon with name HOST becomes + unreachable. + +'/etc/tinc/NETNAME/host-up' + This script is started when any host becomes reachable. + +'/etc/tinc/NETNAME/host-down' + This script is started when any host becomes unreachable. + +'/etc/tinc/NETNAME/subnet-up' + This script is started when a subnet becomes reachable. The Subnet + and the node it belongs to are passed in environment variables. + +'/etc/tinc/NETNAME/subnet-down' + This script is started when a subnet becomes unreachable. + + The scripts are started without command line arguments, but can make +use of certain environment variables. Under UNIX like operating systems +the names of environment variables must be preceded by a $ in scripts. +Under Windows, in '.bat' files, they have to be put between % signs. + +'NETNAME' + If a netname was specified, this environment variable contains it. + +'NAME' + Contains the name of this tinc daemon. + +'DEVICE' + Contains the name of the virtual network device that tinc uses. + +'INTERFACE' + Contains the name of the virtual network interface that tinc uses. + This should be used for commands like ifconfig. + +'NODE' + When a host becomes (un)reachable, this is set to its name. If a + subnet becomes (un)reachable, this is set to the owner of that + subnet. + +'REMOTEADDRESS' + When a host becomes (un)reachable, this is set to its real address. + +'REMOTEPORT' + When a host becomes (un)reachable, this is set to the port number + it uses for communication with other tinc daemons. + +'SUBNET' + When a subnet becomes (un)reachable, this is set to the subnet. + +'WEIGHT' + When a subnet becomes (un)reachable, this is set to the subnet + weight. + + +File: tinc.info, Node: How to configure, Prev: Scripts, Up: Configuration files + +4.4.4 How to configure +---------------------- + +Step 1. Creating the main configuration file +............................................ + +The main configuration file will be called +'/etc/tinc/NETNAME/tinc.conf'. Adapt the following example to create a +basic configuration file: + + Name = YOURNAME + Device = /dev/tap0 + + Then, if you know to which other tinc daemon(s) yours is going to +connect, add 'ConnectTo' values. + +Step 2. Creating your host configuration file +............................................. + +If you added a line containing 'Name = yourname' in the main +configuration file, you will need to create a host configuration file +'/etc/tinc/NETNAME/hosts/yourname'. Adapt the following example to +create a host configuration file: + + Address = your.real.hostname.org + Subnet = 192.168.1.0/24 + + You can also use an IP address instead of a hostname. The 'Subnet' +specifies the address range that is local for _your part of the VPN +only_. If you have multiple address ranges you can specify more than +one 'Subnet'. You might also need to add a 'Port' if you want your tinc +daemon to run on a different port number than the default (655). + + +File: tinc.info, Node: Generating keypairs, Next: Network interfaces, Prev: Configuration files, Up: Configuration + +4.5 Generating keypairs +======================= + +Now that you have already created the main configuration file and your +host configuration file, you can easily create a public/private keypair +by entering the following command: + + tincd -n NETNAME -K + + Tinc will generate a public and a private key and ask you where to +put them. Just press enter to accept the defaults. + + +File: tinc.info, Node: Network interfaces, Next: Example configuration, Prev: Generating keypairs, Up: Configuration + +4.6 Network interfaces +====================== + +Before tinc can start transmitting data over the tunnel, it must set up +the virtual network interface. + + First, decide which IP addresses you want to have associated with +these devices, and what network mask they must have. + + Tinc will open a virtual network device ('/dev/tun', '/dev/tap0' or +similar), which will also create a network interface called something +like 'tun0', 'tap0'. If you are using the Linux tun/tap driver, the +network interface will by default have the same name as the NETNAME. +Under Windows you can change the name of the network interface from the +Network Connections control panel. + + You can configure the network interface by putting ordinary ifconfig, +route, and other commands to a script named '/etc/tinc/NETNAME/tinc-up'. +When tinc starts, this script will be executed. When tinc exits, it +will execute the script named '/etc/tinc/NETNAME/tinc-down', but +normally you don't need to create that script. + + An example 'tinc-up' script: + + #!/bin/sh + ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 + + This script gives the interface an IP address and a netmask. The +kernel will also automatically add a route to this interface, so +normally you don't need to add route commands to the 'tinc-up' script. +The kernel will also bring the interface up after this command. The +netmask is the mask of the _entire_ VPN network, not just your own +subnet. + + The exact syntax of the ifconfig and route commands differs from +platform to platform. You can look up the commands for setting +addresses and adding routes in *note Platform specific information::, +but it is best to consult the manpages of those utilities on your +platform. + + +File: tinc.info, Node: Example configuration, Prev: Network interfaces, Up: Configuration + +4.7 Example configuration +========================= + +Imagine the following situation. Branch A of our example 'company' +wants to connect three branch offices in B, C and D using the Internet. +All four offices have a 24/7 connection to the Internet. + + A is going to serve as the center of the network. B and C will +connect to A, and D will connect to C. Each office will be assigned +their own IP network, 10.x.0.0. + + A: net 10.1.0.0 mask 255.255.0.0 gateway 10.1.54.1 internet IP 1.2.3.4 + B: net 10.2.0.0 mask 255.255.0.0 gateway 10.2.1.12 internet IP 2.3.4.5 + C: net 10.3.0.0 mask 255.255.0.0 gateway 10.3.69.254 internet IP 3.4.5.6 + D: net 10.4.0.0 mask 255.255.0.0 gateway 10.4.3.32 internet IP 4.5.6.7 + + Here, "gateway" is the VPN IP address of the machine that is running +the tincd, and "internet IP" is the IP address of the firewall, which +does not need to run tincd, but it must do a port forwarding of TCP and +UDP on port 655 (unless otherwise configured). + + In this example, it is assumed that eth0 is the interface that points +to the inner (physical) LAN of the office, although this could also be +the same as the interface that leads to the Internet. The configuration +of the real interface is also shown as a comment, to give you an idea of +how these example host is set up. All branches use the netname +'company' for this particular VPN. + +For Branch A +............ + +_BranchA_ would be configured like this: + + In '/etc/tinc/company/tinc-up': + + # Real interface of internal network: + # ifconfig eth0 10.1.54.1 netmask 255.255.0.0 + + ifconfig $INTERFACE 10.1.54.1 netmask 255.0.0.0 + + and in '/etc/tinc/company/tinc.conf': + + Name = BranchA + Device = /dev/tap0 + + On all hosts, '/etc/tinc/company/hosts/BranchA' contains: + + Subnet = 10.1.0.0/16 + Address = 1.2.3.4 + + -----BEGIN RSA PUBLIC KEY----- + ... + -----END RSA PUBLIC KEY----- + + Note that the IP addresses of eth0 and tap0 are the same. This is +quite possible, if you make sure that the netmasks of the interfaces are +different. It is in fact recommended to give both real internal network +interfaces and tap interfaces the same IP address, since that will make +things a lot easier to remember and set up. + +For Branch B +............ + +In '/etc/tinc/company/tinc-up': + + # Real interface of internal network: + # ifconfig eth0 10.2.43.8 netmask 255.255.0.0 + + ifconfig $INTERFACE 10.2.1.12 netmask 255.0.0.0 + + and in '/etc/tinc/company/tinc.conf': + + Name = BranchB + ConnectTo = BranchA + + Note here that the internal address (on eth0) doesn't have to be the +same as on the tap0 device. Also, ConnectTo is given so that this node +will always try to connect to BranchA. + + On all hosts, in '/etc/tinc/company/hosts/BranchB': + + Subnet = 10.2.0.0/16 + Address = 2.3.4.5 + + -----BEGIN RSA PUBLIC KEY----- + ... + -----END RSA PUBLIC KEY----- + +For Branch C +............ + +In '/etc/tinc/company/tinc-up': + + # Real interface of internal network: + # ifconfig eth0 10.3.69.254 netmask 255.255.0.0 + + ifconfig $INTERFACE 10.3.69.254 netmask 255.0.0.0 + + and in '/etc/tinc/company/tinc.conf': + + Name = BranchC + ConnectTo = BranchA + Device = /dev/tap1 + + C already has another daemon that runs on port 655, so they have to +reserve another port for tinc. It knows the portnumber it has to listen +on from it's own host configuration file. + + On all hosts, in '/etc/tinc/company/hosts/BranchC': + + Address = 3.4.5.6 + Subnet = 10.3.0.0/16 + Port = 2000 + + -----BEGIN RSA PUBLIC KEY----- + ... + -----END RSA PUBLIC KEY----- + +For Branch D +............ + +In '/etc/tinc/company/tinc-up': + + # Real interface of internal network: + # ifconfig eth0 10.4.3.32 netmask 255.255.0.0 + + ifconfig $INTERFACE 10.4.3.32 netmask 255.0.0.0 + + and in '/etc/tinc/company/tinc.conf': + + Name = BranchD + ConnectTo = BranchC + Device = /dev/net/tun + + D will be connecting to C, which has a tincd running for this network +on port 2000. It knows the port number from the host configuration +file. Also note that since D uses the tun/tap driver, the network +interface will not be called 'tun' or 'tap0' or something like that, but +will have the same name as netname. + + On all hosts, in '/etc/tinc/company/hosts/BranchD': + + Subnet = 10.4.0.0/16 + Address = 4.5.6.7 + + -----BEGIN RSA PUBLIC KEY----- + ... + -----END RSA PUBLIC KEY----- + +Key files +......... + +A, B, C and D all have generated a public/private keypair with the +following command: + + tincd -n company -K + + The private key is stored in '/etc/tinc/company/rsa_key.priv', the +public key is put into the host configuration file in the +'/etc/tinc/company/hosts/' directory. During key generation, tinc +automatically guesses the right filenames based on the -n option and the +Name directive in the 'tinc.conf' file (if it is available). + +Starting +........ + +After each branch has finished configuration and they have distributed +the host configuration files amongst them, they can start their tinc +daemons. They don't necessarily have to wait for the other branches to +have started their daemons, tinc will try connecting until they are +available. + + +File: tinc.info, Node: Running tinc, Next: Technical information, Prev: Configuration, Up: Top + +5 Running tinc +************** + +If everything else is done, you can start tinc by typing the following +command: + + tincd -n NETNAME + + Tinc will detach from the terminal and continue to run in the +background like a good daemon. If there are any problems however you +can try to increase the debug level and look in the syslog to find out +what the problems are. + +* Menu: + +* Runtime options:: +* Signals:: +* Debug levels:: +* Solving problems:: +* Error messages:: +* Sending bug reports:: + + +File: tinc.info, Node: Runtime options, Next: Signals, Up: Running tinc + +5.1 Runtime options +=================== + +Besides the settings in the configuration file, tinc also accepts some +command line options. + +'-c, --config=PATH' + Read configuration options from the directory PATH. The default is + '/etc/tinc/NETNAME/'. + +'-D, --no-detach' + Don't fork and detach. This will also disable the automatic + restart mechanism for fatal errors. + +'-d, --debug=LEVEL' + Set debug level to LEVEL. The higher the debug level, the more + gets logged. Everything goes via syslog. + +'-k, --kill[=SIGNAL]' + Attempt to kill a running tincd (optionally with the specified + SIGNAL instead of SIGTERM) and exit. Use it in conjunction with + the -n option to make sure you kill the right tinc daemon. Under + native Windows the optional argument is ignored, the service will + always be stopped and removed. + +'-n, --net=NETNAME' + Use configuration for net NETNAME. This will let tinc read all + configuration files from '/etc/tinc/NETNAME/'. Specifying . for + NETNAME is the same as not specifying any NETNAME. *Note Multiple + networks::. + +'-K, --generate-keys[=BITS]' + Generate public/private keypair of BITS length. If BITS is not + specified, 2048 is the default. tinc will ask where you want to + store the files, but will default to the configuration directory + (you can use the -c or -n option in combination with -K). After + that, tinc will quit. + +'-o, --option=[HOST.]KEY=VALUE' + Without specifying a HOST, this will set server configuration + variable KEY to VALUE. If specified as HOST.KEY=VALUE, this will + set the host configuration variable KEY of the host named HOST to + VALUE. This option can be used more than once to specify multiple + configuration variables. + +'-L, --mlock' + Lock tinc into main memory. This will prevent sensitive data like + shared private keys to be written to the system swap + files/partitions. + +'--logfile[=FILE]' + Write log entries to a file instead of to the system logging + facility. If FILE is omitted, the default is + '/var/log/tinc.NETNAME.log'. + +'--pidfile=FILE' + Write PID to FILE instead of '/run/tinc.NETNAME.pid'. + +'--bypass-security' + Disables encryption and authentication. Only useful for debugging. + +'-R, --chroot' + Change process root directory to the directory where the config + file is located ('/etc/tinc/NETNAME/' as determined by -n/-net + option or as given by -c/-config option), for added security. The + chroot is performed after all the initialization is done, after + writing pid files and opening network sockets. + + This option is best used in combination with the -U/-user option + described below. + + You will need to ensure the chroot environment contains all the + files necessary for tinc to run correctly. Most importantly, for + tinc to be able to resolve hostnames inside the chroot environment, + you must copy '/etc/resolv.conf' into the chroot directory. If you + want to be able to run scripts other than 'tinc-up' in the chroot, + you must ensure the appropriate shell is also installed in the + chroot, along with all its dependencies. + +'-U, --user=USER' + Switch to the given USER after initialization, at the same time as + chroot is performed (see -chroot above). With this option tinc + drops privileges, for added security. + +'--help' + Display a short reminder of these runtime options and terminate. + +'--version' + Output version information and exit. + + +File: tinc.info, Node: Signals, Next: Debug levels, Prev: Runtime options, Up: Running tinc + +5.2 Signals +=========== + +You can also send the following signals to a running tincd process: + +'ALRM' + Forces tinc to try to connect to all uplinks immediately. Usually + tinc attempts to do this itself, but increases the time it waits + between the attempts each time it failed, and if tinc didn't + succeed to connect to an uplink the first time after it started, it + defaults to the maximum time of 15 minutes. + +'HUP' + Partially rereads configuration files. Connections to hosts whose + host config file are removed are closed. New outgoing connections + specified in 'tinc.conf' will be made. If the -logfile option is + used, this will also close and reopen the log file, useful when log + rotation is used. + +'INT' + Temporarily increases debug level to 5. Send this signal again to + revert to the original level. + +'USR1' + Dumps the connection list to syslog. + +'USR2' + Dumps virtual network device statistics, all known nodes, edges and + subnets to syslog. + +'WINCH' + Purges all information remembered about unreachable nodes. + + +File: tinc.info, Node: Debug levels, Next: Solving problems, Prev: Signals, Up: Running tinc + +5.3 Debug levels +================ + +The tinc daemon can send a lot of messages to the syslog. The higher +the debug level, the more messages it will log. Each level inherits all +messages of the previous level: + +'0' + This will log a message indicating tinc has started along with a + version number. It will also log any serious error. + +'1' + This will log all connections that are made with other tinc + daemons. + +'2' + This will log status and error messages from scripts and other tinc + daemons. + +'3' + This will log all requests that are exchanged with other tinc + daemons. These include authentication, key exchange and connection + list updates. + +'4' + This will log a copy of everything received on the meta socket. + +'5' + This will log all network traffic over the virtual private network. + + +File: tinc.info, Node: Solving problems, Next: Error messages, Prev: Debug levels, Up: Running tinc + +5.4 Solving problems +==================== + +If tinc starts without problems, but if the VPN doesn't work, you will +have to find the cause of the problem. The first thing to do is to +start tinc with a high debug level in the foreground, so you can +directly see everything tinc logs: + + tincd -n NETNAME -d5 -D + + If tinc does not log any error messages, then you might want to check +the following things: + + * 'tinc-up' script Does this script contain the right commands? + Normally you must give the interface the address of this host on + the VPN, and the netmask must be big enough so that the entire VPN + is covered. + + * Subnet Does the Subnet (or Subnets) in the host configuration file + of this host match the portion of the VPN that belongs to this + host? + + * Firewalls and NATs Do you have a firewall or a NAT device (a + masquerading firewall or perhaps an ADSL router that performs + masquerading)? If so, check that it allows TCP and UDP traffic on + port 655. If it masquerades and the host running tinc is behind + it, make sure that it forwards TCP and UDP traffic to port 655 to + the host running tinc. You can add 'TCPOnly = yes' to your host + config file to force tinc to only use a single TCP connection, this + works through most firewalls and NATs. Since version 1.0.10, tinc + will automatically fall back to TCP if direct communication via UDP + is not possible. + + +File: tinc.info, Node: Error messages, Next: Sending bug reports, Prev: Solving problems, Up: Running tinc + +5.5 Error messages +================== + +What follows is a list of the most common error messages you might find +in the logs. Some of them will only be visible if the debug level is +high enough. + +'Could not open /dev/tap0: No such device' + + * You forgot to 'modprobe netlink_dev' or 'modprobe ethertap'. + * You forgot to compile 'Netlink device emulation' in the + kernel. + +'Can't write to /dev/net/tun: No such device' + + * You forgot to 'modprobe tun'. + * You forgot to compile 'Universal TUN/TAP driver' in the + kernel. + * The tun device is located somewhere else in '/dev/'. + +'Network address and prefix length do not match!' + + * The Subnet field must contain a _network_ address, trailing + bits should be 0. + * If you only want to use one IP address, set the netmask to + /32. + +'Error reading RSA key file `rsa_key.priv': No such file or directory' + + * You forgot to create a public/private keypair. + * Specify the complete pathname to the private key file with the + 'PrivateKeyFile' option. + +'Warning: insecure file permissions for RSA private key file `rsa_key.priv'!' + + * The private key file is readable by users other than root. + Use chmod to correct the file permissions. + +'Creating metasocket failed: Address family not supported' + + * By default tinc tries to create both IPv4 and IPv6 sockets. + On some platforms this might not be implemented. If the logs + show 'Ready' later on, then at least one metasocket was + created, and you can ignore this message. You can add + 'AddressFamily = ipv4' to 'tinc.conf' to prevent this from + happening. + +'Cannot route packet: unknown IPv4 destination 1.2.3.4' + + * You try to send traffic to a host on the VPN for which no + Subnet is known. + * If it is a broadcast address (ending in .255), it probably is + a samba server or a Windows host sending broadcast packets. + You can ignore it. + +'Cannot route packet: ARP request for unknown address 1.2.3.4' + + * You try to send traffic to a host on the VPN for which no + Subnet is known. + +'Packet with destination 1.2.3.4 is looping back to us!' + + * Something is not configured right. Packets are being sent out + to the virtual network device, but according to the Subnet + directives in your host configuration file, those packets + should go to your own host. Most common mistake is that you + have a Subnet line in your host configuration file with a + prefix length which is just as large as the prefix of the + virtual network interface. The latter should in almost all + cases be larger. Rethink your configuration. Note that you + will only see this message if you specified a debug level of 5 + or higher! + * Chances are that a 'Subnet = ...' line in the host + configuration file of this tinc daemon is wrong. Change it to + a subnet that is accepted locally by another interface, or if + that is not the case, try changing the prefix length into /32. + +'Node foo (1.2.3.4) is not reachable' + + * Node foo does not have a connection anymore, its tinc daemon + is not running or its connection to the Internet is broken. + +'Received UDP packet from unknown source 1.2.3.4 (port 12345)' + + * If you see this only sporadically, it is harmless and caused + by a node sending packets using an old key. + +'Got bad/bogus/unauthorized REQUEST from foo (1.2.3.4 port 12345)' + + * Node foo does not have the right public/private keypair. + Generate new keypairs and distribute them again. + * An attacker tries to gain access to your VPN. + * A network error caused corruption of metadata sent from foo. + + +File: tinc.info, Node: Sending bug reports, Prev: Error messages, Up: Running tinc + +5.6 Sending bug reports +======================= + +If you really can't find the cause of a problem, or if you suspect tinc +is not working right, you can send us a bugreport, see *note Contact +information::. Be sure to include the following information in your +bugreport: + + * A clear description of what you are trying to achieve and what the + problem is. + * What platform (operating system, version, hardware architecture) + and which version of tinc you use. + * If compiling tinc fails, a copy of 'config.log' and the error + messages you get. + * Otherwise, a copy of 'tinc.conf', 'tinc-up' and all files in the + 'hosts/' directory. + * The output of the commands 'ifconfig -a' and 'route -n' (or + 'netstat -rn' if that doesn't work). + * The output of any command that fails to work as it should (like + ping or traceroute). + + +File: tinc.info, Node: Technical information, Next: Platform specific information, Prev: Running tinc, Up: Top + +6 Technical information +*********************** + +* Menu: + +* The connection:: +* The meta-protocol:: +* Security:: + + +File: tinc.info, Node: The connection, Next: The meta-protocol, Up: Technical information + +6.1 The connection +================== + +Tinc is a daemon that takes VPN data and transmit that to another host +computer over the existing Internet infrastructure. + +* Menu: + +* The UDP tunnel:: +* The meta-connection:: + + +File: tinc.info, Node: The UDP tunnel, Next: The meta-connection, Up: The connection + +6.1.1 The UDP tunnel +-------------------- + +The data itself is read from a character device file, the so-called +_virtual network device_. This device is associated with a network +interface. Any data sent to this interface can be read from the device, +and any data written to the device gets sent from the interface. There +are two possible types of virtual network devices: 'tun' style, which +are point-to-point devices which can only handle IPv4 and/or IPv6 +packets, and 'tap' style, which are Ethernet devices and handle complete +Ethernet frames. + + So when tinc reads an Ethernet frame from the device, it determines +its type. When tinc is in its default routing mode, it can handle IPv4 +and IPv6 packets. Depending on the Subnet lines, it will send the +packets off to their destination IP address. In the 'switch' and 'hub' +mode, tinc will use broadcasts and MAC address discovery to deduce the +destination of the packets. Since the latter modes only depend on the +link layer information, any protocol that runs over Ethernet is +supported (for instance IPX and Appletalk). However, only 'tap' style +devices provide this information. + + After the destination has been determined, the packet will be +compressed (optionally), a sequence number will be added to the packet, +the packet will then be encrypted and a message authentication code will +be appended. + + When that is done, time has come to actually transport the packet to +the destination computer. We do this by sending the packet over an UDP +connection to the destination host. This is called _encapsulating_, the +VPN packet (though now encrypted) is encapsulated in another IP +datagram. + + When the destination receives this packet, the same thing happens, +only in reverse. So it checks the message authentication code, decrypts +the contents of the UDP datagram, checks the sequence number and writes +the decrypted information to its own virtual network device. + + If the virtual network device is a 'tun' device (a point-to-point +tunnel), there is no problem for the kernel to accept a packet. +However, if it is a 'tap' device (this is the only available type on +FreeBSD), the destination MAC address must match that of the virtual +network interface. If tinc is in its default routing mode, ARP does not +work, so the correct destination MAC can not be known by the sending +host. Tinc solves this by letting the receiving end detect the MAC +address of its own virtual network interface and overwriting the +destination MAC address of the received packet. + + In switch or hub modes ARP does work so the sender already knows the +correct destination MAC address. In those modes every interface should +have a unique MAC address, so make sure they are not the same. Because +switch and hub modes rely on MAC addresses to function correctly, these +modes cannot be used on the following operating systems which don't have +a 'tap' style virtual network device: NetBSD, Darwin and Solaris. + + +File: tinc.info, Node: The meta-connection, Prev: The UDP tunnel, Up: The connection + +6.1.2 The meta-connection +------------------------- + +Having only a UDP connection available is not enough. Though suitable +for transmitting data, we want to be able to reliably send other +information, such as routing and session key information to somebody. + + TCP is a better alternative, because it already contains protection +against information being lost, unlike UDP. + + So we establish two connections. One for the encrypted VPN data, and +one for other information, the meta-data. Hence, we call the second +connection the meta-connection. We can now be sure that the +meta-information doesn't get lost on the way to another computer. + + Like with any communication, we must have a protocol, so that +everybody knows what everything stands for, and how she should react. +Because we have two connections, we also have two protocols. The +protocol used for the UDP data is the "data-protocol," the other one is +the "meta-protocol." + + The reason we don't use TCP for both protocols is that UDP is much +better for encapsulation, even while it is less reliable. The real +problem is that when TCP would be used to encapsulate a TCP stream +that's on the private network, for every packet sent there would be +three ACKs sent instead of just one. Furthermore, if there would be a +timeout, both TCP streams would sense the timeout, and both would start +re-sending packets. + + +File: tinc.info, Node: The meta-protocol, Next: Security, Prev: The connection, Up: Technical information + +6.2 The meta-protocol +===================== + +The meta protocol is used to tie all tinc daemons together, and exchange +information about which tinc daemon serves which virtual subnet. + + The meta protocol consists of requests that can be sent to the other +side. Each request has a unique number and several parameters. All +requests are represented in the standard ASCII character set. It is +possible to use tools such as telnet or netcat to connect to a tinc +daemon started with the -bypass-security option and to read and write +requests by hand, provided that one understands the numeric codes sent. + + The authentication scheme is described in *note Authentication +protocol::. After a successful authentication, the server and the +client will exchange all the information about other tinc daemons and +subnets they know of, so that both sides (and all the other tinc daemons +behind them) have their information synchronised. + + message + ------------------------------------------------------------------ + ADD_EDGE node1 node2 21.32.43.54 655 222 0 + | | | | | +-> options + | | | | +----> weight + | | | +--------> UDP port of node2 + | | +----------------> real address of node2 + | +-------------------------> name of destination node + +-------------------------------> name of source node + + ADD_SUBNET node 192.168.1.0/24 + | | +--> prefixlength + | +--------> network address + +------------------> owner of this subnet + ------------------------------------------------------------------ + + The ADD_EDGE messages are to inform other tinc daemons that a +connection between two nodes exist. The address of the destination node +is available so that VPN packets can be sent directly to that node. + + The ADD_SUBNET messages inform other tinc daemons that certain +subnets belong to certain nodes. tinc will use it to determine to which +node a VPN packet has to be sent. + + message + ------------------------------------------------------------------ + DEL_EDGE node1 node2 + | +----> name of destination node + +----------> name of source node + + DEL_SUBNET node 192.168.1.0/24 + | | +--> prefixlength + | +--------> network address + +------------------> owner of this subnet + ------------------------------------------------------------------ + + In case a connection between two daemons is closed or broken, +DEL_EDGE messages are sent to inform the other daemons of that fact. +Each daemon will calculate a new route to the the daemons, or mark them +unreachable if there isn't any. + + message + ------------------------------------------------------------------ + REQ_KEY origin destination + | +--> name of the tinc daemon it wants the key from + +----------> name of the daemon that wants the key + + ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 + | | \______________/ | | +--> MAC length + | | | | +-----> digest algorithm + | | | +--------> cipher algorithm + | | +--> 128 bits key + | +--> name of the daemon that wants the key + +----------> name of the daemon that uses this key + + KEY_CHANGED origin + +--> daemon that has changed it's packet key + ------------------------------------------------------------------ + + The keys used to encrypt VPN packets are not sent out directly. This +is because it would generate a lot of traffic on VPNs with many daemons, +and chances are that not every tinc daemon will ever send a packet to +every other daemon. Instead, if a daemon needs a key it sends a request +for it via the meta connection of the nearest hop in the direction of +the destination. + + daemon message + ------------------------------------------------------------------ + origin PING + dest. PONG + ------------------------------------------------------------------ + + There is also a mechanism to check if hosts are still alive. Since +network failures or a crash can cause a daemon to be killed without +properly shutting down the TCP connection, this is necessary to keep an +up to date connection list. PINGs are sent at regular intervals, except +when there is also some other traffic. A little bit of salt (random +data) is added with each PING and PONG message, to make sure that long +sequences of PING/PONG messages without any other traffic won't result +in known plaintext. + + This basically covers what is sent over the meta connection by tinc. + + +File: tinc.info, Node: Security, Prev: The meta-protocol, Up: Technical information + +6.3 Security +============ + +Tinc got its name from "TINC," short for _There Is No Cabal_; the +alleged Cabal was/is an organisation that was said to keep an eye on the +entire Internet. As this is exactly what you _don't_ want, we named the +tinc project after TINC. + + But in order to be "immune" to eavesdropping, you'll have to encrypt +your data. Because tinc is a _Secure_ VPN (SVPN) daemon, it does +exactly that: encrypt. Tinc by default uses blowfish encryption with +128 bit keys in CBC mode, 32 bit sequence numbers and 4 byte long +message authentication codes to make sure eavesdroppers cannot get and +cannot change any information at all from the packets they can +intercept. The encryption algorithm and message authentication +algorithm can be changed in the configuration. The length of the +message authentication codes is also adjustable. The length of the key +for the encryption algorithm is always the default length used by +LibreSSL/OpenSSL. + +* Menu: + +* Authentication protocol:: +* Encryption of network packets:: +* Security issues:: + + +File: tinc.info, Node: Authentication protocol, Next: Encryption of network packets, Up: Security + +6.3.1 Authentication protocol +----------------------------- + +A new scheme for authentication in tinc has been devised, which offers +some improvements over the protocol used in 1.0pre2 and 1.0pre3. +Explanation is below. + + daemon message + -------------------------------------------------------------------------- + client + + server + + client ID client 12 + | +---> version + +-------> name of tinc daemon + + server ID server 12 + | +---> version + +-------> name of tinc daemon + + client META_KEY 5f0823a93e35b69e...7086ec7866ce582b + \_________________________________/ + +-> RSAKEYLEN bits totally random string S1, + encrypted with server's public RSA key + + server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630 + \_________________________________/ + +-> RSAKEYLEN bits totally random string S2, + encrypted with client's public RSA key + + From now on: + - the client will symmetrically encrypt outgoing traffic using S1 + - the server will symmetrically encrypt outgoing traffic using S2 + + client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0 + \_________________________________/ + +-> CHALLEN bits totally random string H1 + + server CHALLENGE 57fb4b2ccd70d6bb35a64c142f47e61d57f + \_________________________________/ + +-> CHALLEN bits totally random string H2 + + client CHAL_REPLY 816a86 + +-> 160 bits SHA1 of H2 + + server CHAL_REPLY 928ffe + +-> 160 bits SHA1 of H1 + + After the correct challenge replies are received, both ends have proved + their identity. Further information is exchanged. + + client ACK 655 123 0 + | | +-> options + | +----> estimated weight + +--------> listening port of client + + server ACK 655 321 0 + | | +-> options + | +----> estimated weight + +--------> listening port of server + -------------------------------------------------------------------------- + + This new scheme has several improvements, both in efficiency and +security. + + First of all, the server sends exactly the same kind of messages over +the wire as the client. The previous versions of tinc first +authenticated the client, and then the server. This scheme even allows +both sides to send their messages simultaneously, there is no need to +wait for the other to send something first. This means that any +calculations that need to be done upon sending or receiving a message +can also be done in parallel. This is especially important when doing +RSA encryption/decryption. Given that these calculations are the main +part of the CPU time spent for the authentication, speed is improved by +a factor 2. + + Second, only one RSA encrypted message is sent instead of two. This +reduces the amount of information attackers can see (and thus use for a +cryptographic attack). It also improves speed by a factor two, making +the total speedup a factor 4. + + Third, and most important: The symmetric cipher keys are exchanged +first, the challenge is done afterwards. In the previous authentication +scheme, because a man-in-the-middle could pass the challenge/chal_reply +phase (by just copying the messages between the two real tinc daemons), +but no information was exchanged that was really needed to read the rest +of the messages, the challenge/chal_reply phase was of no real use. The +man-in-the-middle was only stopped by the fact that only after the ACK +messages were encrypted with the symmetric cipher. Potentially, it +could even send it's own symmetric key to the server (if it knew the +server's public key) and read some of the metadata the server would send +it (it was impossible for the mitm to read actual network packets +though). The new scheme however prevents this. + + This new scheme makes sure that first of all, symmetric keys are +exchanged. The rest of the messages are then encrypted with the +symmetric cipher. Then, each side can only read received messages if +they have their private key. The challenge is there to let the other +side know that the private key is really known, because a challenge +reply can only be sent back if the challenge is decrypted correctly, and +that can only be done with knowledge of the private key. + + Fourth: the first thing that is sent via the symmetric cipher +encrypted connection is a totally random string, so that there is no +known plaintext (for an attacker) in the beginning of the encrypted +stream. + + +File: tinc.info, Node: Encryption of network packets, Next: Security issues, Prev: Authentication protocol, Up: Security + +6.3.2 Encryption of network packets +----------------------------------- + +A data packet can only be sent if the encryption key is known to both +parties, and the connection is activated. If the encryption key is not +known, a request is sent to the destination using the meta connection to +retrieve it. The packet is stored in a queue while waiting for the key +to arrive. + + The UDP packet containing the network packet from the VPN has the +following layout: + + ... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer + \___________________/\_____/ + | | + V +---> digest algorithm + Encrypted with symmetric cipher + + So, the entire VPN packet is encrypted using a symmetric cipher, +including a 32 bits sequence number that is added in front of the actual +VPN packet, to act as a unique IV for each packet and to prevent replay +attacks. A message authentication code is added to the UDP packet to +prevent alteration of packets. By default the first 4 bytes of the +digest are used for this, but this can be changed using the MACLength +configuration variable. + + +File: tinc.info, Node: Security issues, Prev: Encryption of network packets, Up: Security + +6.3.3 Security issues +--------------------- + +In August 2000, we discovered the existence of a security hole in all +versions of tinc up to and including 1.0pre2. This had to do with the +way we exchanged keys. Since then, we have been working on a new +authentication scheme to make tinc as secure as possible. The current +version uses the LibreSSL or OpenSSL library and uses strong +authentication with RSA keys. + + On the 29th of December 2001, Jerome Etienne posted a security +analysis of tinc 1.0pre4. Due to a lack of sequence numbers and a +message authentication code for each packet, an attacker could possibly +disrupt certain network services or launch a denial of service attack by +replaying intercepted packets. The current version adds sequence +numbers and message authentication codes to prevent such attacks. + + On the 15th of September 2003, Peter Gutmann posted a security +analysis of tinc 1.0.1. He argues that the 32 bit sequence number used +by tinc is not a good IV, that tinc's default length of 4 bytes for the +MAC is too short, and he doesn't like tinc's use of RSA during +authentication. We do not know of a security hole in this version of +tinc, but tinc's security is not as strong as TLS or IPsec. We will +address these issues in tinc 2.0. + + Cryptography is a hard thing to get right. We cannot make any +guarantees. Time, review and feedback are the only things that can +prove the security of any cryptographic product. If you wish to review +tinc or give us feedback, you are strongly encouraged to do so. + + +File: tinc.info, Node: Platform specific information, Next: About us, Prev: Technical information, Up: Top + +7 Platform specific information +******************************* + +* Menu: + +* Interface configuration:: +* Routes:: +* Automatically starting tinc:: + + +File: tinc.info, Node: Interface configuration, Next: Routes, Up: Platform specific information + +7.1 Interface configuration +=========================== + +When configuring an interface, one normally assigns it an address and a +netmask. The address uniquely identifies the host on the network +attached to the interface. The netmask, combined with the address, +forms a subnet. It is used to add a route to the routing table +instructing the kernel to send all packets which fall into that subnet +to that interface. Because all packets for the entire VPN should go to +the virtual network interface used by tinc, the netmask should be such +that it encompasses the entire VPN. + + For IPv4 addresses: + +Linux 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Linux iproute2 'ip addr add' ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +OpenBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +NetBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Solaris 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Darwin (Mac OS X) 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Windows 'netsh interface ip set address' INTERFACE 'static' ADDRESS NETMASK + + For IPv6 addresses: + +Linux 'ifconfig' INTERFACE 'add' ADDRESS'/'PREFIXLENGTH +FreeBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +OpenBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +NetBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +Solaris 'ifconfig' INTERFACE 'inet6 plumb up' + 'ifconfig' INTERFACE 'inet6 addif' ADDRESS ADDRESS +Darwin (Mac OS X) 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +Windows 'netsh interface ipv6 add address' INTERFACE 'static' ADDRESS/PREFIXLENGTH + + On Linux, it is possible to create a persistent tun/tap interface +which will continue to exist even if tinc quit, although this is +normally not required. It can be useful to set up a tun/tap interface +owned by a non-root user, so tinc can be started without needing any +root privileges at all. + +Linux 'ip tuntap add dev' INTERFACE 'mode' TUN|TAP 'user' USERNAME + + +File: tinc.info, Node: Routes, Next: Automatically starting tinc, Prev: Interface configuration, Up: Platform specific information + +7.2 Routes +========== + +In some cases it might be necessary to add more routes to the virtual +network interface. There are two ways to indicate which interface a +packet should go to, one is to use the name of the interface itself, +another way is to specify the (local) address that is assigned to that +interface (LOCAL_ADDRESS). The former way is unambiguous and therefore +preferable, but not all platforms support this. + + Adding routes to IPv4 subnets: + +Linux 'route add -net' NETWORK_ADDRESS 'netmask' NETMASK INTERFACE +Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +OpenBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +NetBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +Solaris 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' +Darwin (Mac OS X) 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH '-interface' INTERFACE +Windows 'netsh routing ip add persistentroute' NETWORK_ADDRESS NETMASK INTERFACE + LOCAL_ADDRESS + + Adding routes to IPv6 subnets: + +Linux 'route add -A inet6' NETWORK_ADDRESS'/'PREFIXLENGTH INTERFACE +Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +OpenBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH +NetBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH +Solaris 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' +Darwin (Mac OS X) 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH '-interface' INTERFACE +Windows 'netsh interface ipv6 add route' NETWORK ADDRESS/PREFIXLENGTH INTERFACE + + +File: tinc.info, Node: Automatically starting tinc, Prev: Routes, Up: Platform specific information + +7.3 Automatically starting tinc +=============================== + +* Menu: + +* Linux:: +* Windows:: +* Other platforms:: + + +File: tinc.info, Node: Linux, Next: Windows, Up: Automatically starting tinc + +7.3.1 Linux +----------- + +There are many Linux distributions, and historically, many of them had +their own way of starting programs at boot time. Today, a number of +major Linux distributions have chosen to use systemd as their init +system. Tinc ships with systemd service files that allow you to start +and stop tinc using systemd. There are two service files: +'tinc.service' is used to globally enable or disable all tinc daemons +managed by systemd, and 'tinc@NETNAME.service' is used to enable or +disable specific tinc daemons. So if one has created a tinc network +with netname 'foo', then you have to run the following two commands to +ensure it is started at boot time: + + systemctl enable tinc + systemctl enable tinc@foo + + To start the tinc daemon immediately if it wasn't already running, +use the following command: + + systemctl start tinc@foo + + You can also use 'systemctl start tinc', this will start all tinc +daemons that are enabled. You can stop and disable tinc networks in the +same way. + + If your system is not using systemd, then you have to look up your +distribution's way of starting tinc at boot time. + + +File: tinc.info, Node: Windows, Next: Other platforms, Prev: Linux, Up: Automatically starting tinc + +7.3.2 Windows +------------- + +On Windows, if tinc is started without the '-D' or '--no-detach' option, +it will automatically register itself as a service that is started at +boot time. When tinc is stopped using the '-k' or '--kill', it will +also automatically unregister itself. Once tinc is registered as a +service, it is also possible to stop and start tinc using the Windows +Services Manager. + + +File: tinc.info, Node: Other platforms, Prev: Windows, Up: Automatically starting tinc + +7.3.3 Other platforms +--------------------- + +On platforms other than the ones mentioned in the earlier sections, you +have to look up your platform's way of starting programs at boot time. + + +File: tinc.info, Node: About us, Next: Concept Index, Prev: Platform specific information, Up: Top + +8 About us +********** + +* Menu: + +* Contact information:: +* Authors:: + + +File: tinc.info, Node: Contact information, Next: Authors, Up: About us + +8.1 Contact information +======================= + +Tinc's website is at , this server is located +in the Netherlands. + + We have an IRC channel on the FreeNode and OFTC IRC networks. +Connect to irc.freenode.net (https://freenode.net/) or irc.oftc.net +(https://www.oftc.net/) and join channel #tinc. + + +File: tinc.info, Node: Authors, Prev: Contact information, Up: About us + +8.2 Authors +=========== + +Ivo Timmermans (zarq) +Guus Sliepen (guus) () + + We have received a lot of valuable input from users. With their +help, tinc has become the flexible and robust tool that it is today. We +have composed a list of contributions, in the file called 'THANKS' in +the source distribution. + + +File: tinc.info, Node: Concept Index, Prev: About us, Up: Top + +Concept Index +************* + +[index] +* Menu: + +* ACK: Authentication protocol. + (line 10) +* Address: Host configuration variables. + (line 6) +* AddressFamily: Main configuration variables. + (line 6) +* ADD_EDGE: The meta-protocol. (line 22) +* ADD_SUBNET: The meta-protocol. (line 22) +* ANS_KEY: The meta-protocol. (line 63) +* authentication: Authentication protocol. + (line 6) +* binary package: Building and installing tinc. + (line 9) +* BindToAddress: Main configuration variables. + (line 12) +* BindToInterface: Main configuration variables. + (line 25) +* Broadcast: Main configuration variables. + (line 33) +* Cabal: Security. (line 6) +* CHALLENGE: Authentication protocol. + (line 10) +* CHAL_REPLY: Authentication protocol. + (line 10) +* CIDR notation: Host configuration variables. + (line 93) +* Cipher: Host configuration variables. + (line 14) +* ClampMSS: Host configuration variables. + (line 20) +* client: How connections work. + (line 18) +* command line: Runtime options. (line 9) +* Compression: Host configuration variables. + (line 26) +* connection: The connection. (line 6) +* ConnectTo: Main configuration variables. + (line 53) +* daemon: Running tinc. (line 11) +* data-protocol: The meta-connection. (line 18) +* debug level: Runtime options. (line 17) +* debug levels: Debug levels. (line 6) +* DecrementTTL: Main configuration variables. + (line 64) +* DEL_EDGE: The meta-protocol. (line 46) +* DEL_SUBNET: The meta-protocol. (line 46) +* Device: Main configuration variables. + (line 73) +* DEVICE: Scripts. (line 64) +* device files: Device files. (line 6) +* DeviceType: Main configuration variables. + (line 79) +* Digest: Host configuration variables. + (line 31) +* DirectOnly: Main configuration variables. + (line 149) +* dummy: Main configuration variables. + (line 86) +* encapsulating: The UDP tunnel. (line 30) +* encryption: Encryption of network packets. + (line 6) +* environment variables: Scripts. (line 53) +* example: Example configuration. + (line 6) +* exec: Main configuration variables. + (line 319) +* Forwarding: Main configuration variables. + (line 156) +* frame type: The UDP tunnel. (line 6) +* GraphDumpFile: Main configuration variables. + (line 176) +* Hostnames: Main configuration variables. + (line 184) +* http: Main configuration variables. + (line 316) +* hub: Main configuration variables. + (line 254) +* ID: Authentication protocol. + (line 10) +* IffOneQueue: Main configuration variables. + (line 195) +* IndirectData: Host configuration variables. + (line 36) +* Interface: Main configuration variables. + (line 198) +* INTERFACE: Scripts. (line 67) +* IRC: Contact information. (line 9) +* key generation: Generating keypairs. (line 6) +* KeyExpire: Main configuration variables. + (line 206) +* KEY_CHANGED: The meta-protocol. (line 63) +* libraries: Libraries. (line 6) +* LibreSSL: LibreSSL/OpenSSL. (line 6) +* license: LibreSSL/OpenSSL. (line 38) +* LocalDiscovery: Main configuration variables. + (line 212) +* lzo: lzo. (line 6) +* MACExpire: Main configuration variables. + (line 223) +* MACLength: Host configuration variables. + (line 44) +* MaxTimeout: Main configuration variables. + (line 228) +* meta-protocol: The meta-connection. (line 18) +* META_KEY: Authentication protocol. + (line 10) +* Mode: Main configuration variables. + (line 232) +* multicast: Main configuration variables. + (line 98) +* multiple networks: Multiple networks. (line 6) +* Name: Main configuration variables. + (line 259) +* NAME: Scripts. (line 61) +* netmask: Network interfaces. (line 33) +* netname: Multiple networks. (line 6) +* NETNAME: Scripts. (line 58) +* Network Administrators Guide: Configuration introduction. + (line 15) +* NODE: Scripts. (line 71) +* OpenSSL: LibreSSL/OpenSSL. (line 6) +* options: Runtime options. (line 9) +* PEM format: Host configuration variables. + (line 69) +* PING: The meta-protocol. (line 88) +* PingInterval: Main configuration variables. + (line 270) +* PingTimeout: Main configuration variables. + (line 274) +* platforms: Supported platforms. (line 6) +* PMTU: Host configuration variables. + (line 49) +* PMTUDiscovery: Host configuration variables. + (line 52) +* PONG: The meta-protocol. (line 88) +* Port: Host configuration variables. + (line 57) +* port numbers: Other files. (line 17) +* PriorityInheritance: Main configuration variables. + (line 280) +* private: Virtual Private Networks. + (line 10) +* PrivateKey: Main configuration variables. + (line 285) +* PrivateKeyFile: Main configuration variables. + (line 291) +* ProcessPriority: Main configuration variables. + (line 296) +* Proxy: Main configuration variables. + (line 301) +* PublicKey: Host configuration variables. + (line 61) +* PublicKeyFile: Host configuration variables. + (line 64) +* raw_socket: Main configuration variables. + (line 91) +* release: Supported platforms. (line 14) +* REMOTEADDRESS: Scripts. (line 76) +* REMOTEPORT: Scripts. (line 79) +* ReplayWindow: Main configuration variables. + (line 324) +* requirements: Libraries. (line 6) +* REQ_KEY: The meta-protocol. (line 63) +* router: Main configuration variables. + (line 235) +* runtime options: Runtime options. (line 9) +* scalability: tinc. (line 19) +* scripts: Scripts. (line 6) +* server: How connections work. + (line 18) +* signals: Signals. (line 6) +* socks4: Main configuration variables. + (line 305) +* socks5: Main configuration variables. + (line 310) +* StrictSubnets: Main configuration variables. + (line 335) +* Subnet: Host configuration variables. + (line 76) +* SUBNET: Scripts. (line 83) +* Subnet weight: Host configuration variables. + (line 98) +* SVPN: Security. (line 11) +* switch: Main configuration variables. + (line 243) +* systemd: Linux. (line 6) +* TCP: The meta-connection. (line 10) +* TCPonly: Host configuration variables. + (line 105) +* tinc: Introduction. (line 6) +* TINC: Security. (line 6) +* tinc-down: Scripts. (line 29) +* tinc-up: Scripts. (line 19) +* tinc-up <1>: Network interfaces. (line 19) +* tincd: tinc. (line 14) +* traditional VPNs: tinc. (line 19) +* tunifhead: Main configuration variables. + (line 133) +* TunnelServer: Main configuration variables. + (line 342) +* tunnohead: Main configuration variables. + (line 127) +* UDP: The UDP tunnel. (line 30) +* UDP <1>: Encryption of network packets. + (line 12) +* UDPRcvBuf: Main configuration variables. + (line 349) +* UDPSndBuf: Main configuration variables. + (line 354) +* UML: Main configuration variables. + (line 109) +* Universal tun/tap: Configuration of Linux kernels. + (line 6) +* utun: Main configuration variables. + (line 140) +* VDE: Main configuration variables. + (line 114) +* virtual: Virtual Private Networks. + (line 18) +* virtual network device: The UDP tunnel. (line 6) +* VPN: Virtual Private Networks. + (line 6) +* vpnd: tinc. (line 6) +* website: Contact information. (line 6) +* WEIGHT: Scripts. (line 86) +* zlib: zlib. (line 6) + +  Tag Table: -(Indirect) -Node: Top888 -Node: Introduction1186 -Node: VPNs2034 -Node: tinc3755 -Node: Supported platforms5258 -Node: Preparations7214 -Node: Configuring the kernel7469 -Node: Configuration of Linux kernels 2.1.60 up to 2.4.08812 -Node: Configuration of Linux kernels 2.4.0 and higher10055 -Node: Configuration of FreeBSD kernels11128 -Node: Configuration of OpenBSD kernels11742 -Node: Configuration of Solaris kernels12225 -Node: Libraries12683 -Node: OpenSSL13040 -Node: zlib14878 -Node: Installation15686 -Node: Building and installing tinc16704 -Node: System files17253 -Node: Device files17513 -Node: Other files18817 -Node: Configuration19431 -Node: Configuration introduction19738 -Node: Multiple networks20972 -Node: How connections work22387 -Node: Configuration files23571 -Node: Main configuration variables24605 -Node: Host configuration variables29459 -Node: How to configure33723 -Node: Generating keypairs35062 -Node: Network interfaces35558 -Node: Example configuration37837 -Node: Running tinc43704 -Node: Runtime options44221 -Node: Error messages45810 -Node: Technical information48691 -Node: The connection48897 -Node: The UDP tunnel49234 -Node: The meta-connection51531 -Node: The meta-protocol52992 -Node: Security57443 -Node: Authentication protocol58648 -Node: Encryption of network packets63939 -Node: About us65262 -Node: Contact Information65425 -Node: Authors65820 -Node: Concept Index66438 +Node: Top806 +Node: Introduction1105 +Node: Virtual Private Networks1915 +Node: tinc3639 +Node: Supported platforms5167 +Node: Preparations5868 +Node: Configuring the kernel6124 +Node: Configuration of Linux kernels6534 +Node: Configuration of FreeBSD kernels7389 +Node: Configuration of OpenBSD kernels7854 +Node: Configuration of NetBSD kernels8211 +Node: Configuration of Solaris kernels8616 +Node: Configuration of Darwin (Mac OS X) kernels9279 +Node: Configuration of Windows10098 +Node: Libraries10638 +Node: LibreSSL/OpenSSL11047 +Node: zlib13589 +Node: lzo14618 +Node: Installation15601 +Node: Building and installing tinc16511 +Node: Darwin (Mac OS X) build environment17171 +Node: Cygwin (Windows) build environment17736 +Node: MinGW (Windows) build environment18325 +Node: System files18919 +Node: Device files19184 +Node: Other files19600 +Node: Configuration20213 +Node: Configuration introduction20524 +Node: Multiple networks21792 +Node: How connections work23218 +Node: Configuration files24440 +Node: Main configuration variables25934 +Node: Host configuration variables42182 +Node: Scripts47714 +Node: How to configure50980 +Node: Generating keypairs52238 +Node: Network interfaces52737 +Node: Example configuration54585 +Node: Running tinc59910 +Node: Runtime options60500 +Node: Signals64125 +Node: Debug levels65316 +Node: Solving problems66252 +Node: Error messages67804 +Node: Sending bug reports71813 +Node: Technical information72760 +Node: The connection72991 +Node: The UDP tunnel73303 +Node: The meta-connection76355 +Node: The meta-protocol77824 +Node: Security82841 +Node: Authentication protocol83983 +Node: Encryption of network packets89028 +Node: Security issues90404 +Node: Platform specific information92044 +Node: Interface configuration92304 +Node: Routes94600 +Node: Automatically starting tinc96650 +Node: Linux96873 +Node: Windows98094 +Node: Other platforms98599 +Node: About us98881 +Node: Contact information99056 +Node: Authors99459 +Node: Concept Index99864  End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/doc/tinc.info-1 b/doc/tinc.info-1 deleted file mode 100644 index a893700..0000000 --- a/doc/tinc.info-1 +++ /dev/null @@ -1,1317 +0,0 @@ -This is tinc.info, produced by makeinfo version 4.1 from tinc.texi. - -INFO-DIR-SECTION Networking tools -START-INFO-DIR-ENTRY -* tinc: (tinc). The tinc Manual. -END-INFO-DIR-ENTRY - - This is the info manual for tinc, a Virtual Private Network daemon. - - Copyright (C) 1998-2002 Ivo Timmermans , -Guus Sliepen and Wessel Dankers -. - - $Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - -File: tinc.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) - -* Menu: - -* Introduction:: Introduction -* Preparations:: -* Installation:: -* Configuration:: -* Running tinc:: -* Technical information:: -* About us:: -* Concept Index:: All used terms explained - - -File: tinc.info, Node: Introduction, Next: Preparations, Prev: Top, Up: Top - -Introduction -************ - - tinc is a Virtual Private Network (VPN) daemon that uses tunneling -and encryption to create a secure private network between hosts on the -Internet. - - Because the tunnel appears to the IP level network code as a normal -network device, there is no need to adapt any existing software. The -encrypted tunnels allows VPN sites to share information with each other -over the Internet without exposing any information to others. - - This document is the manual for tinc. Included are chapters on how -to configure your computer to use tinc, as well as the configuration -process of tinc itself. - -* Menu: - -* VPNs:: Virtual Private Networks in general -* tinc:: about tinc -* Supported platforms:: - - -File: tinc.info, Node: VPNs, Next: tinc, Prev: Introduction, Up: Introduction - -Virtual Private Networks -======================== - - A Virtual Private Network or VPN is a network that can only be -accessed by a few elected computers that participate. This goal is -achievable in more than just one way. - - Private networks can consist of a single stand-alone Ethernet LAN. -Or even two computers hooked up using a null-modem cable. In these -cases, it is obvious that the network is _private_, no one can access -it from the outside. But if your computers are linked to the Internet, -the network is not private anymore, unless one uses firewalls to block -all private traffic. But then, there is no way to send private data to -trusted computers on the other end of the Internet. - - This problem can be solved by using _virtual_ networks. Virtual -networks can live on top of other networks, but they use encapsulation -to keep using their private address space so they do not interfere with -the Internet. Mostly, virtual networks appear like a singe LAN, even -though they can span the entire world. But virtual networks can't be -secured by using firewalls, because the traffic that flows through it -has to go through the Internet, where other people can look at it. - - As is the case with either type of VPN, anybody could eavesdrop. Or -worse, alter data. Hence it's probably advisable to encrypt the data -that flows over the network. - - When one introduces encryption, we can form a true VPN. Other -people may see encrypted traffic, but if they don't know how to -decipher it (they need to know the key for that), they cannot read the -information that flows through the VPN. This is what tinc was made for. - - -File: tinc.info, Node: tinc, Next: Supported platforms, Prev: VPNs, Up: Introduction - -tinc -==== - - I really don't quite remember what got us started, but it must have -been Guus' idea. He wrote a simple implementation (about 50 lines of -C) that used the ethertap device that Linux knows of since somewhere -about kernel 2.1.60. It didn't work immediately and he improved it a -bit. At this stage, the project was still simply called `vpnd'. - - Since then, a lot has changed--to say the least. - - tinc now supports encryption, it consists of a single daemon (tincd) -for both the receiving and sending end, it has become largely -runtime-configurable--in short, it has become a full-fledged -professional package. - - tinc also allows more than two sites to connect to eachother and -form a single VPN. Traditionally VPNs are created by making tunnels, -which only have two endpoints. Larger VPNs with more sites are created -by adding more tunnels. tinc takes another approach: only endpoints -are specified, the software itself will take care of creating the -tunnels. This allows for easier configuration and improved scalability. - - A lot can--and will be--changed. We have a number of things that we -would like to see in the future releases of tinc. Not everything will -be available in the near future. Our first objective is to make tinc -work perfectly as it stands, and then add more advanced features. - - Meanwhile, we're always open-minded towards new ideas. And we're -available too. - - -File: tinc.info, Node: Supported platforms, Prev: tinc, Up: Introduction - -Supported platforms -=================== - - tinc has been verified to work under Linux, FreeBSD, OpenBSD and -Solaris, with various hardware architectures. These are some of the -platforms that are supported by the universal tun/tap device driver or -other virtual network device drivers. Without such a driver, tinc will -most likely compile and run, but it will not be able to send or receive -data packets. - - For an up to date list of supported platforms, please check the list -on our website: `http://tinc.nl.linux.org/platforms.html'. - -Linux ------ - - tinc was first written for Linux running on an intel x86 processor, -so this is the best supported platform. The protocol however, and -actually anything about tinc, has been rewritten to support random byte -ordering and arbitrary word length. So in theory it should run on other -processors that Linux runs on. It has already been verified to run on -alpha and sparc processors as well. - - tinc uses the ethertap device or the universal tun/tap driver. The -former is provided in the standard kernel from version 2.1.60 up to -2.3.x, but has been replaced in favour of the tun/tap driver in kernel -versions 2.4.0 and later. - -FreeBSD -------- - - tinc on FreeBSD relies on the universal tun/tap driver for its data -acquisition from the kernel. Therefore, tinc will work on the same -platforms as this driver. These are: FreeBSD 3.x, 4.x, 5.x. - -OpenBSD -------- - - tinc on OpenBSD relies on the tun driver for its data acquisition -from the kernel. It has been verified to work under at least OpenBSD -2.9. - - Tunneling IPv6 packets may not work on OpenBSD. - -Solaris -------- - - tinc on Solaris relies on the universal tun/tap driver for its data -acquisition from the kernel. Therefore, tinc will work on the same -platforms as this driver. These are: Solaris 8 (SunOS 5.8). - - IPv6 packets cannot be tunneled on Solaris. - - -File: tinc.info, Node: Preparations, Next: Installation, Prev: Introduction, Up: Top - -Preparations -************ - - This chapter contains information on how to prepare your system to -support tinc. - -* Menu: - -* Configuring the kernel:: -* Libraries:: - - -File: tinc.info, Node: Configuring the kernel, Next: Libraries, Prev: Preparations, Up: Preparations - -Configuring the kernel -====================== - - If you are running Linux, chances are good that your kernel already -supports all the devices that tinc needs for proper operation. For -example, the standard kernel from Redhat Linux already has support for -ethertap and netlink compiled in. Debian users can use the modconf -utility to select the modules. If your Linux distribution supports -this method of selecting devices, look out for something called -`ethertap', and `netlink_dev' if it is using a kernel version prior to -2.4.0. In that case you will need both these devices. If you are using -kernel 2.4.0 or later, you need to select `tun'. - - If you can install these devices in a similar manner, you may skip -this section. Otherwise, you will have to recompile the kernel in -order to turn on the required features. If you are unfamiliar with the -process of configuring and compiling a new kernel, you should read the -Kernel HOWTO (http://howto.linuxberg.com/LDP/HOWTO/Kernel-HOWTO.html) -first. - -* Menu: - -* Configuration of Linux kernels 2.1.60 up to 2.4.0:: -* Configuration of Linux kernels 2.4.0 and higher:: -* Configuration of FreeBSD kernels:: -* Configuration of OpenBSD kernels:: -* Configuration of Solaris kernels:: - - -File: tinc.info, Node: Configuration of Linux kernels 2.1.60 up to 2.4.0, Next: Configuration of Linux kernels 2.4.0 and higher, Prev: Configuring the kernel, Up: Configuring the kernel - -Configuration of Linux kernels 2.1.60 up to 2.4.0 -------------------------------------------------- - - Here are the options you have to turn on when configuring a new -kernel: - - Code maturity level options - [*] Prompt for development and/or incomplete code/drivers - Networking options - [*] Kernel/User netlink socket - Netlink device emulation - Network device support - Ethertap network tap - - If you want to run more than one instance of tinc or other programs -that use the ethertap, you have to compile the ethertap driver as a -module, otherwise you can also choose to compile it directly into the -kernel. - - If you decide to build any of these as dynamic kernel modules, it's -a good idea to add these lines to `/etc/modules.conf': - - alias char-major-36 netlink_dev - alias tap0 ethertap - options tap0 -o tap0 unit=0 - alias tap1 ethertap - options tap1 -o tap1 unit=1 - ... - alias tap_N_ ethertap - options tap_N_ -o tap_N_ unit=_N_ - - Add as much alias/options lines as necessary. - - -File: tinc.info, Node: Configuration of Linux kernels 2.4.0 and higher, Next: Configuration of FreeBSD kernels, Prev: Configuration of Linux kernels 2.1.60 up to 2.4.0, Up: Configuring the kernel - -Configuration of Linux kernels 2.4.0 and higher ------------------------------------------------ - - Here are the options you have to turn on when configuring a new -kernel: - - Code maturity level options - [*] Prompt for development and/or incomplete code/drivers - Network device support - Universal tun/tap device driver support - - It's not necessary to compile this driver as a module, even if you -are going to run more than one instance of tinc. - - If you have an early 2.4 kernel, you can choose both the tun/tap -driver and the `Ethertap network tap' device. This latter is marked -obsolete, and chances are that it won't even function correctly -anymore. Make sure you select the universal tun/tap driver. - - If you decide to build the tun/tap driver as a kernel module, add -these lines to `/etc/modules.conf': - - alias char-major-10-200 tun - - -File: tinc.info, Node: Configuration of FreeBSD kernels, Next: Configuration of OpenBSD kernels, Prev: Configuration of Linux kernels 2.4.0 and higher, Up: Configuring the kernel - -Configuration of FreeBSD kernels --------------------------------- - - This section will contain information on how to configure your -FreeBSD kernel to support the universal tun/tap device. For 4.1 and -higher versions, this is included in the default kernel configuration, -for earlier systems (4.0 and earlier), you need to install the -universal tun/tap driver yourself. - - Unfortunately somebody still has to write the text. - - -File: tinc.info, Node: Configuration of OpenBSD kernels, Next: Configuration of Solaris kernels, Prev: Configuration of FreeBSD kernels, Up: Configuring the kernel - -Configuration of OpenBSD kernels --------------------------------- - - This section will contain information on how to configure your -OpenBSD kernel to support the tun device. For 2.9 and 3.0 systems, -this is included in the default kernel configuration. - - Unfortunately somebody still has to write the text. - - -File: tinc.info, Node: Configuration of Solaris kernels, Prev: Configuration of OpenBSD kernels, Up: Configuring the kernel - -Configuration of Solaris kernels --------------------------------- - - This section will contain information on how to configure your -Solaris kernel to support the universal tun/tap device. For Solaris 8 -(SunOS 5.8), this is included in the default kernel configuration. - - Unfortunately somebody still has to write the text. - - -File: tinc.info, Node: Libraries, Prev: Configuring the kernel, Up: Preparations - -Libraries -========= - - Before you can configure or build tinc, you need to have the OpenSSL -library installed on your system. If you try to configure tinc without -having installed it, configure will give you an error message, and stop. - -* Menu: - -* OpenSSL:: -* zlib:: - - -File: tinc.info, Node: OpenSSL, Next: zlib, Prev: Libraries, Up: Libraries - -OpenSSL -------- - - For all cryptography-related functions, tinc uses the functions -provided by the OpenSSL library. - - If this library is not installed, you wil get an error when -configuring tinc for build. Support for running tinc without having -OpenSSL installed _may_ be added in the future. - - You can use your operating system's package manager to install this -if available. Make sure you install the development AND runtime -versions of this package. - - If you have to install OpenSSL manually, you can get the source code -from . Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - - If you installed the OpenSSL libraries from source, it may be -necessary to let configure know where they are, by passing configure -one of the -with-openssl-* parameters. - - --with-openssl=DIR OpenSSL library and headers prefix - --with-openssl-include=DIR OpenSSL headers directory - (Default is OPENSSL_DIR/include) - --with-openssl-lib=DIR OpenSSL library directory - (Default is OPENSSL_DIR/lib) - -License -....... - - Since the license under which OpenSSL is distributed is not directly -compatible with the terms of the GNU GPL -`http://www.openssl.org/support/faq.html#LEGAL2', therefore we include -an addition to the GPL (see also the file COPYING.README): - - This program is released under the GPL with the additional - exemption that compiling, linking, and/or using OpenSSL is - allowed. You may provide binary packages linked to the OpenSSL - libraries, provided that all other requirements of the GPL are met. - - -File: tinc.info, Node: zlib, Prev: OpenSSL, Up: Libraries - -zlib ----- - - For the optional compression of UDP packets, tinc uses the functions -provided by the zlib library. - - If this library is not installed, you wil get an error when -configuring tinc for build. Support for running tinc without having -zlib installed _may_ be added in the future. - - You can use your operating system's package manager to install this -if available. Make sure you install the development AND runtime -versions of this package. - - If you have to install zlib manually, you can get the source code -from . Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - - -File: tinc.info, Node: Installation, Next: Configuration, Prev: Preparations, Up: Top - -Installation -************ - - If you use Debian, you may want to install one of the precompiled -packages for your system. These packages are equipped with system -startup scripts and sample configurations. - - If you cannot use one of the precompiled packages, or you want to -compile tinc for yourself, you can use the source. The source is -distributed under the GNU General Public License (GPL). Download the -source from the download page (http://tinc.nl.linux.org/download.html), -which has the checksums of these files listed; you may wish to check -these with md5sum before continuing. - - tinc comes in a convenient autoconf/automake package, which you can -just treat the same as any other package. Which is just untar it, type -`configure' and then `make'. More detailed instructions are in the -file `INSTALL', which is included in the source distribution. - -* Menu: - -* Building and installing tinc:: -* System files:: - - -File: tinc.info, Node: Building and installing tinc, Next: System files, Prev: Installation, Up: Installation - -Building and installing tinc -============================ - - Detailed instructions on configuring the source, building tinc and -installing tinc can be found in the file called `INSTALL'. - - If you happen to have a binary package for tinc for your -distribution, you can use the package management tools of that -distribution to install tinc. The documentation that comes along with -your distribution will tell you how to do that. - - -File: tinc.info, Node: System files, Prev: Building and installing tinc, Up: Installation - -System files -============ - - Before you can run tinc, you must make sure you have all the needed -files on your system. - -* Menu: - -* Device files:: -* Other files:: - - -File: tinc.info, Node: Device files, Next: Other files, Prev: System files, Up: System files - -Device files ------------- - - First, you'll need the special device file(s) that form the interface -between the kernel and the daemon. - - The permissions for these files have to be such that only the super -user may read/write to this file. You'd want this, because otherwise -eavesdropping would become a bit too easy. This does, however, imply -that you'd have to run tincd as root. - - If you use Linux and have a kernel version prior to 2.4.0, you have -to make the ethertap devices: - - mknod -m 600 /dev/tap0 c 36 16 - chown 0.0 /dev/tap0 - mknod -m 600 /dev/tap1 c 36 17 - chown 0.0 /dev/tap0 - ... - mknod -m 600 /dev/tap_N_ c 36 _N+16_ - chown 0.0 /dev/tap_N_ - - There is a maximum of 16 ethertap devices. - - If you use the universal tun/tap driver, you have to create the -following device file (unless it already exist): - - mknod -m 600 /dev/tun c 10 200 - chown 0.0 /dev/tun - - If you use Linux, and you run the new 2.4 kernel using the devfs -filesystem, then the tun/tap device will probably be automatically -generated as `/dev/misc/net/tun'. - - Unlike the ethertap device, you do not need multiple device files if -you are planning to run multiple tinc daemons. - - -File: tinc.info, Node: Other files, Prev: Device files, Up: System files - -Other files ------------ - -`/etc/networks' -............... - - You may add a line to `/etc/networks' so that your VPN will get a -symbolic name. For example: - - myvpn 10.0.0.0 - -`/etc/services' -............... - - You may add this line to `/etc/services'. The effect is that you -may supply a `tinc' as a valid port number to some programs. The -number 655 is registered with the IANA. - - tinc 655/tcp TINC - tinc 655/udp TINC - # Ivo Timmermans - - -File: tinc.info, Node: Configuration, Next: Running tinc, Prev: Installation, Up: Top - -Configuration -************* - -* Menu: - -* Configuration introduction:: -* Multiple networks:: -* How connections work:: -* Configuration files:: -* Generating keypairs:: -* Network interfaces:: -* Example configuration:: - - -File: tinc.info, Node: Configuration introduction, Next: Multiple networks, Prev: Configuration, Up: Configuration - -Configuration introduction -========================== - - Before actually starting to configure tinc and editing files, make -sure you have read this entire section so you know what to expect. -Then, make it clear to yourself how you want to organize your VPN: What -are the nodes (computers running tinc)? What IP addresses/subnets do -they have? What is the network mask of the entire VPN? Do you need -special firewall rules? Do you have to set up masquerading or -forwarding rules? These questions can only be answered by yourself, -you will not find the answers in this documentation. Make sure you -have an adequate understanding of networks in general. A good resource -on networking is the Linux Network Administrators Guide -(http://www.linuxdoc.org/LDP/nag2/). - - If you have everything clearly pictured in your mind, proceed in the -following order: First, generate the configuration files (`tinc.conf', -your host configuration file, `tinc-up' and perhaps `tinc-down'). Then -generate the keypairs. Finally, distribute the host configuration -files. These steps are described in the subsections below. - - -File: tinc.info, Node: Multiple networks, Next: How connections work, Prev: Configuration introduction, Up: Configuration - -Multiple networks -================= - - In order to allow you to run more than one tinc daemon on one -computer, for instance if your computer is part of more than one VPN, -you can assign a "netname" to your VPN. It is not required if you only -run one tinc daemon, it doesn't even have to be the same on all the -sites of your VPN, but it is recommended that you choose one anyway. - - We will asume you use a netname throughout this document. This -means that you call tincd with the -n argument, which will assign a -netname to this daemon. - - The effect of this is that the daemon will set its configuration -"root" to /etc/tinc/netname/, where netname is your argument to the -n -option. You'll notice that it appears in syslog as "tinc.netname". - - However, it is not strictly necessary that you call tinc with the -n -option. In this case, the network name would just be empty, and it will -be used as such. tinc now looks for files in /etc/tinc/, instead of -/etc/tinc/netname/; the configuration file should be -/etc/tinc/tinc.conf, and the host configuration files are now expected -to be in /etc/tinc/hosts/. - - But it is highly recommended that you use this feature of tinc, -because it will be so much clearer whom your daemon talks to. Hence, -we will assume that you use it. - - -File: tinc.info, Node: How connections work, Next: Configuration files, Prev: Multiple networks, Up: Configuration - -How connections work -==================== - - When tinc starts up, it parses the command-line options and then -reads in the configuration file. If it sees a `ConnectTo' value -pointing to another tinc daemon in the file, it will try to connect to -that other one. Whether this succeeds or not and whether `ConnectTo' -is specified or not, tinc will listen for incoming connection from -other deamons. If you did specify a `ConnectTo' value and the other -side is not responding, tinc will keep retrying. This means that once -started, tinc will stay running until you tell it to stop, and failures -to connect to other tinc daemons will not stop your tinc daemon for -trying again later. This means you don't have to intervene if there -are any network problems. - - There is no real distinction between a server and a client in tinc. -If you wish, you can view a tinc daemon without a `ConnectTo' value as -a server, and one which does specify such a value as a client. It does -not matter if two tinc daemons have a `ConnectTo' value pointing to -eachother however. - - -File: tinc.info, Node: Configuration files, Next: Generating keypairs, Prev: How connections work, Up: Configuration - -Configuration files -=================== - - The actual configuration of the daemon is done in the file -`/etc/tinc/netname/tinc.conf' and at least one other file in the -directory `/etc/tinc/netname/hosts/'. - - These file consists of comments (lines started with a #) or -assignments in the form of - - Variable = Value. - - The variable names are case insensitive, and any spaces, tabs, -newlines and carriage returns are ignored. Note: it is not required -that you put in the `=' sign, but doing so improves readability. If -you leave it out, remember to replace it with at least one space -character. - - In this section all valid variables are listed in alphabetical order. -The default value is given between parentheses, other comments are -between square brackets and required directives are given in *bold*. - -* Menu: - -* Main configuration variables:: -* Host configuration variables:: -* How to configure:: - - -File: tinc.info, Node: Main configuration variables, Next: Host configuration variables, Prev: Configuration files, Up: Configuration files - -Main configuration variables ----------------------------- - -AddressFamily = (ipv4) [experimental] - This option affects the address family of listening and outgoing - sockets. If "any" is selected, then depending on the operating - system both IPv4 and IPv6 or just IPv6 listening sockets will be - created. - -BindToInterface = [experimental] - If you have more than one network interface in your computer, tinc - will by default listen on all of them for incoming connections. - It is possible to bind tinc to a single interface like eth0 or - ppp0 with this variable. - - This option may not work on all platforms. - -*ConnectTo = * - Specifies which host to connect to on startup. Multiple ConnectTo - variables may be specified, if connecting to the first one fails - then tinc will try the next one, and so on. It is possible to - specify hostnames for dynamic IP addresses (like those given on - dyndns.org), tinc will not cache the resolved IP address. - - If you don't specify a host with ConnectTo, regardless of whether a - value for ConnectPort is given, tinc won't connect at all, and will - instead just listen for incoming connections. - -*Device = * (/dev/tap0 or /dev/misc/net/tun) - The virtual network device to use. Note that you can only use one - device per daemon. See also *Note Device files::. - -Hostnames = (no) - This option selects whether IP addresses (both real and on the VPN) - should be resolved. Since DNS lookups are blocking, it might - affect tinc's efficiency, even stopping the daemon for a few - seconds everytime it does a lookup if your DNS server is not - responding. - - This does not affect resolving hostnames to IP addresses from the - configuration file. - -Interface = - Defines the name of the interface corresponding to the virtual - network device. Depending on the operating system and the type of - device this may or may not actually set the name. Currently this - option only affects the Linux tun/tap device. - -Mode = (router) - This option selects the way packets are routed to other daemons. - - router - In this mode Subnet variables in the host configuration files - will be used to form a routing table. Only unicast packets - of routable protocols (IPv4 and IPv6) are supported in this - mode. - - switch - In this mode the MAC addresses of the packets on the VPN will - be used to dynamically create a routing table just like an - Ethernet switch does. Unicast, multicast and broadcast - packets of every protocol that runs over Ethernet are - supported in this mode at the cost of frequent broadcast ARP - requests and routing table updates. - - hub - This mode is almost the same as the switch mode, but instead - every packet will be broadcast to the other daemons while no - routing table is managed. - -KeyExpire = (3600) - This option controls the time the encryption keys used to encrypt - the data are valid. It is common practice to change keys at - regular intervals to make it even harder for crackers, even though - it is thought to be nearly impossible to crack a single key. - -MACExpire = (600) - This option controls the amount of time MAC addresses are kept - before they are removed. This only has effect when Mode is set to - "switch". - -*Name = * - This is a symbolic name for this connection. It can be anything - -PingTimeout = (60) - The number of seconds of inactivity that tinc will wait before - sending a probe to the other end. If that other end doesn't - answer within that same amount of seconds, the connection is - terminated, and the others will be notified of this. - -PriorityInheritance = (no) [experimental] - When this option is enabled the value of the TOS field of tunneled - IPv4 packets will be inherited by the UDP packets that are sent - out. - -PrivateKey = [obsolete] - This is the RSA private key for tinc. However, for safety reasons - it is advised to store private keys of any kind in separate files. - This prevents accidental eavesdropping if you are editting the - configuration file. - -*PrivateKeyFile = * [recommended] - This is the full path name of the RSA private key file that was - generated by "tincd -generate-keys". It must be a full path, not a - relative directory. - - Note that there must be exactly one of PrivateKey or PrivateKeyFile - specified in the configuration file. - - -File: tinc.info, Node: Host configuration variables, Next: How to configure, Prev: Main configuration variables, Up: Configuration files - -Host configuration variables ----------------------------- - -*Address = * [recommended] - This variable is only required if you want to connect to this - host. It must resolve to the external IP address where the host - can be reached, not the one that is internal to the VPN. - -Cipher = (blowfish) - The symmetric cipher algorithm used to encrypt UDP packets. Any - cipher supported by OpenSSL is recognized. - -Compression = (0) - This option sets the level of compression used for UDP packets. - Possible values are 0 (off), 1 (fast) and any integer up to 9 - (best). - -Digest = (sha1) - The digest algorithm used to authenticate UDP packets. Any digest - supported by OpenSSL is recognized. Furthermore, specifying - "none" will turn off packet authentication. - -IndirectData = (no) - This option specifies whether other tinc daemons besides the one - you specified with ConnectTo can make a direct connection to you. - This is especially useful if you are behind a firewall and it is - impossible to make a connection from the outside to your tinc - daemon. Otherwise, it is best to leave this option out or set it - to no. - -MACLength = (4) - The length of the message authentication code used to authenticate - UDP packets. Can be anything from 0 up to the length of the - digest produced by the digest algorithm. - -Port = (655) - Connect to the upstream host (given with the ConnectTo directive) - on port port. port may be given in decimal (default), octal (when - preceded by a single zero) o hexadecimal (prefixed with 0x). port - is the port number for both the UDP and the TCP (meta) connections. - -PublicKey = [obsolete] - This is the RSA public key for this host. - -PublicKeyFile = [obsolete] - This is the full path name of the RSA public key file that was - generated by "tincd -generate-keys". It must be a full path, not - a relative directory. - - From version 1.0pre4 on tinc will store the public key directly - into the host configuration file in PEM format, the above two - options then are not necessary. Either the PEM format is used, or - exactly *one of the above two options* must be specified in each - host configuration file, if you want to be able to establish a - connection with that host. - -Subnet = - The subnet which this tinc daemon will serve. tinc tries to look - up which other daemon it should send a packet to by searching the - appropiate subnet. If the packet matches a subnet, it will be - sent to the daemon who has this subnet in his host configuration - file. Multiple subnet lines can be specified for each daemon. - - Subnets can either be single MAC, IPv4 or IPv6 addresses, in which - case a subnet consisting of only that single address is assumed, - or they can be a IPv4 or IPv6 network address with a prefixlength. - Shorthand notations are not supported. For example, IPv4 subnets - must be in a form like 192.168.1.0/24, where 192.168.1.0 is the - network address and 24 is the number of bits set in the netmask. - Note that subnets like 192.168.1.1/24 are invalid! Read a - networking HOWTO/FAQ/guide if you don't understand this. IPv6 - subnets are notated like fec0:0:0:1:0:0:0:0/64. MAC addresses are - notated like 0:1a:2b:3c:4d:5e. - - prefixlength is the number of bits set to 1 in the netmask part; - for example: netmask 255.255.255.0 would become /24, 255.255.252.0 - becomes /22. This conforms to standard CIDR notation as described - in RFC1519 (ftp://ftp.isi.edu/in-notes/rfc1519.txt) - -TCPonly = (no) [experimental] - If this variable is set to yes, then the packets are tunnelled - over a TCP connection instead of a UDP connection. This is - especially useful for those who want to run a tinc daemon from - behind a masquerading firewall, or if UDP packet routing is - disabled somehow. Setting this options also implicitly sets - IndirectData. - - -File: tinc.info, Node: How to configure, Prev: Host configuration variables, Up: Configuration files - -How to configure ----------------- - -Step 1. Creating the main configuration file -............................................. - - The main configuration file will be called -`/etc/tinc/netname/tinc.conf'. Adapt the following example to create a -basic configuration file: - - Name = _yourname_ - Device = _/dev/tap0_ - PrivateKeyFile = /etc/tinc/_netname_/rsa_key.priv - - Then, if you know to which other tinc daemon(s) yours is going to -connect, add `ConnectTo' values. - -Step 2. Creating your host configuration file -.............................................. - - If you added a line containing `Name = yourname' in the main -configuarion file, you will need to create a host configuration file -`/etc/tinc/netname/hosts/yourname'. Adapt the following example to -create a host configuration file: - - Address = _your.real.hostname.org_ - Subnet = _192.168.1.0/24_ - - You can also use an IP address instead of a hostname. The `Subnet' -specifies the address range that is local for _your part of the VPN -only_. If you have multiple address ranges you can specify more than -one `Subnet'. You might also need to add a `Port' if you want your -tinc daemon to run on a different port number than the default (655). - - -File: tinc.info, Node: Generating keypairs, Next: Network interfaces, Prev: Configuration files, Up: Configuration - -Generating keypairs -=================== - - Now that you have already created the main configuration file and -your host configuration file, you can easily create a public/private -keypair by entering the following command: - - tincd -n _netname_ -K - - tinc will generate a public and a private key and ask you where to -put them. Just press enter to accept the defaults. - - -File: tinc.info, Node: Network interfaces, Next: Example configuration, Prev: Generating keypairs, Up: Configuration - -Network interfaces -================== - - Before tinc can start transmitting data over the tunnel, it must set -up the virtual network interface. - - First, decide which IP addresses you want to have associated with -these devices, and what network mask they must have. - - tinc will open a virtual network device (`/dev/tun', `/dev/tap0' or -similar), which will also create a network interface called something -like `tun0', `tap0', or, if you are using the Linux tun/tap driver, the -network interface will by default have the same name as the netname. - - You can configure the network interface by putting ordinary -ifconfig, route, and other commands to a script named -`/etc/tinc/netname/tinc-up'. When tinc starts, this script will be -executed. When tinc exits, it will execute the script named -`/etc/tinc/netname/tinc-down', but normally you don't need to create -that script. - - An example `tinc-up' script: - - #!/bin/sh - ifconfig $INTERFACE hw ether fe:fd:0:0:0:0 - ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 - ifconfig $INTERFACE -arp - - The first line sets up the MAC address of the network interface. -Due to the nature of how Ethernet and tinc work, it has to be set to -fe:fd:0:0:0:0 for tinc to work in it's normal mode. If you configured -tinc to work in `switch' or `hub' mode, the hardware address should -instead be set to a unique address instead of fe:fd:0:0:0:0. - - You can use the environment variable $INTERFACE to get the name of -the interface. However, this might not be reliable. If in doubt, use -the name of the interface explicitly. - - The next line gives the interface an IP address and a netmask. The -kernel will also automatically add a route to this interface, so -normally you don't need to add route commands to the `tinc-up' script. -The kernel will also bring the interface up after this command. The -netmask is the mask of the _entire_ VPN network, not just your own -subnet. - - The last line tells the kernel not to use ARP on that interface. -Again this has to do with how Ethernet and tinc work. Use this option -only if you are running tinc under Linux and are using tinc's normal -routing mode. - - -File: tinc.info, Node: Example configuration, Prev: Network interfaces, Up: Configuration - -Example configuration -===================== - - Imagine the following situation. Branch A of our example `company' -wants to connect three branch offices in B, C and D using the Internet. -All four offices have a 24/7 connection to the Internet. - - A is going to serve as the center of the network. B and C will -connect to A, and D will connect to C. Each office will be assigned -their own IP network, 10.x.0.0. - - A: net 10.1.0.0 mask 255.255.0.0 gateway 10.1.54.1 internet IP 1.2.3.4 - B: net 10.2.0.0 mask 255.255.0.0 gateway 10.2.1.12 internet IP 2.3.4.5 - C: net 10.3.0.0 mask 255.255.0.0 gateway 10.3.69.254 internet IP 3.4.5.6 - D: net 10.4.0.0 mask 255.255.0.0 gateway 10.4.3.32 internet IP 4.5.6.7 - - "gateway" is the VPN IP address of the machine that is running the -tincd. "internet IP" is the IP address of the firewall, which does not -need to run tincd, but it must do a port forwarding of TCP&UDP on port -655 (unless otherwise configured). - - In this example, it is assumed that eth0 is the interface that -points to the inner (physical) LAN of the office, although this could -also be the same as the interface that leads to the Internet. The -configuration of the real interface is also shown as a comment, to give -you an idea of how these example host is set up. All branches use the -netname `company' for this particular VPN. - -For Branch A -............ - - _BranchA_ would be configured like this: - - In `/etc/tinc/company/tinc-up': - - # Real interface of internal network: - # ifconfig eth0 10.1.54.1 netmask 255.255.0.0 broadcast 10.1.255.255 - - ifconfig tap0 hw ether fe:fd:0:0:0:0 - ifconfig tap0 10.1.54.1 netmask 255.0.0.0 - ifconfig tap0 -arp - - and in `/etc/tinc/company/tinc.conf': - - Name = BranchA - PrivateKey = /etc/tinc/company/rsa_key.priv - Device = /dev/tap0 - - On all hosts, /etc/tinc/company/hosts/BranchA contains: - - Subnet = 10.1.0.0/16 - Address = 1.2.3.4 - - Note that the IP addresses of eth0 and tap0 are the same. - This is quite possible, if you make sure that the netmasks of the interfaces are different. - It is in fact recommended to give give both real internal network interfaces and tap interfaces the same IP address, - since that will make things a lot easier to remember and set up. - - -----BEGIN RSA PUBLIC KEY----- - ... - -----END RSA PUBLIC KEY----- - -For Branch B -............ - - In `/etc/tinc/company/tinc-up': - - # Real interface of internal network: - # ifconfig eth0 10.2.43.8 netmask 255.255.0.0 broadcast 10.2.255.255 - - ifconfig tap0 hw ether fe:fd:0:0:0:0 - ifconfig tap0 10.2.1.12 netmask 255.0.0.0 - ifconfig tap0 -arp - - and in `/etc/tinc/company/tinc.conf': - - Name = BranchB - ConnectTo = BranchA - PrivateKey = /etc/tinc/company/rsa_key.priv - - Note here that the internal address (on eth0) doesn't have to be the -same as on the tap0 device. Also, ConnectTo is given so that no-one can -connect to this node. - - On all hosts, in `/etc/tinc/company/hosts/BranchB': - - Subnet = 10.2.0.0/16 - Address = 2.3.4.5 - - -----BEGIN RSA PUBLIC KEY----- - ... - -----END RSA PUBLIC KEY----- - -For Branch C -............ - - In `/etc/tinc/company/tinc-up': - - # Real interface of internal network: - # ifconfig eth0 10.3.69.254 netmask 255.255.0.0 broadcast 10.3.255.255 - - ifconfig tap1 hw ether fe:fd:0:0:0:0 - ifconfig tap1 10.3.69.254 netmask 255.0.0.0 - ifconfig tap1 -arp - - and in `/etc/tinc/company/tinc.conf': - - Name = BranchC - ConnectTo = BranchA - Device = /dev/tap1 - - C already has another daemon that runs on port 655, so they have to -reserve another port for tinc. It knows the portnumber it has to listen -on from it's own host configuration file. - - On all hosts, in `/etc/tinc/company/hosts/BranchC': - - Address = 3.4.5.6 - Subnet = 10.3.0.0/16 - Port = 2000 - - -----BEGIN RSA PUBLIC KEY----- - ... - -----END RSA PUBLIC KEY----- - -For Branch D -............ - - In `/etc/tinc/company/tinc-up': - - # Real interface of internal network: - # ifconfig eth0 10.4.3.32 netmask 255.255.0.0 broadcast 10.4.255.255 - - ifconfig company hw ether fe:fd:0:0:0:0 - ifconfig company 10.4.3.32 netmask 255.0.0.0 - ifconfig company -arp - - and in `/etc/tinc/company/tinc.conf': - - Name = BranchD - ConnectTo = BranchC - Device = /dev/misc/net/tun - PrivateKeyFile = /etc/tinc/company/rsa_key.priv - - D will be connecting to C, which has a tincd running for this -network on port 2000. It knows the port number from the host -configuration file. Also note that since D uses the tun/tap driver, -the network interface will not be called `tun' or `tap0' or something -like that, but will have the same name as netname. - - On all hosts, in `/etc/tinc/company/hosts/BranchD': - - Subnet = 10.4.0.0/16 - Address = 4.5.6.7 - - -----BEGIN RSA PUBLIC KEY----- - ... - -----END RSA PUBLIC KEY----- - -Key files -......... - - A, B, C and D all have generated a public/private keypair with the -following command: - - tincd -n company -K - - The private key is stored in `/etc/tinc/company/rsa_key.priv', the -public key is put into the host configuration file in the -`/etc/tinc/company/hosts/' directory. During key generation, tinc -automatically guesses the right filenames based on the -n option and -the Name directive in the `tinc.conf' file (if it is available). - -Starting -........ - - After each branch has finished configuration and they have -distributed the host configuration files amongst them, they can start -their tinc daemons. They don't necessarily have to wait for the other -branches to have started their daemons, tinc will try connecting until -they are available. - - -File: tinc.info, Node: Running tinc, Next: Technical information, Prev: Configuration, Up: Top - -Running tinc -************ - - If everything else is done, you can start tinc by typing the -following command: - - tincd -n _netname_ - - tinc will detach from the terminal and continue to run in the -background like a good daemon. If there are any problems however you -can try to increase the debug level and look in the syslog to find out -what the problems are. - -* Menu: - -* Runtime options:: -* Error messages:: - - -File: tinc.info, Node: Runtime options, Next: Error messages, Up: Running tinc - -Runtime options -=============== - - Besides the settings in the configuration file, tinc also accepts -some command line options. - - This list is a longer version of that in the manpage. The latter is -generated automatically, so may be more up-to-date. - -`--bypass-security' - Disables encryption and authentication. Only useful for debugging. - -`-c, --config=PATH' - Read configuration options from the directory PATH. The default is - `/etc/tinc/netname/'. - -`-d, --debug=LEVEL' - Set debug level to LEVEL. The higher the debug level, the more - gets logged. Everything goes via syslog. - -`-K, --generate-keys[=BITS]' - Generate public/private keypair of BITS length. If BITS is not - specified, 1024 is the default. tinc will ask where you want to - store the files, but will default to the configuration directory - (you can use the -c or -n option in combination with -K). After - that, tinc will quit. - -`--help' - Display a short reminder of these runtime options and terminate. - -`-k, --kill[=SIGNAL]' - Attempt to kill a running tincd (optionally with the specified - SIGNAL instead of SIGTERM) and exit. Use it in conjunction with - the -n option to make sure you kill the right tinc daemon. - -`-n, --net=NETNAME' - Connect to net NETNAME. *Note Multiple networks::. - -`-D, --no-detach' - Don't fork and detach. This will also disable the automatic - restart mechanism for fatal errors. - -`--version' - Output version information and exit. - - -File: tinc.info, Node: Error messages, Prev: Runtime options, Up: Running tinc - -Error messages -============== - - What follows is a list of the most common error messages you can see -when configuring tinc. Most of these messages are visible in the syslog -only, so keep an eye on it! - -*Could not open /dev/tap0: No such device* - * You forgot to `modprobe netlink_dev' or `modprobe ethertap'. - - * You forgot to compile `Netlink device emulation' in the - kernel. - -*Can't write to /dev/misc/net/tun: No such device* - * You forgot to `modprobe tun'. - - * You forgot to compile `Universal TUN/TAP driver' in the - kernel. - -*Packet with destination 1.2.3.4 is looping back to us!* - * Something is not configured right. Packets are being sent out - to the virtual network device, but according to the Subnet - directives in your host configuration file, those packets - should go to your own host. Most common mistake is that you - have a Subnet line in your host configuration file with a - prefix length which is just as large as the prefix of the - virtual network interface. The latter should in almost all - cases be larger. Rethink your configuration. Note that you - will only see this message if you specified a debug level of - 5 or higher! - - * Chances are that a `Subnet = ...' line in the host - configuration file of this tinc daemon is wrong. Change it - to a subnet that is accepted locally by another interface, or - if that is not the case, try changing the prefix length into - /32. - -*Network doesn't work, syslog shows only packets of length 46* - Jan 1 12:00:00 host tinc.net[1234]: Read packet of length 46 from tap device - Jan 1 12:00:00 host tinc.net[1234]: Trying to look up 0.0.192.168 in connection list failed! - - * Add the `ifconfig $INTERFACE -arp' to tinc-up. - -*Network address and prefix length do not match!* - * The Subnet field must contain a _network_ address. - - * If you only want to use one IP address, set the netmask to - /32. - -*This is a bug: net.c:253: 24: Some error* - * This is something that should not have happened. Please - report this, and tell us exactly what went wrong before you - got this message. In normal operation, these errors should - not occur. - -*Error reading RSA key file `rsa_key.priv': No such file or directory* - * You must specify the complete pathname. Specifying a - relative path does not make sense here. tinc changes its - directory to / when starting (to avoid keeping a mount point - busy); and even if we built in a default directory to look - for these files, the key files are bound to be in a different - directory. - - -File: tinc.info, Node: Technical information, Next: About us, Prev: Running tinc, Up: Top - -Technical information -********************* - -* Menu: - -* The connection:: -* The meta-protocol:: -* Security:: - - -File: tinc.info, Node: The connection, Next: The meta-protocol, Prev: Technical information, Up: Technical information - -The connection -============== - - tinc is a daemon that takes VPN data and transmit that to another -host computer over the existing Internet infrastructure. - -* Menu: - -* The UDP tunnel:: -* The meta-connection:: - diff --git a/doc/tinc.info-2 b/doc/tinc.info-2 deleted file mode 100644 index c76d214..0000000 --- a/doc/tinc.info-2 +++ /dev/null @@ -1,520 +0,0 @@ -This is tinc.info, produced by makeinfo version 4.1 from tinc.texi. - -INFO-DIR-SECTION Networking tools -START-INFO-DIR-ENTRY -* tinc: (tinc). The tinc Manual. -END-INFO-DIR-ENTRY - - This is the info manual for tinc, a Virtual Private Network daemon. - - Copyright (C) 1998-2002 Ivo Timmermans , -Guus Sliepen and Wessel Dankers -. - - $Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - -File: tinc.info, Node: The UDP tunnel, Next: The meta-connection, Prev: The connection, Up: The connection - -The UDP tunnel --------------- - - The data itself is read from a character device file, the so-called -_virtual network device_. This device is associated with a network -interface. Any data sent to this interface can be read from the device, -and any data written to the device gets sent from the interface. Data -to and from the device is formatted as if it were a normal Ethernet -card, so a frame is preceded by two MAC addresses and a _frame type_ -field. - - So when tinc reads an Ethernet frame from the device, it determines -its type. When tinc is in it's default routing mode, it can handle IPv4 -and IPv6 packets. Depending on the Subnet lines, it will send the -packets off to their destination. In the `switch' and `hub' mode, tinc -will use broadcasts and MAC address discovery to deduce the destination -of the packets. Since the latter modes only depend on the link layer -information, any protocol that runs over Ethernet is supported (for -instance IPX and Appletalk). - - After the destination has been determined, a sequence number will be -added to the packet. The packet will then be encrypted and a message -authentication code will be appended. - - When that is done, time has come to actually transport the packet to -the destination computer. We do this by sending the packet over an UDP -connection to the destination host. This is called _encapsulating_, -the VPN packet (though now encrypted) is encapsulated in another IP -datagram. - - When the destination receives this packet, the same thing happens, -only in reverse. So it checks the message authentication code, -decrypts the contents of the UDP datagram, checks the sequence number -and writes the decrypted information to its own virtual network device. - - To let the kernel on the receiving end accept the packet, the -destination MAC address must match that of the virtual network -interface. If tinc is in it's default routing mode, ARP does not work, -so the correct destination MAC cannot be set by the sending daemons. -tinc solves this by always overwriting the destination MAC address with -fe:fd:0:0:0:0. That is also the reason why you must set the MAC address -of your tap interface to that address. - - -File: tinc.info, Node: The meta-connection, Prev: The UDP tunnel, Up: The connection - -The meta-connection -------------------- - - Having only an UDP connection available is not enough. Though -suitable for transmitting data, we want to be able to reliably send -other information, such as routing and session key information to -somebody. - - TCP is a better alternative, because it already contains protection -against information being lost, unlike UDP. - - So we establish two connections. One for the encrypted VPN data, -and one for other information, the meta-data. Hence, we call the second -connection the meta-connection. We can now be sure that the -meta-information doesn't get lost on the way to another computer. - - Like with any communication, we must have a protocol, so that -everybody knows what everything stands for, and how she should react. -Because we have two connections, we also have two protocols. The -protocol used for the UDP data is the "data-protocol," the other one is -the "meta-protocol." - - The reason we don't use TCP for both protocols is that UDP is much -better for encapsulation, even while it is less reliable. The real -problem is that when TCP would be used to encapsulate a TCP stream -that's on the private network, for every packet sent there would be -three ACKs sent instead of just one. Furthermore, if there would be a -timeout, both TCP streams would sense the timeout, and both would start -re-sending packets. - - -File: tinc.info, Node: The meta-protocol, Next: Security, Prev: The connection, Up: Technical information - -The meta-protocol -================= - - The meta protocol is used to tie all tinc daemons together, and -exchange information about which tinc daemon serves which virtual -subnet. - - The meta protocol consists of requests that can be sent to the other -side. Each request has a unique number and several parameters. All -requests are represented in the standard ASCII character set. It is -possible to use tools such as telnet or netcat to connect to a tinc -daemon and to read and write requests by hand, provided that one -understands the numeric codes sent. - - The authentication scheme is described in *Note Authentication -protocol::. After a successful authentication, the server and the -client will exchange all the information about other tinc daemons and -subnets they know of, so that both sides (and all the other tinc -daemons behind them) have their information synchronised. - - daemon message - -------------------------------------------------------------------------- - origin ADD_EDGE node1 12.23.34.45 655 node2 21.32.43.54 655 222 0 - | | | \___________________/ | +-> options - | | | | +----> weight - | | | +----------------> see below - | | +--> UDP port - | +----------> real address - +------------------> name of node on one side of the edge - - origin ADD_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> IPv4 network address - +------------------> owner of this subnet - -------------------------------------------------------------------------- - - In case a connection between two daemons is closed or broken, -DEL_EDGE messages are sent to inform the other daemons of that fact. -Each daemon will calculate a new route to the the daemons, or mark them -unreachable if there isn't any. - - The keys used to encrypt VPN packets are not sent out directly. This -is because it would generate a lot of traffic on VPNs with many -daemons, and chances are that not every tinc daemon will ever send a -packet to every other daemon. Instead, if a daemon needs a key it sends -a request for it via the meta connection of the nearest hop in the -direction of the destination. If any hop on the way has already learned -the key, it will act as a proxy and forward its copy back to the -requester. - - daemon message - -------------------------------------------------------------------------- - daemon REQ_KEY origin destination - | +--> name of the tinc daemon it wants the key from - +----------> name of the daemon that wants the key - - daemon ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 - | | \______________/ | | +--> MAC length - | | | | +-----> digest algorithm - | | | +--------> cipher algorithm - | | +--> 128 bits key - | +--> name of the daemon that wants the key - +----------> name of the daemon that uses this key - - daemon KEY_CHANGED origin - +--> daemon that has changed it's packet key - -------------------------------------------------------------------------- - - There is also a mechanism to check if hosts are still alive. Since -network failures or a crash can cause a daemon to be killed without -properly shutting down the TCP connection, this is necessary to keep an -up to date connection list. PINGs are sent at regular intervals, except -when there is also some other traffic. A little bit of salt (random -data) is added with each PING and PONG message, to make sure that long -sequences of PING/PONG messages without any other traffic won't result -in known plaintext. - - daemon message - -------------------------------------------------------------------------- - origin PING - dest. PONG - -------------------------------------------------------------------------- - - This basically covers what is sent over the meta connection by tinc. - - -File: tinc.info, Node: Security, Prev: The meta-protocol, Up: Technical information - -About tinc's encryption and other security-related issues. -========================================================== - - tinc got its name from "TINC," short for _There Is No Cabal_; the -alleged Cabal was/is an organisation that was said to keep an eye on the -entire Internet. As this is exactly what you _don't_ want, we named -the tinc project after TINC. - - But in order to be "immune" to eavesdropping, you'll have to encrypt -your data. Because tinc is a _Secure_ VPN (SVPN) daemon, it does -exactly that: encrypt. tinc by default uses blowfish encryption with -128 bit keys in CBC mode, 32 bit sequence numbers and 4 byte long -message authentication codes to make sure eavesdroppers cannot get and -cannot change any information at all from the packets they can -intercept. The encryption algorithm and message authentication -algorithm can be changed in the configuration. The length of the message -authentication codes is also adjustable. The length of the key for the -encryption algorithm is always the default length used by OpenSSL. - -* Menu: - -* Authentication protocol:: -* Encryption of network packets:: - - -File: tinc.info, Node: Authentication protocol, Next: Encryption of network packets, Prev: Security, Up: Security - -Authentication protocol ------------------------ - - A new scheme for authentication in tinc has been devised, which -offers some improvements over the protocol used in 1.0pre2 and 1.0pre3. -Explanation is below. - - daemon message - -------------------------------------------------------------------------- - client - - server - - client ID client 12 - | +---> version - +-------> name of tinc daemon - - server ID server 12 - | +---> version - +-------> name of tinc daemon - - client META_KEY 5f0823a93e35b69e...7086ec7866ce582b - \_________________________________/ - +-> RSAKEYLEN bits totally random string S1, - encrypted with server's public RSA key - - server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630 - \_________________________________/ - +-> RSAKEYLEN bits totally random string S2, - encrypted with client's public RSA key - - From now on: - - the client will symmetrically encrypt outgoing traffic using S1 - - the server will symmetrically encrypt outgoing traffic using S2 - - client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0 - \_________________________________/ - +-> CHALLEN bits totally random string H1 - - server CHALLENGE 57fb4b2ccd70d6bb35a64c142f47e61d57f - \_________________________________/ - +-> CHALLEN bits totally random string H2 - - client CHAL_REPLY 816a86 - +-> 160 bits SHA1 of H2 - - server CHAL_REPLY 928ffe - +-> 160 bits SHA1 of H1 - - After the correct challenge replies are received, both ends have proved - their identity. Further information is exchanged. - - client ACK 655 12.23.34.45 123 0 - | | | +-> options - | | +----> estimated weight - | +------------> IP address of server as seen by client - +--------------------> UDP port of client - - server ACK 655 21.32.43.54 321 0 - | | | +-> options - | | +----> estimated weight - | +------------> IP address of client as seen by server - +--------------------> UDP port of server - -------------------------------------------------------------------------- - - This new scheme has several improvements, both in efficiency and -security. - - First of all, the server sends exactly the same kind of messages -over the wire as the client. The previous versions of tinc first -authenticated the client, and then the server. This scheme even allows -both sides to send their messages simultaneously, there is no need to -wait for the other to send something first. This means that any -calculations that need to be done upon sending or receiving a message -can also be done in parallel. This is especially important when doing -RSA encryption/decryption. Given that these calculations are the main -part of the CPU time spent for the authentication, speed is improved by -a factor 2. - - Second, only one RSA encrypted message is sent instead of two. This -reduces the amount of information attackers can see (and thus use for a -cryptographic attack). It also improves speed by a factor two, making -the total speedup a factor 4. - - Third, and most important: The symmetric cipher keys are exchanged -first, the challenge is done afterwards. In the previous authentication -scheme, because a man-in-the-middle could pass the challenge/chal_reply -phase (by just copying the messages between the two real tinc daemons), -but no information was exchanged that was really needed to read the -rest of the messages, the challenge/chal_reply phase was of no real -use. The man-in-the-middle was only stopped by the fact that only after -the ACK messages were encrypted with the symmetric cipher. Potentially, -it could even send it's own symmetric key to the server (if it knew the -server's public key) and read some of the metadata the server would -send it (it was impossible for the mitm to read actual network packets -though). The new scheme however prevents this. - - This new scheme makes sure that first of all, symmetric keys are -exchanged. The rest of the messages are then encrypted with the -symmetric cipher. Then, each side can only read received messages if -they have their private key. The challenge is there to let the other -side know that the private key is really known, because a challenge -reply can only be sent back if the challenge is decrypted correctly, -and that can only be done with knowledge of the private key. - - Fourth: the first thing that is send via the symmetric cipher -encrypted connection is a totally random string, so that there is no -known plaintext (for an attacker) in the beginning of the encrypted -stream. - - -File: tinc.info, Node: Encryption of network packets, Prev: Authentication protocol, Up: Security - -Encryption of network packet ----------------------------- - - A data packet can only be sent if the encryption key is known to both -parties, and the connection is activated. If the encryption key is not -known, a request is sent to the destination using the meta connection -to retrieve it. The packet is stored in a queue while waiting for the -key to arrive. - - The UDP packet containing the network packet from the VPN has the -following layout: - - ... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer - \___________________/\_____/ - | | - V +---> digest algorithm - Encrypted with symmetric cipher - - So, the entire VPN packet is encrypted using a symmetric cipher. A -32 bits sequence number is added in front of the actual VPN packet, to -act as a unique IV for each packet and to prevent replay attacks. A -message authentication code is added to the UDP packet to prevent -alteration of packets. By default the first 4 bytes of the digest are -used for this, but this can be changed using the MACLength -configuration variable. - - -File: tinc.info, Node: About us, Next: Concept Index, Prev: Technical information, Up: Top - -About us -******** - -* Menu: - -* Contact Information:: -* Authors:: - - -File: tinc.info, Node: Contact Information, Next: Authors, Prev: About us, Up: About us - -Contact information -=================== - - tinc's website is at , this server is -located in the Netherlands. - - We have an IRC channel on the Open Projects IRC network. Connect to -irc.openprojects.net (http://openprojects.nu/services/irc.html), and -join channel #tinc. - - -File: tinc.info, Node: Authors, Prev: Contact Information, Up: About us - -Authors -======= - -Ivo Timmermans (zarq) () - Main coder/hacker and maintainer of the package. - -Guus Sliepen (guus) () - Originator of it all, co-author. - -Wessel Dankers (Ubiq) () - For the name `tinc' and various suggestions. - - We have received a lot of valuable input from users. With their -help, tinc has become the flexible and robust tool that it is today. -We have composed a list of contributions, in the file called `THANKS' in -the source distribution. - - -File: tinc.info, Node: Concept Index, Prev: About us, Up: Top - -Concept Index -************* - -* Menu: - -* ACK: Authentication protocol. -* ADD_EDGE: The meta-protocol. -* ADD_SUBNET: The meta-protocol. -* Address: Host configuration variables. -* AddressFamily: Main configuration variables. -* ANS_KEY: The meta-protocol. -* arp <1>: Error messages. -* arp: Network interfaces. -* authentication: Authentication protocol. -* binary package: Building and installing tinc. -* BindToInterface: Main configuration variables. -* Cabal: Security. -* CHAL_REPLY: Authentication protocol. -* CHALLENGE: Authentication protocol. -* CIDR notation: Host configuration variables. -* Cipher: Host configuration variables. -* client: How connections work. -* command line: Runtime options. -* Compression: Host configuration variables. -* connection: The connection. -* ConnectTo: Main configuration variables. -* daemon: Running tinc. -* data-protocol: The meta-connection. -* Debian: Configuring the kernel. -* debug level: Runtime options. -* DEL_EDGE: The meta-protocol. -* Device: Main configuration variables. -* device files: Device files. -* Digest: Host configuration variables. -* encapsulating: The UDP tunnel. -* encryption: Encryption of network packets. -* ethertap: Configuring the kernel. -* example: Example configuration. -* frame type: The UDP tunnel. -* FreeBSD: Supported platforms. -* hardware address: Network interfaces. -* Hostnames: Main configuration variables. -* hub: Main configuration variables. -* ID: Authentication protocol. -* ifconfig: Network interfaces. -* IndirectData: Host configuration variables. -* Interface: Main configuration variables. -* IRC: Contact Information. -* Kernel-HOWTO: Configuring the kernel. -* key generation: Generating keypairs. -* KEY_CHANGED: The meta-protocol. -* KeyExpire: Main configuration variables. -* libraries: Libraries. -* license: OpenSSL. -* Linux: Supported platforms. -* MAC address: Network interfaces. -* MACExpire: Main configuration variables. -* MACLength: Host configuration variables. -* meta-protocol: The meta-connection. -* META_KEY: Authentication protocol. -* Mode: Main configuration variables. -* multiple networks: Multiple networks. -* Name: Main configuration variables. -* netlink_dev: Configuring the kernel. -* netmask: Network interfaces. -* netname: Multiple networks. -* Network Administrators Guide: Configuration introduction. -* OpenBSD: Supported platforms. -* OpenSSL: OpenSSL. -* options: Runtime options. -* PEM format: Host configuration variables. -* PING: The meta-protocol. -* PingTimeout: Main configuration variables. -* platforms: Supported platforms. -* PONG: The meta-protocol. -* Port: Host configuration variables. -* port numbers: Other files. -* PriorityInheritance: Main configuration variables. -* private: VPNs. -* PrivateKey: Main configuration variables. -* PrivateKeyFile: Main configuration variables. -* PublicKey: Host configuration variables. -* PublicKeyFile: Host configuration variables. -* RedHat: Configuring the kernel. -* release: Supported platforms. -* REQ_KEY: The meta-protocol. -* requirements: Libraries. -* router: Main configuration variables. -* runtime options: Runtime options. -* scalability: tinc. -* server: How connections work. -* Solaris: Supported platforms. -* Subnet: Host configuration variables. -* SVPN: Security. -* switch: Main configuration variables. -* TCP: The meta-connection. -* TCPonly: Host configuration variables. -* TINC: Security. -* tinc: Introduction. -* tinc-up: Network interfaces. -* tincd: tinc. -* Traditional VPNs: tinc. -* tun: Configuring the kernel. -* UDP <1>: Encryption of network packets. -* UDP: The UDP tunnel. -* virtual: VPNs. -* virtual network device: The UDP tunnel. -* VPN: VPNs. -* vpnd: tinc. -* website: Contact Information. -* zlib: zlib. - - diff --git a/doc/tinc.texi b/doc/tinc.texi index 5ce852e..0420e6f 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -1,24 +1,23 @@ \input texinfo @c -*-texinfo-*- -@c $Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ @c %**start of header @setfilename tinc.info @settitle tinc Manual @setchapternewpage odd @c %**end of header +@include tincinclude.texi + @ifinfo @dircategory Networking tools @direntry * tinc: (tinc). The tinc Manual. @end direntry -This is the info manual for tinc, a Virtual Private Network daemon. +This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -Copyright @copyright{} 1998-2002 Ivo Timmermans -, Guus Sliepen and -Wessel Dankers . - -$Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ +Copyright @copyright{} 1998-2019 Ivo Timmermans, +Guus Sliepen and +Wessel Dankers . Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -38,12 +37,11 @@ permission notice identical to this one. @page @vskip 0pt plus 1filll -@cindex copyright -Copyright @copyright{} 1998-2002 Ivo Timmermans -, Guus Sliepen and -Wessel Dankers . +This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -$Id: tinc.texi,v 1.8.4.28 2002/04/09 11:43:29 guus Exp $ +Copyright @copyright{} 1998-2019 Ivo Timmermans, +Guus Sliepen and +Wessel Dankers . Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -56,29 +54,30 @@ permission notice identical to this one. @end titlepage +@ifnottex @c ================================================================== -@node Top, Introduction, (dir), (dir) +@node Top +@top Top @menu -* Introduction:: Introduction +* Introduction:: * Preparations:: * Installation:: * Configuration:: * Running tinc:: * Technical information:: +* Platform specific information:: * About us:: * Concept Index:: All used terms explained @end menu - - -@contents +@end ifnottex @c ================================================================== -@node Introduction, Preparations, Top, Top +@node Introduction @chapter Introduction @cindex tinc -tinc is a Virtual Private Network (VPN) daemon that uses tunneling and +Tinc is a Virtual Private Network (VPN) daemon that uses tunneling and encryption to create a secure private network between hosts on the Internet. @@ -92,13 +91,13 @@ configure your computer to use tinc, as well as the configuration process of tinc itself. @menu -* VPNs:: Virtual Private Networks in general -* tinc:: about tinc +* Virtual Private Networks:: +* tinc:: About tinc * Supported platforms:: @end menu @c ================================================================== -@node VPNs, tinc, Introduction, Introduction +@node Virtual Private Networks @section Virtual Private Networks @cindex VPN @@ -120,7 +119,7 @@ computers on the other end of the Internet. This problem can be solved by using @emph{virtual} networks. Virtual networks can live on top of other networks, but they use encapsulation to keep using their private address space so they do not interfere with -the Internet. Mostly, virtual networks appear like a singe LAN, even though +the Internet. Mostly, virtual networks appear like a single LAN, even though they can span the entire world. But virtual networks can't be secured by using firewalls, because the traffic that flows through it has to go through the Internet, where other people can look at it. @@ -136,7 +135,7 @@ through the VPN. This is what tinc was made for. @c ================================================================== -@node tinc, Supported platforms, VPNs, Introduction +@node tinc @section tinc @cindex vpnd @@ -144,22 +143,22 @@ I really don't quite remember what got us started, but it must have been Guus' idea. He wrote a simple implementation (about 50 lines of C) that used the ethertap device that Linux knows of since somewhere about kernel 2.1.60. It didn't work immediately and he improved it a -bit. At this stage, the project was still simply called @samp{vpnd}. +bit. At this stage, the project was still simply called "vpnd". Since then, a lot has changed---to say the least. @cindex tincd -tinc now supports encryption, it consists of a single daemon (tincd) for +Tinc now supports encryption, it consists of a single daemon (tincd) for both the receiving and sending end, it has become largely runtime-configurable---in short, it has become a full-fledged professional package. -@cindex Traditional VPNs +@cindex traditional VPNs @cindex scalability -tinc also allows more than two sites to connect to eachother and form a single VPN. +Tinc also allows more than two sites to connect to each other and form a single VPN. Traditionally VPNs are created by making tunnels, which only have two endpoints. Larger VPNs with more sites are created by adding more tunnels. -tinc takes another approach: only endpoints are specified, +Tinc takes another approach: only endpoints are specified, the software itself will take care of creating the tunnels. This allows for easier configuration and improved scalability. @@ -173,12 +172,12 @@ available too. @c ================================================================== -@node Supported platforms, , tinc, Introduction +@node Supported platforms @section Supported platforms @cindex platforms -tinc has been verified to work under Linux, FreeBSD, OpenBSD and Solaris, with -various hardware architectures. These are some of the platforms +Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, Mac OS X (Darwin), Solaris, and Windows (both natively and in a Cygwin environment), +with various hardware architectures. These are some of the platforms that are supported by the universal tun/tap device driver or other virtual network device drivers. Without such a driver, tinc will most likely compile and run, but it will not be able to send or receive data @@ -187,53 +186,7 @@ packets. @cindex release For an up to date list of supported platforms, please check the list on our website: -@uref{http://tinc.nl.linux.org/platforms.html}. - - -@c ================================================================== -@subsection Linux - -@cindex Linux -tinc was first written for Linux running on an intel x86 processor, so -this is the best supported platform. The protocol however, and actually -anything about tinc, has been rewritten to support random byte ordering -and arbitrary word length. So in theory it should run on other -processors that Linux runs on. It has already been verified to run on -alpha and sparc processors as well. - -tinc uses the ethertap device or the universal tun/tap driver. The former is provided in the standard kernel -from version 2.1.60 up to 2.3.x, but has been replaced in favour of the tun/tap driver in kernel versions 2.4.0 and later. - - -@c ================================================================== -@subsection FreeBSD - -@cindex FreeBSD -tinc on FreeBSD relies on the universal tun/tap driver for its data -acquisition from the kernel. Therefore, tinc will work on the same platforms -as this driver. These are: FreeBSD 3.x, 4.x, 5.x. - - -@c ================================================================== -@subsection OpenBSD - -@cindex OpenBSD -tinc on OpenBSD relies on the tun driver for its data -acquisition from the kernel. It has been verified to work under at least OpenBSD 2.9. - -Tunneling IPv6 packets may not work on OpenBSD. - - -@c ================================================================== -@subsection Solaris - -@cindex Solaris -tinc on Solaris relies on the universal tun/tap driver for its data -acquisition from the kernel. Therefore, tinc will work on the same platforms -as this driver. These are: Solaris 8 (SunOS 5.8). - -IPv6 packets cannot be tunneled on Solaris. - +@uref{https://www.tinc-vpn.org/platforms/}. @c @c @@ -249,7 +202,7 @@ IPv6 packets cannot be tunneled on Solaris. @c @c ================================================================== -@node Preparations, Installation, Introduction, Top +@node Preparations @chapter Preparations This chapter contains information on how to prepare your system to @@ -262,79 +215,27 @@ support tinc. @c ================================================================== -@node Configuring the kernel, Libraries, Preparations, Preparations +@node Configuring the kernel @section Configuring the kernel -@cindex RedHat -@cindex Debian -@cindex netlink_dev -@cindex tun -@cindex ethertap -If you are running Linux, chances are good that your kernel already supports -all the devices that tinc needs for proper operation. For example, the -standard kernel from Redhat Linux already has support for ethertap and netlink -compiled in. Debian users can use the modconf utility to select the modules. -If your Linux distribution supports this method of selecting devices, look out -for something called `ethertap', and `netlink_dev' if it is using a kernel -version prior to 2.4.0. In that case you will need both these devices. If you -are using kernel 2.4.0 or later, you need to select `tun'. - -@cindex Kernel-HOWTO -If you can install these devices in a similar manner, you may skip this section. -Otherwise, you will have to recompile the kernel in order to turn on the required features. -If you are unfamiliar with the process of configuring and compiling a new kernel, -you should read the @uref{http://howto.linuxberg.com/LDP/HOWTO/Kernel-HOWTO.html, Kernel HOWTO} first. - @menu -* Configuration of Linux kernels 2.1.60 up to 2.4.0:: -* Configuration of Linux kernels 2.4.0 and higher:: +* Configuration of Linux kernels:: * Configuration of FreeBSD kernels:: * Configuration of OpenBSD kernels:: +* Configuration of NetBSD kernels:: * Configuration of Solaris kernels:: +* Configuration of Darwin (Mac OS X) kernels:: +* Configuration of Windows:: @end menu @c ================================================================== -@node Configuration of Linux kernels 2.1.60 up to 2.4.0, Configuration of Linux kernels 2.4.0 and higher, Configuring the kernel, Configuring the kernel -@subsection Configuration of Linux kernels 2.1.60 up to 2.4.0 - -Here are the options you have to turn on when configuring a new kernel: - -@example -Code maturity level options -[*] Prompt for development and/or incomplete code/drivers -Networking options -[*] Kernel/User netlink socket - Netlink device emulation -Network device support - Ethertap network tap -@end example - -If you want to run more than one instance of tinc or other programs that use -the ethertap, you have to compile the ethertap driver as a module, otherwise -you can also choose to compile it directly into the kernel. - -If you decide to build any of these as dynamic kernel modules, it's a good idea -to add these lines to @file{/etc/modules.conf}: - -@example -alias char-major-36 netlink_dev -alias tap0 ethertap -options tap0 -o tap0 unit=0 -alias tap1 ethertap -options tap1 -o tap1 unit=1 -... -alias tap@emph{N} ethertap -options tap@emph{N} -o tap@emph{N} unit=@emph{N} -@end example - -Add as much alias/options lines as necessary. - - -@c ================================================================== -@node Configuration of Linux kernels 2.4.0 and higher, Configuration of FreeBSD kernels, Configuration of Linux kernels 2.1.60 up to 2.4.0, Configuring the kernel -@subsection Configuration of Linux kernels 2.4.0 and higher +@node Configuration of Linux kernels +@subsection Configuration of Linux kernels +@cindex Universal tun/tap +For tinc to work, you need a kernel that supports the Universal tun/tap device. +Most distributions come with kernels that already support this. Here are the options you have to turn on when configuring a new kernel: @example @@ -347,11 +248,6 @@ Network device support It's not necessary to compile this driver as a module, even if you are going to run more than one instance of tinc. -If you have an early 2.4 kernel, you can choose both the tun/tap driver and the -`Ethertap network tap' device. This latter is marked obsolete, and chances are -that it won't even function correctly anymore. Make sure you select the -universal tun/tap driver. - If you decide to build the tun/tap driver as a kernel module, add these lines to @file{/etc/modules.conf}: @@ -361,87 +257,118 @@ alias char-major-10-200 tun @c ================================================================== -@node Configuration of FreeBSD kernels, Configuration of OpenBSD kernels, Configuration of Linux kernels 2.4.0 and higher, Configuring the kernel +@node Configuration of FreeBSD kernels @subsection Configuration of FreeBSD kernels -This section will contain information on how to configure your FreeBSD -kernel to support the universal tun/tap device. For 4.1 and higher -versions, this is included in the default kernel configuration, for earlier -systems (4.0 and earlier), you need to install the universal tun/tap driver -yourself. - -Unfortunately somebody still has to write the text. +For FreeBSD version 4.1 and higher, tun and tap drivers are included in the default kernel configuration. +The tap driver can be loaded with @code{kldload if_tap}, or by adding @code{if_tap_load="YES"} to @file{/boot/loader.conf}. @c ================================================================== -@node Configuration of OpenBSD kernels, Configuration of Solaris kernels, Configuration of FreeBSD kernels, Configuring the kernel +@node Configuration of OpenBSD kernels @subsection Configuration of OpenBSD kernels -This section will contain information on how to configure your OpenBSD -kernel to support the tun device. For 2.9 and 3.0 systems, -this is included in the default kernel configuration. - -Unfortunately somebody still has to write the text. +Recent versions of OpenBSD come with both tun and tap devices enabled in the default kernel configuration. @c ================================================================== -@node Configuration of Solaris kernels, , Configuration of OpenBSD kernels, Configuring the kernel +@node Configuration of NetBSD kernels +@subsection Configuration of NetBSD kernels + +For NetBSD version 1.5.2 and higher, +the tun driver is included in the default kernel configuration. + +Tunneling IPv6 may not work on NetBSD's tun device. + + +@c ================================================================== +@node Configuration of Solaris kernels @subsection Configuration of Solaris kernels -This section will contain information on how to configure your Solaris -kernel to support the universal tun/tap device. For Solaris 8 (SunOS 5.8), -this is included in the default kernel configuration. - -Unfortunately somebody still has to write the text. +For Solaris 8 (SunOS 5.8) and higher, +the tun driver may or may not be included in the default kernel configuration. +If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}. +For x86 and sparc64 architectures, precompiled versions can be found at @uref{https://www.monkey.org/~dugsong/fragroute/}. +If the @file{net/if_tun.h} header file is missing, install it from the source package. @c ================================================================== -@node Libraries, , Configuring the kernel, Preparations +@node Configuration of Darwin (Mac OS X) kernels +@subsection Configuration of Darwin (Mac OS X) kernels + +Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel. +OS X version 10.6.8 and later have a built-in tun driver called "utun". +Tinc also supports the driver from @uref{http://tuntaposx.sourceforge.net/}, +which supports both tun and tap style devices. + +By default, tinc expects the tuntaposx driver to be installed. +To use the utun driver, set add @code{Device = utunX} to @file{tinc.conf}, +where X is the desired number for the utun interface. +You can also omit the number, in which case the first free number will be chosen. + + +@c ================================================================== +@node Configuration of Windows +@subsection Configuration of Windows + +You will need to install the latest TAP-Win32 driver from OpenVPN. +You can download it from @uref{https://openvpn.net/index.php/open-source/downloads.html}. +Using the Network Connections control panel, +configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script, +as explained in the rest of the documentation. + + +@c ================================================================== +@node Libraries @section Libraries @cindex requirements @cindex libraries -Before you can configure or build tinc, you need to have the OpenSSL -library installed on your system. If you try to configure tinc without -having installed it, configure will give you an error message, and stop. +Before you can configure or build tinc, you need to have the LibreSSL or OpenSSL, +zlib and lzo libraries installed on your system. If you try to configure tinc without +having them installed, configure will give you an error message, and stop. @menu -* OpenSSL:: +* LibreSSL/OpenSSL:: * zlib:: +* lzo:: @end menu @c ================================================================== -@node OpenSSL, zlib, Libraries, Libraries -@subsection OpenSSL +@node LibreSSL/OpenSSL +@subsection LibreSSL/OpenSSL +@cindex LibreSSL @cindex OpenSSL For all cryptography-related functions, tinc uses the functions provided -by the OpenSSL library. +by the LibreSSL or the OpenSSL library. -If this library is not installed, you wil get an error when configuring -tinc for build. Support for running tinc without having OpenSSL +If this library is not installed, you will get an error when configuring +tinc for build. Support for running tinc with other cryptographic libraries installed @emph{may} be added in the future. You can use your operating system's package manager to install this if available. Make sure you install the development AND runtime versions of this package. -If you have to install OpenSSL manually, you can get the source code -from @url{http://www.openssl.org/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the +If your operating system comes neither with LibreSSL or OpenSSL, you have to +install one manually. It is recommended that you get the latest version of +LibreSSL from @url{http://www.libressl.org/}. Instructions on how to +configure, build and install this package are included within the package. +Please make sure you build development and runtime libraries (which is the default). -If you installed the OpenSSL libraries from source, it may be necessary +If you installed the LibreSSL or OpenSSL libraries from source, it may be necessary to let configure know where they are, by passing configure one of the ---with-openssl-* parameters. +--with-openssl-* parameters. Note that you even have to use --with-openssl-* if you +are using LibreSSL. @example ---with-openssl=DIR OpenSSL library and headers prefix ---with-openssl-include=DIR OpenSSL headers directory +--with-openssl=DIR LibreSSL/OpenSSL library and headers prefix +--with-openssl-include=DIR LibreSSL/OpenSSL headers directory (Default is OPENSSL_DIR/include) ---with-openssl-lib=DIR OpenSSL library directory +--with-openssl-lib=DIR LibreSSL/OpenSSL library directory (Default is OPENSSL_DIR/lib) @end example @@ -449,10 +376,12 @@ to let configure know where they are, by passing configure one of the @subsubheading License @cindex license +The complete source code of tinc is covered by the GNU GPL version 2. Since the license under which OpenSSL is distributed is not directly compatible with the terms of the GNU GPL -@uref{http://www.openssl.org/support/faq.html#LEGAL2}, therefore we -include an addition to the GPL (see also the file COPYING.README): +@uref{https://www.openssl.org/support/faq.html#LEGAL2}, we +include an exemption to the GPL (see also the file COPYING.README) to allow +everyone to create a statically or dynamically linked executable: @quotation This program is released under the GPL with the additional exemption @@ -461,25 +390,62 @@ provide binary packages linked to the OpenSSL libraries, provided that all other requirements of the GPL are met. @end quotation +Since the LZO library used by tinc is also covered by the GPL, +we also present the following exemption: + +@quotation +Hereby I grant a special exception to the tinc VPN project +(https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library +(https://www.openssl.org). + +Markus F.X.J. Oberhumer +@end quotation + @c ================================================================== -@node zlib, , OpenSSL, Libraries +@node zlib @subsection zlib @cindex zlib For the optional compression of UDP packets, tinc uses the functions provided by the zlib library. -If this library is not installed, you wil get an error when configuring -tinc for build. Support for running tinc without having zlib -installed @emph{may} be added in the future. +If this library is not installed, you will get an error when running the +configure script. You can either install the zlib library, or disable support +for zlib compression by using the "--disable-zlib" option when running the +configure script. Note that if you disable support for zlib, the resulting +binary will not work correctly on VPNs where zlib compression is used. You can use your operating system's package manager to install this if available. Make sure you install the development AND runtime versions of this package. If you have to install zlib manually, you can get the source code -from @url{http://www.gzip.org/zlib/}. Instructions on how to configure, +from @url{https://zlib.net/}. Instructions on how to configure, +build and install this package are included within the package. Please +make sure you build development and runtime libraries (which is the +default). + + +@c ================================================================== +@node lzo +@subsection lzo + +@cindex lzo +Another form of compression is offered using the LZO library. + +If this library is not installed, you will get an error when running the +configure script. You can either install the LZO library, or disable support +for LZO compression by using the "--disable-lzo" option when running the +configure script. Note that if you disable support for LZO, the resulting +binary will not work correctly on VPNs where LZO compression is used. + +You can use your operating system's package manager to install this if +available. Make sure you install the development AND runtime versions +of this package. + +If you have to install lzo manually, you can get the source code +from @url{https://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure, build and install this package are included within the package. Please make sure you build development and runtime libraries (which is the default). @@ -495,7 +461,7 @@ default). @c @c ================================================================== -@node Installation, Configuration, Preparations, Top +@node Installation @chapter Installation If you use Debian, you may want to install one of the @@ -505,13 +471,11 @@ system startup scripts and sample configurations. If you cannot use one of the precompiled packages, or you want to compile tinc for yourself, you can use the source. The source is distributed under the GNU General Public License (GPL). Download the source from the -@uref{http://tinc.nl.linux.org/download.html, download page}, which has -the checksums of these files listed; you may wish to check these with -md5sum before continuing. +@uref{https://www.tinc-vpn.org/download/, download page}. -tinc comes in a convenient autoconf/automake package, which you can just +Tinc comes in a convenient autoconf/automake package, which you can just treat the same as any other package. Which is just untar it, type -`configure' and then `make'. +`./configure' and then `make'. More detailed instructions are in the file @file{INSTALL}, which is included in the source distribution. @@ -522,7 +486,7 @@ included in the source distribution. @c ================================================================== -@node Building and installing tinc, System files, Installation, Installation +@node Building and installing tinc @section Building and installing tinc Detailed instructions on configuring the source, building tinc and installing tinc @@ -533,9 +497,50 @@ If you happen to have a binary package for tinc for your distribution, you can use the package management tools of that distribution to install tinc. The documentation that comes along with your distribution will tell you how to do that. +@menu +* Darwin (Mac OS X) build environment:: +* Cygwin (Windows) build environment:: +* MinGW (Windows) build environment:: +@end menu + @c ================================================================== -@node System files, , Building and installing tinc, Installation +@node Darwin (Mac OS X) build environment +@subsection Darwin (Mac OS X) build environment + +In order to build tinc on Darwin, you need to install Xcode from @uref{https://developer.apple.com/xcode/}. +It might also help to install a recent version of Fink from @uref{http://www.finkproject.org/}. + +You need to download and install LibreSSL (or OpenSSL) and LZO, +either directly from their websites (see @ref{Libraries}) or using Fink. + +@c ================================================================== +@node Cygwin (Windows) build environment +@subsection Cygwin (Windows) build environment + +If Cygwin hasn't already been installed, install it directly from +@uref{https://www.cygwin.com/}. + +When tinc is compiled in a Cygwin environment, it can only be run in this environment, +but all programs, including those started outside the Cygwin environment, will be able to use the VPN. +It will also support all features. + +@c ================================================================== +@node MinGW (Windows) build environment +@subsection MinGW (Windows) build environment + +You will need to install the MinGW environment from @uref{http://www.mingw.org}. +You also need to download and install LibreSSL (or OpenSSL) and LZO. + +When tinc is compiled using MinGW it runs natively under Windows, +it is not necessary to keep MinGW installed. + +When detaching, tinc will install itself as a service, +which will be restarted automatically after reboots. + + +@c ================================================================== +@node System files @section System files Before you can run tinc, you must make sure you have all the needed @@ -548,51 +553,23 @@ files on your system. @c ================================================================== -@node Device files, Other files, System files, System files +@node Device files @subsection Device files @cindex device files -First, you'll need the special device file(s) that form the interface -between the kernel and the daemon. +Most operating systems nowadays come with the necessary device files by default, +or they have a mechanism to create them on demand. -The permissions for these files have to be such that only the super user -may read/write to this file. You'd want this, because otherwise -eavesdropping would become a bit too easy. This does, however, imply -that you'd have to run tincd as root. - -If you use Linux and have a kernel version prior to 2.4.0, you have to make the -ethertap devices: +If you use Linux and do not have udev installed, +you may need to create the following device file if it does not exist: @example -mknod -m 600 /dev/tap0 c 36 16 -chown 0.0 /dev/tap0 -mknod -m 600 /dev/tap1 c 36 17 -chown 0.0 /dev/tap0 -... -mknod -m 600 /dev/tap@emph{N} c 36 @emph{N+16} -chown 0.0 /dev/tap@emph{N} +mknod -m 600 /dev/net/tun c 10 200 @end example -There is a maximum of 16 ethertap devices. - -If you use the universal tun/tap driver, you have to create the -following device file (unless it already exist): - -@example -mknod -m 600 /dev/tun c 10 200 -chown 0.0 /dev/tun -@end example - -If you use Linux, and you run the new 2.4 kernel using the devfs filesystem, -then the tun/tap device will probably be automatically generated as -@file{/dev/misc/net/tun}. - -Unlike the ethertap device, you do not need multiple device files if -you are planning to run multiple tinc daemons. - @c ================================================================== -@node Other files, , Device files, System files +@node Other files @subsection Other files @subsubheading @file{/etc/networks} @@ -614,7 +591,7 @@ number 655 is registered with the IANA. @example tinc 655/tcp TINC tinc 655/udp TINC -# Ivo Timmermans +# Ivo Timmermans @end example @@ -630,7 +607,7 @@ tinc 655/udp TINC @c ================================================================== -@node Configuration, Running tinc, Installation, Top +@node Configuration @chapter Configuration @menu @@ -644,10 +621,9 @@ tinc 655/udp TINC @end menu @c ================================================================== -@node Configuration introduction, Multiple networks, Configuration, Configuration +@node Configuration introduction @section Configuration introduction -@cindex Network Administrators Guide Before actually starting to configure tinc and editing files, make sure you have read this entire section so you know what to expect. Then, make it clear to yourself how you want to organize your VPN: @@ -656,11 +632,13 @@ What IP addresses/subnets do they have? What is the network mask of the entire VPN? Do you need special firewall rules? Do you have to set up masquerading or forwarding rules? +Do you want to run tinc in router mode or switch mode? These questions can only be answered by yourself, you will not find the answers in this documentation. Make sure you have an adequate understanding of networks in general. +@cindex Network Administrators Guide A good resource on networking is the -@uref{http://www.linuxdoc.org/LDP/nag2/, Linux Network Administrators Guide}. +@uref{http://www.tldp.org/LDP/nag2/, Linux Network Administrators Guide}. If you have everything clearly pictured in your mind, proceed in the following order: @@ -671,31 +649,31 @@ These steps are described in the subsections below. @c ================================================================== -@node Multiple networks, How connections work, Configuration introduction, Configuration +@node Multiple networks @section Multiple networks @cindex multiple networks @cindex netname In order to allow you to run more than one tinc daemon on one computer, for instance if your computer is part of more than one VPN, -you can assign a ``netname'' to your VPN. +you can assign a @var{netname} to your VPN. It is not required if you only run one tinc daemon, it doesn't even have to be the same on all the sites of your VPN, but it is recommended that you choose one anyway. -We will asume you use a netname throughout this document. +We will assume you use a netname throughout this document. This means that you call tincd with the -n argument, which will assign a netname to this daemon. The effect of this is that the daemon will set its configuration -``root'' to /etc/tinc/netname/, where netname is your argument to the -n -option. You'll notice that it appears in syslog as ``tinc.netname''. +root to @file{@value{sysconfdir}/tinc/@var{netname}/}, where @var{netname} is your argument to the -n +option. You'll notice that it appears in syslog as @file{tinc.@var{netname}}. However, it is not strictly necessary that you call tinc with the -n option. In this case, the network name would just be empty, and it will -be used as such. tinc now looks for files in /etc/tinc/, instead of -/etc/tinc/netname/; the configuration file should be /etc/tinc/tinc.conf, -and the host configuration files are now expected to be in /etc/tinc/hosts/. +be used as such. tinc now looks for files in @file{@value{sysconfdir}/tinc/}, instead of +@file{@value{sysconfdir}/tinc/@var{netname}/}; the configuration file should be @file{@value{sysconfdir}/tinc/tinc.conf}, +and the host configuration files are now expected to be in @file{@value{sysconfdir}/tinc/hosts/}. But it is highly recommended that you use this feature of tinc, because it will be so much clearer whom your daemon talks to. Hence, we will @@ -703,37 +681,40 @@ assume that you use it. @c ================================================================== -@node How connections work, Configuration files, Multiple networks, Configuration +@node How connections work @section How connections work When tinc starts up, it parses the command-line options and then -reads in the configuration file. -If it sees a `ConnectTo' value pointing to another tinc daemon in the file, -it will try to connect to that other one. +reads in the configuration file tinc.conf. +If it sees one or more `ConnectTo' values pointing to other tinc daemons in that file, +it will try to connect to those other daemons. Whether this succeeds or not and whether `ConnectTo' is specified or not, -tinc will listen for incoming connection from other deamons. +tinc will listen for incoming connection from other daemons. If you did specify a `ConnectTo' value and the other side is not responding, tinc will keep retrying. This means that once started, tinc will stay running until you tell it to stop, and failures to connect to other tinc daemons will not stop your tinc daemon for trying again later. -This means you don't have to intervene if there are any network problems. +This means you don't have to intervene if there are temporary network problems. @cindex client @cindex server There is no real distinction between a server and a client in tinc. If you wish, you can view a tinc daemon without a `ConnectTo' value as a server, and one which does specify such a value as a client. -It does not matter if two tinc daemons have a `ConnectTo' value pointing to eachother however. +It does not matter if two tinc daemons have a `ConnectTo' value pointing to each other however. @c ================================================================== -@node Configuration files, Generating keypairs, How connections work, Configuration +@node Configuration files @section Configuration files The actual configuration of the daemon is done in the file -@file{/etc/tinc/netname/tinc.conf} and at least one other file in the directory -@file{/etc/tinc/netname/hosts/}. +@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf} and at least one other file in the directory +@file{@value{sysconfdir}/tinc/@var{netname}/hosts/}. + +An optional directory @file{@value{sysconfdir}/tinc/@var{netname}/conf.d} can be added from which +any .conf file will be read. These file consists of comments (lines started with a #) or assignments in the form of @@ -747,31 +728,51 @@ and carriage returns are ignored. Note: it is not required that you put in the `=' sign, but doing so improves readability. If you leave it out, remember to replace it with at least one space character. +The server configuration is complemented with host specific configuration (see +the next section). Although all host configuration options for the local node +listed in this document can also be put in +@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf}, it is recommended to +put host specific configuration options in the host configuration file, as this +makes it easy to exchange with other nodes. + In this section all valid variables are listed in alphabetical order. The default value is given between parentheses, -other comments are between square brackets and -required directives are given in @strong{bold}. +other comments are between square brackets. @menu * Main configuration variables:: * Host configuration variables:: +* Scripts:: * How to configure:: @end menu @c ================================================================== -@node Main configuration variables, Host configuration variables, Configuration files, Configuration files +@node Main configuration variables @subsection Main configuration variables @table @asis @cindex AddressFamily -@item AddressFamily = (ipv4) [experimental] +@item AddressFamily = (any) This option affects the address family of listening and outgoing sockets. -If "any" is selected, then depending on the operating system +If any is selected, then depending on the operating system both IPv4 and IPv6 or just IPv6 listening sockets will be created. +@cindex BindToAddress +@item BindToAddress = <@var{address}> [<@var{port}>] [experimental] +If your computer has more than one IPv4 or IPv6 address, tinc +will by default listen on all of them for incoming connections. +Multiple BindToAddress variables may be specified, +in which case listening sockets for each specified address are made. + +If no @var{port} is specified, the socket will be bound to the port specified by the Port option, +or to port 655 if neither is given. +To only bind to a specific port but not to a specific address, use "*" for the @var{address}. + +This option may not work on all platforms. + @cindex BindToInterface -@item BindToInterface = [experimental] +@item BindToInterface = <@var{interface}> [experimental] If you have more than one network interface in your computer, tinc will by default listen on all of them for incoming connections. It is possible to bind tinc to a single interface like eth0 or ppp0 with this @@ -779,38 +780,215 @@ variable. This option may not work on all platforms. -@cindex ConnectTo -@item @strong{ConnectTo = } -Specifies which host to connect to on startup. Multiple ConnectTo -variables may be specified, if connecting to the first one fails then -tinc will try the next one, and so on. It is possible to specify -hostnames for dynamic IP addresses (like those given on dyndns.org), -tinc will not cache the resolved IP address. +@cindex Broadcast +@item Broadcast = (mst) [experimental] +This option selects the way broadcast packets are sent to other daemons. +@emph{NOTE: all nodes in a VPN must use the same Broadcast mode, otherwise routing loops can form.} -If you don't specify a host with ConnectTo, regardless of whether a -value for ConnectPort is given, tinc won't connect at all, and will -instead just listen for incoming connections. +@table @asis +@item no +Broadcast packets are never sent to other nodes. + +@item mst +Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree. +This ensures broadcast packets reach all nodes. + +@item direct +Broadcast packets are sent directly to all nodes that can be reached directly. +Broadcast packets received from other nodes are never forwarded. +If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. +@end table + +@cindex ConnectTo +@item ConnectTo = <@var{name}> +Specifies which other tinc daemon to connect to on startup. +Multiple ConnectTo variables may be specified, +in which case outgoing connections to each specified tinc daemon are made. +The names should be known to this tinc daemon +(i.e., there should be a host configuration file for the name on the ConnectTo line). + +If you don't specify a host with ConnectTo, +tinc won't try to connect to other daemons at all, +and will instead just listen for incoming connections. + +@cindex DecrementTTL +@item DecrementTTL = (no) [experimental] +When enabled, tinc will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets, +before forwarding a received packet to the virtual network device or to another node, +and will drop packets that have a TTL value of zero, +in which case it will send an ICMP Time Exceeded packet back. + +Do not use this option if you use switch mode and want to use IPv6. @cindex Device -@item @strong{Device = } (/dev/tap0 or /dev/misc/net/tun) -The virtual network device to use. Note that you can only use one device per -daemon. See also @ref{Device files}. +@item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform) +The virtual network device to use. +Tinc will automatically detect what kind of device it is. +Under Windows, use @var{Interface} instead of @var{Device}. +Note that you can only use one device per daemon. +See also @ref{Device files}. + +@cindex DeviceType +@item DeviceType = <@var{type}> (platform dependent) +The type of the virtual network device. +Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. +However, this option can be used to select one of the special interface types, if support for them is compiled in. + +@table @asis +@cindex dummy +@item dummy +Use a dummy interface. +No packets are ever read or written to a virtual network device. +Useful for testing, or when setting up a node that only forwards packets for other nodes. + +@cindex raw_socket +@item raw_socket +Open a raw socket, and bind it to a pre-existing +@var{Interface} (eth0 by default). +All packets are read from this interface. +Packets received for the local node are written to the raw socket. +However, at least on Linux, the operating system does not process IP packets destined for the local host. + +@cindex multicast +@item multicast +Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using @var{Device}. +Packets are read from and written to this multicast socket. +This can be used to connect to UML, QEMU or KVM instances listening on the same multicast address. +Do NOT connect multiple tinc daemons to the same multicast address, this will very likely cause routing loops. +Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. + +@cindex UML +@item uml (not compiled in by default) +Create a UNIX socket with the filename specified by +@var{Device}, or @file{@value{runstatedir}/@var{netname}.umlsocket} +if not specified. +Tinc will wait for a User Mode Linux instance to connect to this socket. + +@cindex VDE +@item vde (not compiled in by default) +Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, +using the UNIX socket specified by +@var{Device}, or @file{@value{runstatedir}/vde.ctl} +if not specified. +@end table + +Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, +it can be used to change the way packets are interpreted: + +@table @asis +@item tun (BSD and Linux) +Set type to tun. +Depending on the platform, this can either be with or without an address family header (see below). + +@cindex tunnohead +@item tunnohead (BSD) +Set type to tun without an address family header. +Tinc will expect packets read from the virtual network device to start with an IP header. +On some platforms IPv6 packets cannot be read from or written to the device in this mode. + +@cindex tunifhead +@item tunifhead (BSD) +Set type to tun with an address family header. +Tinc will expect packets read from the virtual network device +to start with a four byte header containing the address family, +followed by an IP header. +This mode should support both IPv4 and IPv6 packets. + +@cindex utun +@item utun (OS X) +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +This mode should support both IPv4 and IPv6 packets. + +@item tap (BSD and Linux) +Set type to tap. +Tinc will expect packets read from the virtual network device +to start with an Ethernet header. +@end table + +@cindex DirectOnly +@item DirectOnly = (no) [experimental] +When this option is enabled, packets that cannot be sent directly to the destination node, +but which would have to be forwarded by an intermediate node, are dropped instead. +When combined with the IndirectData option, +packets for nodes for which we do not have a meta connection with are also dropped. + +@cindex Forwarding +@item Forwarding = (internal) [experimental] +This option selects the way indirect packets are forwarded. + +@table @asis +@item off +Incoming packets that are not meant for the local node, +but which should be forwarded to another node, are dropped. + +@item internal +Incoming packets that are meant for another node are forwarded by tinc internally. + +This is the default mode, and unless you really know you need another forwarding mode, don't change it. + +@item kernel +Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. +This is less efficient, but allows the kernel to apply its routing and firewall rules on them, +and can also help debugging. +@end table + +@cindex GraphDumpFile +@item GraphDumpFile = <@var{filename}> [experimental] +If this option is present, +tinc will dump the current network graph to the file @var{filename} +every minute, unless there were no changes to the graph. +The file is in a format that can be read by graphviz tools. +If @var{filename} starts with a pipe symbol |, +then the rest of the filename is interpreted as a shell command +that is executed, the graph is then sent to stdin. @cindex Hostnames @item Hostnames = (no) This option selects whether IP addresses (both real and on the VPN) should be resolved. Since DNS lookups are blocking, it might affect -tinc's efficiency, even stopping the daemon for a few seconds everytime +tinc's efficiency, even stopping the daemon for a few seconds every time it does a lookup if your DNS server is not responding. This does not affect resolving hostnames to IP addresses from the -configuration file. +configuration file, but whether hostnames should be resolved while logging. + +@cindex IffOneQueue +@item IffOneQueue = (no) [experimental] +(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. @cindex Interface -@item Interface = +@item Interface = <@var{interface}> Defines the name of the interface corresponding to the virtual network device. -Depending on the operating system and the type of device this may or may not actually set the name. -Currently this option only affects the Linux tun/tap device. +Depending on the operating system and the type of device this may or may not actually set the name of the interface. +Under Windows, this variable is used to select which network interface will be used. +If you specified a Device, this variable is almost always already correctly set. + +@cindex KeyExpire +@item KeyExpire = <@var{seconds}> (3600) +This option controls the time the encryption keys used to encrypt the data +are valid. It is common practice to change keys at regular intervals to +make it even harder for crackers, even though it is thought to be nearly +impossible to crack a single key. + +@cindex LocalDiscovery +@item LocalDiscovery = (no) [experimental] +When enabled, tinc will try to detect peers that are on the same local network. +This will allow direct communication using LAN addresses, even if both peers are behind a NAT +and they only ConnectTo a third node outside the NAT, +which normally would prevent the peers from learning each other's LAN address. + +Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. +This feature may not work in all possible situations. + +@cindex MACExpire +@item MACExpire = <@var{seconds}> (600) +This option controls the amount of time MAC addresses are kept before they are removed. +This only has effect when Mode is set to "switch". + +@cindex MaxTimeout +@item MaxTimeout = <@var{seconds}> (900) +This is the maximum delay before trying to reconnect to other tinc daemons. @cindex Mode @item Mode = (router) @@ -823,6 +1001,8 @@ In this mode Subnet variables in the host configuration files will be used to form a routing table. Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. +This is the default mode, and unless you really know you need another mode, don't change it. + @cindex switch @item switch In this mode the MAC addresses of the packets on the VPN will be used to @@ -830,6 +1010,8 @@ dynamically create a routing table just like an Ethernet switch does. Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode at the cost of frequent broadcast ARP requests and routing table updates. +This mode is primarily useful if you want to bridge Ethernet segments. + @cindex hub @item hub This mode is almost the same as the switch mode, but instead @@ -837,28 +1019,26 @@ every packet will be broadcast to the other daemons while no routing table is managed. @end table -@cindex KeyExpire -@item KeyExpire = (3600) -This option controls the time the encryption keys used to encrypt the data -are valid. It is common practice to change keys at regular intervals to -make it even harder for crackers, even though it is thought to be nearly -impossible to crack a single key. - -@cindex MACExpire -@item MACExpire = (600) -This option controls the amount of time MAC addresses are kept before they are removed. -This only has effect when Mode is set to "switch". - @cindex Name -@item @strong{Name = } -This is a symbolic name for this connection. It can be anything +@item Name = <@var{name}> [required] +This is a symbolic name for this connection. +The name must consist only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _). + +If Name starts with a $, then the contents of the environment variable that follows will be used. +In that case, invalid characters will be converted to underscores. +If Name is $HOST, but no such environment variable exist, +the hostname will be read using the gethostname() system call. + +@cindex PingInterval +@item PingInterval = <@var{seconds}> (60) +The number of seconds of inactivity that tinc will wait before sending a +probe to the other end. @cindex PingTimeout -@item PingTimeout = (60) -The number of seconds of inactivity that tinc will wait before sending a -probe to the other end. If that other end doesn't answer within that -same amount of seconds, the connection is terminated, and the others -will be notified of this. +@item PingTimeout = <@var{seconds}> (5) +The number of seconds to wait for a response to pings or to allow meta +connections to block. If the other end doesn't respond within this time, +the connection is terminated, and the others will be notified of this. @cindex PriorityInheritance @item PriorityInheritance = (no) [experimental] @@ -866,49 +1046,125 @@ When this option is enabled the value of the TOS field of tunneled IPv4 packets will be inherited by the UDP packets that are sent out. @cindex PrivateKey -@item PrivateKey = [obsolete] +@item PrivateKey = <@var{key}> [obsolete] This is the RSA private key for tinc. However, for safety reasons it is advised to store private keys of any kind in separate files. This prevents -accidental eavesdropping if you are editting the configuration file. +accidental eavesdropping if you are editing the configuration file. @cindex PrivateKeyFile -@item @strong{PrivateKeyFile = } [recommended] +@item PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/rsa_key.priv}) This is the full path name of the RSA private key file that was -generated by ``tincd --generate-keys''. It must be a full path, not a +generated by @samp{tincd --generate-keys}. It must be a full path, not a relative directory. -Note that there must be exactly one of PrivateKey -or PrivateKeyFile -specified in the configuration file. +@cindex ProcessPriority +@item ProcessPriority = +When this option is used the priority of the tincd process will be adjusted. +Increasing the priority may help to reduce latency and packet loss on the VPN. + +@cindex Proxy +@item Proxy = socks4 | socks5 | http | exec @var{...} [experimental] +Use a proxy when making outgoing connections. +The following proxy types are currently supported: + +@table @asis +@cindex socks4 +@item socks4 <@var{address}> <@var{port}> [<@var{username}>] +Connects to the proxy using the SOCKS version 4 protocol. +Optionally, a @var{username} can be supplied which will be passed on to the proxy server. + +@cindex socks5 +@item socks5 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>] +Connect to the proxy using the SOCKS version 5 protocol. +If a @var{username} and @var{password} are given, basic username/password authentication will be used, +otherwise no authentication will be used. + +@cindex http +@item http <@var{address}> <@var{port}> +Connects to the proxy and sends a HTTP CONNECT request. + +@cindex exec +@item exec <@var{command}> +Executes the given command which should set up the outgoing connection. +The environment variables @env{NAME}, @env{NODE}, @env{REMOTEADDRES} and @env{REMOTEPORT} are available. +@end table + +@cindex ReplayWindow +@item ReplayWindow = (16) +This is the size of the replay tracking window for each remote node, in bytes. +The window is a bitfield which tracks 1 packet per bit, so for example +the default setting of 16 will track up to 128 packets in the window. In high +bandwidth scenarios, setting this to a higher value can reduce packet loss from +the interaction of replay tracking with underlying real packet loss and/or +reordering. Setting this to zero will disable replay tracking completely and +pass all traffic, but leaves tinc vulnerable to replay-based attacks on your +traffic. + +@cindex StrictSubnets +@item StrictSubnets = (no) [experimental] +When this option is enabled tinc will only use Subnet statements which are +present in the host config files in the local +@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. +Subnets learned via connections to other nodes and which are not +present in the local host config files are ignored. + +@cindex TunnelServer +@item TunnelServer = (no) [experimental] +When this option is enabled tinc will no longer forward information between other tinc daemons, +and will only allow connections with nodes for which host config files are present in the local +@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. +Setting this options also implicitly sets StrictSubnets. + +@cindex UDPRcvBuf +@item UDPRcvBuf = (OS default) +Sets the socket receive buffer size for the UDP socket, in bytes. +If unset, the default buffer size will be used by the operating system. + +@cindex UDPSndBuf +@item UDPSndBuf = Pq OS default +Sets the socket send buffer size for the UDP socket, in bytes. +If unset, the default buffer size will be used by the operating system. @end table @c ================================================================== -@node Host configuration variables, How to configure, Main configuration variables, Configuration files +@node Host configuration variables @subsection Host configuration variables @table @asis @cindex Address -@item @strong{Address = } [recommended] +@item Address = <@var{IP address}|@var{hostname}> [] [recommended] This variable is only required if you want to connect to this host. It must resolve to the external IP address where the host can be reached, not the one that is internal to the VPN. +If no port is specified, the default Port is used. +Multiple Address variables can be specified, in which case each address will be +tried until a working connection has been established. @cindex Cipher -@item Cipher = (blowfish) +@item Cipher = <@var{cipher}> (aes-256-cbc) The symmetric cipher algorithm used to encrypt UDP packets. -Any cipher supported by OpenSSL is recognized. +Any cipher supported by LibreSSL or OpenSSL is recognized. +Furthermore, specifying "none" will turn off packet encryption. +It is best to use only those ciphers which support CBC mode. + +@cindex ClampMSS +@item ClampMSS = (yes) +This option specifies whether tinc should clamp the maximum segment size (MSS) +of TCP packets to the path MTU. This helps in situations where ICMP +Fragmentation Needed or Packet too Big messages are dropped by firewalls. @cindex Compression -@item Compression = (0) +@item Compression = <@var{level}> (0) This option sets the level of compression used for UDP packets. -Possible values are 0 (off), 1 (fast) and any integer up to 9 (best). +Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), +10 (fast lzo) and 11 (best lzo). @cindex Digest -@item Digest = (sha1) +@item Digest = <@var{digest}> (sha256) The digest algorithm used to authenticate UDP packets. -Any digest supported by OpenSSL is recognized. +Any digest supported by LibreSSL or OpenSSL is recognized. Furthermore, specifying "none" will turn off packet authentication. @cindex IndirectData @@ -920,26 +1176,33 @@ make a connection from the outside to your tinc daemon. Otherwise, it is best to leave this option out or set it to no. @cindex MACLength -@item MACLength = (4) +@item MACLength = <@var{bytes}> (4) The length of the message authentication code used to authenticate UDP packets. Can be anything from 0 up to the length of the digest produced by the digest algorithm. +@cindex PMTU +@item PMTU = <@var{mtu}> (1514) +This option controls the initial path MTU to this node. + +@cindex PMTUDiscovery +@item PMTUDiscovery = (yes) +When this option is enabled, tinc will try to discover the path MTU to this node. +After the path MTU has been discovered, it will be enforced on the VPN. + @cindex Port -@item Port = (655) -Connect to the upstream host (given with the ConnectTo directive) on -port port. port may be given in decimal (default), octal (when preceded -by a single zero) o hexadecimal (prefixed with 0x). port is the port -number for both the UDP and the TCP (meta) connections. +@item Port = <@var{port}> (655) +This is the port this tinc daemon listens on. +You can use decimal portnumbers or symbolic names (as listed in @file{/etc/services}). @cindex PublicKey -@item PublicKey = [obsolete] +@item PublicKey = <@var{key}> [obsolete] This is the RSA public key for this host. @cindex PublicKeyFile -@item PublicKeyFile = [obsolete] +@item PublicKeyFile = <@var{path}> [obsolete] This is the full path name of the RSA public key file that was generated -by ``tincd --generate-keys''. It must be a full path, not a relative +by @samp{tincd --generate-keys}. It must be a full path, not a relative directory. @cindex PEM format @@ -951,9 +1214,9 @@ in each host configuration file, if you want to be able to establish a connection with that host. @cindex Subnet -@item Subnet = +@item Subnet = <@var{address}[/@var{prefixlength}[#@var{weight}]]> The subnet which this tinc daemon will serve. -tinc tries to look up which other daemon it should send a packet to by searching the appropiate subnet. +Tinc tries to look up which other daemon it should send a packet to by searching the appropriate subnet. If the packet matches a subnet, it will be sent to the daemon who has this subnet in his host configuration file. Multiple subnet lines can be specified for each daemon. @@ -961,43 +1224,152 @@ Multiple subnet lines can be specified for each daemon. Subnets can either be single MAC, IPv4 or IPv6 addresses, in which case a subnet consisting of only that single address is assumed, or they can be a IPv4 or IPv6 network address with a prefixlength. -Shorthand notations are not supported. For example, IPv4 subnets must be in a form like 192.168.1.0/24, where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask. Note that subnets like 192.168.1.1/24 are invalid! Read a networking HOWTO/FAQ/guide if you don't understand this. -IPv6 subnets are notated like fec0:0:0:1:0:0:0:0/64. +IPv6 subnets are notated like fec0:0:0:1::/64. MAC addresses are notated like 0:1a:2b:3c:4d:5e. @cindex CIDR notation -prefixlength is the number of bits set to 1 in the netmask part; for +Prefixlength is the number of bits set to 1 in the netmask part; for example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes /22. This conforms to standard CIDR notation as described in -@uref{ftp://ftp.isi.edu/in-notes/rfc1519.txt, RFC1519} +@uref{https://www.ietf.org/rfc/rfc1519.txt, RFC1519} + +@cindex Subnet weight +A Subnet can be given a weight to indicate its priority over identical Subnets +owned by different nodes. The default weight is 10. Lower values indicate +higher priority. Packets will be sent to the node with the highest priority, +unless that node is not reachable, in which case the node with the next highest +priority will be tried, and so on. @cindex TCPonly -@item TCPonly = (no) [experimental] +@item TCPonly = (no) [deprecated] If this variable is set to yes, then the packets are tunnelled over a TCP connection instead of a UDP connection. This is especially useful for those who want to run a tinc daemon from behind a masquerading firewall, or if UDP packet routing is disabled somehow. Setting this options also implicitly sets IndirectData. + +Since version 1.0.10, tinc will automatically detect whether communication via +UDP is possible or not. @end table @c ================================================================== -@node How to configure, , Host configuration variables, Configuration files +@node Scripts +@subsection Scripts + +@cindex scripts +Apart from reading the server and host configuration files, +tinc can also run scripts at certain moments. +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. + +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. + +Under Windows (not Cygwin), the scripts must have the extension .bat. + +@table @file +@cindex tinc-up +@item @value{sysconfdir}/tinc/@var{netname}/tinc-up +This is the most important script. +If it is present it will be executed right after the tinc daemon has been +started and has connected to the virtual network device. +It should be used to set up the corresponding network interface, +but can also be used to start other things. + +Under Windows you can use the Network Connections control panel instead of creating this script. + +@cindex tinc-down +@item @value{sysconfdir}/tinc/@var{netname}/tinc-down +This script is started right before the tinc daemon quits. + +@item @value{sysconfdir}/tinc/@var{netname}/hosts/@var{host}-up +This script is started when the tinc daemon with name @var{host} becomes reachable. + +@item @value{sysconfdir}/tinc/@var{netname}/hosts/@var{host}-down +This script is started when the tinc daemon with name @var{host} becomes unreachable. + +@item @value{sysconfdir}/tinc/@var{netname}/host-up +This script is started when any host becomes reachable. + +@item @value{sysconfdir}/tinc/@var{netname}/host-down +This script is started when any host becomes unreachable. + +@item @value{sysconfdir}/tinc/@var{netname}/subnet-up +This script is started when a subnet becomes reachable. +The Subnet and the node it belongs to are passed in environment variables. + +@item @value{sysconfdir}/tinc/@var{netname}/subnet-down +This script is started when a subnet becomes unreachable. +@end table + +@cindex environment variables +The scripts are started without command line arguments, +but can make use of certain environment variables. +Under UNIX like operating systems the names of environment variables must be preceded by a $ in scripts. +Under Windows, in @file{.bat} files, they have to be put between % signs. + +@table @env +@cindex NETNAME +@item NETNAME +If a netname was specified, this environment variable contains it. + +@cindex NAME +@item NAME +Contains the name of this tinc daemon. + +@cindex DEVICE +@item DEVICE +Contains the name of the virtual network device that tinc uses. + +@cindex INTERFACE +@item INTERFACE +Contains the name of the virtual network interface that tinc uses. +This should be used for commands like ifconfig. + +@cindex NODE +@item NODE +When a host becomes (un)reachable, this is set to its name. +If a subnet becomes (un)reachable, this is set to the owner of that subnet. + +@cindex REMOTEADDRESS +@item REMOTEADDRESS +When a host becomes (un)reachable, this is set to its real address. + +@cindex REMOTEPORT +@item REMOTEPORT +When a host becomes (un)reachable, +this is set to the port number it uses for communication with other tinc daemons. + +@cindex SUBNET +@item SUBNET +When a subnet becomes (un)reachable, this is set to the subnet. + +@cindex WEIGHT +@item WEIGHT +When a subnet becomes (un)reachable, this is set to the subnet weight. + +@end table + + +@c ================================================================== +@node How to configure @subsection How to configure @subsubheading Step 1. Creating the main configuration file -The main configuration file will be called @file{/etc/tinc/netname/tinc.conf}. +The main configuration file will be called @file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf}. Adapt the following example to create a basic configuration file: @example -Name = @emph{yourname} -Device = @emph{/dev/tap0} -PrivateKeyFile = /etc/tinc/@emph{netname}/rsa_key.priv +Name = @var{yourname} +Device = @file{/dev/tap0} @end example Then, if you know to which other tinc daemon(s) yours is going to connect, @@ -1005,13 +1377,13 @@ add `ConnectTo' values. @subsubheading Step 2. Creating your host configuration file -If you added a line containing `Name = yourname' in the main configuarion file, -you will need to create a host configuration file @file{/etc/tinc/netname/hosts/yourname}. +If you added a line containing `Name = yourname' in the main configuration file, +you will need to create a host configuration file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/yourname}. Adapt the following example to create a host configuration file: @example -Address = @emph{your.real.hostname.org} -Subnet = @emph{192.168.1.0/24} +Address = your.real.hostname.org +Subnet = 192.168.1.0/24 @end example You can also use an IP address instead of a hostname. @@ -1021,7 +1393,7 @@ You might also need to add a `Port' if you want your tinc daemon to run on a dif @c ================================================================== -@node Generating keypairs, Network interfaces, Configuration files, Configuration +@node Generating keypairs @section Generating keypairs @cindex key generation @@ -1029,15 +1401,15 @@ Now that you have already created the main configuration file and your host conf you can easily create a public/private keypair by entering the following command: @example -tincd -n @emph{netname} -K +tincd -n @var{netname} -K @end example -tinc will generate a public and a private key and ask you where to put them. +Tinc will generate a public and a private key and ask you where to put them. Just press enter to accept the defaults. @c ================================================================== -@node Network interfaces, Example configuration, Generating keypairs, Configuration +@node Network interfaces @section Network interfaces Before tinc can start transmitting data over the tunnel, it must @@ -1046,38 +1418,25 @@ set up the virtual network interface. First, decide which IP addresses you want to have associated with these devices, and what network mask they must have. -tinc will open a virtual network device (@file{/dev/tun}, @file{/dev/tap0} or similar), -which will also create a network interface called something like `tun0', `tap0', or, -if you are using the Linux tun/tap driver, the network interface will by default have the same name as the netname. +Tinc will open a virtual network device (@file{/dev/tun}, @file{/dev/tap0} or similar), +which will also create a network interface called something like @samp{tun0}, @samp{tap0}. +If you are using the Linux tun/tap driver, the network interface will by default have the same name as the @var{netname}. +Under Windows you can change the name of the network interface from the Network Connections control panel. @cindex tinc-up You can configure the network interface by putting ordinary ifconfig, route, and other commands -to a script named @file{/etc/tinc/netname/tinc-up}. When tinc starts, this script -will be executed. When tinc exits, it will execute the script named -@file{/etc/tinc/netname/tinc-down}, but normally you don't need to create that script. +to a script named @file{@value{sysconfdir}/tinc/@var{netname}/tinc-up}. +When tinc starts, this script will be executed. When tinc exits, it will execute the script named +@file{@value{sysconfdir}/tinc/@var{netname}/tinc-down}, but normally you don't need to create that script. An example @file{tinc-up} script: @example #!/bin/sh -ifconfig $INTERFACE hw ether fe:fd:0:0:0:0 ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 -ifconfig $INTERFACE -arp @end example -@cindex MAC address -@cindex hardware address -The first line sets up the MAC address of the network interface. -Due to the nature of how Ethernet and tinc work, it has to be set to fe:fd:0:0:0:0 -for tinc to work in it's normal mode. -If you configured tinc to work in `switch' or `hub' mode, the hardware address should instead -be set to a unique address instead of fe:fd:0:0:0:0. - -You can use the environment variable $INTERFACE to get the name of the interface. -However, this might not be reliable. If in doubt, use the name of the interface explicitly. - -@cindex ifconfig -The next line gives the interface an IP address and a netmask. +This script gives the interface an IP address and a netmask. The kernel will also automatically add a route to this interface, so normally you don't need to add route commands to the @file{tinc-up} script. The kernel will also bring the interface up after this command. @@ -1085,14 +1444,13 @@ The kernel will also bring the interface up after this command. The netmask is the mask of the @emph{entire} VPN network, not just your own subnet. -@cindex arp -The last line tells the kernel not to use ARP on that interface. -Again this has to do with how Ethernet and tinc work. -Use this option only if you are running tinc under Linux and are using tinc's normal routing mode. +The exact syntax of the ifconfig and route commands differs from platform to platform. +You can look up the commands for setting addresses and adding routes in @ref{Platform specific information}, +but it is best to consult the manpages of those utilities on your platform. @c ================================================================== -@node Example configuration, , Network interfaces, Configuration +@node Example configuration @section Example configuration @@ -1112,9 +1470,9 @@ C: net 10.3.0.0 mask 255.255.0.0 gateway 10.3.69.254 internet IP 3.4.5.6 D: net 10.4.0.0 mask 255.255.0.0 gateway 10.4.3.32 internet IP 4.5.6.7 @end example -``gateway'' is the VPN IP address of the machine that is running the -tincd. ``internet IP'' is the IP address of the firewall, which does not -need to run tincd, but it must do a port forwarding of TCP&UDP on port +Here, ``gateway'' is the VPN IP address of the machine that is running the +tincd, and ``internet IP'' is the IP address of the firewall, which does not +need to run tincd, but it must do a port forwarding of TCP and UDP on port 655 (unless otherwise configured). In this example, it is assumed that eth0 is the interface that points to @@ -1128,68 +1486,62 @@ for this particular VPN. @emph{BranchA} would be configured like this: -In @file{/etc/tinc/company/tinc-up}: +In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example # Real interface of internal network: -# ifconfig eth0 10.1.54.1 netmask 255.255.0.0 broadcast 10.1.255.255 +# ifconfig eth0 10.1.54.1 netmask 255.255.0.0 -ifconfig tap0 hw ether fe:fd:0:0:0:0 -ifconfig tap0 10.1.54.1 netmask 255.0.0.0 -ifconfig tap0 -arp +ifconfig $INTERFACE 10.1.54.1 netmask 255.0.0.0 @end example -and in @file{/etc/tinc/company/tinc.conf}: +and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchA -PrivateKey = /etc/tinc/company/rsa_key.priv Device = /dev/tap0 @end example -On all hosts, /etc/tinc/company/hosts/BranchA contains: +On all hosts, @file{@value{sysconfdir}/tinc/company/hosts/BranchA} contains: @example Subnet = 10.1.0.0/16 Address = 1.2.3.4 -Note that the IP addresses of eth0 and tap0 are the same. -This is quite possible, if you make sure that the netmasks of the interfaces are different. -It is in fact recommended to give give both real internal network interfaces and tap interfaces the same IP address, -since that will make things a lot easier to remember and set up. - -----BEGIN RSA PUBLIC KEY----- ... -----END RSA PUBLIC KEY----- @end example +Note that the IP addresses of eth0 and tap0 are the same. +This is quite possible, if you make sure that the netmasks of the interfaces are different. +It is in fact recommended to give both real internal network interfaces and tap interfaces the same IP address, +since that will make things a lot easier to remember and set up. + @subsubheading For Branch B -In @file{/etc/tinc/company/tinc-up}: +In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example # Real interface of internal network: -# ifconfig eth0 10.2.43.8 netmask 255.255.0.0 broadcast 10.2.255.255 +# ifconfig eth0 10.2.43.8 netmask 255.255.0.0 -ifconfig tap0 hw ether fe:fd:0:0:0:0 -ifconfig tap0 10.2.1.12 netmask 255.0.0.0 -ifconfig tap0 -arp +ifconfig $INTERFACE 10.2.1.12 netmask 255.0.0.0 @end example -and in @file{/etc/tinc/company/tinc.conf}: +and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchB ConnectTo = BranchA -PrivateKey = /etc/tinc/company/rsa_key.priv @end example Note here that the internal address (on eth0) doesn't have to be the -same as on the tap0 device. Also, ConnectTo is given so that no-one can -connect to this node. +same as on the tap0 device. Also, ConnectTo is given so that this node will +always try to connect to BranchA. -On all hosts, in @file{/etc/tinc/company/hosts/BranchB}: +On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchB}: @example Subnet = 10.2.0.0/16 @@ -1203,18 +1555,16 @@ Address = 2.3.4.5 @subsubheading For Branch C -In @file{/etc/tinc/company/tinc-up}: +In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example # Real interface of internal network: -# ifconfig eth0 10.3.69.254 netmask 255.255.0.0 broadcast 10.3.255.255 +# ifconfig eth0 10.3.69.254 netmask 255.255.0.0 -ifconfig tap1 hw ether fe:fd:0:0:0:0 -ifconfig tap1 10.3.69.254 netmask 255.0.0.0 -ifconfig tap1 -arp +ifconfig $INTERFACE 10.3.69.254 netmask 255.0.0.0 @end example -and in @file{/etc/tinc/company/tinc.conf}: +and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchC @@ -1226,7 +1576,7 @@ C already has another daemon that runs on port 655, so they have to reserve another port for tinc. It knows the portnumber it has to listen on from it's own host configuration file. -On all hosts, in @file{/etc/tinc/company/hosts/BranchC}: +On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchC}: @example Address = 3.4.5.6 @@ -1241,24 +1591,21 @@ Port = 2000 @subsubheading For Branch D -In @file{/etc/tinc/company/tinc-up}: +In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example # Real interface of internal network: -# ifconfig eth0 10.4.3.32 netmask 255.255.0.0 broadcast 10.4.255.255 +# ifconfig eth0 10.4.3.32 netmask 255.255.0.0 -ifconfig company hw ether fe:fd:0:0:0:0 -ifconfig company 10.4.3.32 netmask 255.0.0.0 -ifconfig company -arp +ifconfig $INTERFACE 10.4.3.32 netmask 255.0.0.0 @end example -and in @file{/etc/tinc/company/tinc.conf}: +and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchD ConnectTo = BranchC -Device = /dev/misc/net/tun -PrivateKeyFile = /etc/tinc/company/rsa_key.priv +Device = /dev/net/tun @end example D will be connecting to C, which has a tincd running for this network on @@ -1267,7 +1614,7 @@ Also note that since D uses the tun/tap driver, the network interface will not be called `tun' or `tap0' or something like that, but will have the same name as netname. -On all hosts, in @file{/etc/tinc/company/hosts/BranchD}: +On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchD}: @example Subnet = 10.4.0.0/16 @@ -1286,8 +1633,8 @@ A, B, C and D all have generated a public/private keypair with the following com tincd -n company -K @end example -The private key is stored in @file{/etc/tinc/company/rsa_key.priv}, -the public key is put into the host configuration file in the @file{/etc/tinc/company/hosts/} directory. +The private key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv}, +the public key is put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory. During key generation, tinc automatically guesses the right filenames based on the -n option and the Name directive in the @file{tinc.conf} file (if it is available). @@ -1300,89 +1647,237 @@ their daemons, tinc will try connecting until they are available. @c ================================================================== -@node Running tinc, Technical information, Configuration, Top +@node Running tinc @chapter Running tinc If everything else is done, you can start tinc by typing the following command: @example -tincd -n @emph{netname} +tincd -n @var{netname} @end example @cindex daemon -tinc will detach from the terminal and continue to run in the background like a good daemon. +Tinc will detach from the terminal and continue to run in the background like a good daemon. If there are any problems however you can try to increase the debug level and look in the syslog to find out what the problems are. @menu * Runtime options:: +* Signals:: +* Debug levels:: +* Solving problems:: * Error messages:: +* Sending bug reports:: @end menu @c ================================================================== -@node Runtime options, Error messages, , Running tinc +@node Runtime options @section Runtime options Besides the settings in the configuration file, tinc also accepts some command line options. -This list is a longer version of that in the manpage. The latter is -generated automatically, so may be more up-to-date. - @cindex command line @cindex runtime options @cindex options @c from the manpage -@table @samp -@item --bypass-security -Disables encryption and authentication. -Only useful for debugging. - -@item -c, --config=PATH -Read configuration options from the directory PATH. The default is -@file{/etc/tinc/netname/}. - -@cindex debug level -@item -d, --debug=LEVEL -Set debug level to LEVEL. The higher the debug level, the more gets -logged. Everything goes via syslog. - -@item -K, --generate-keys[=BITS] -Generate public/private keypair of BITS length. If BITS is not specified, -1024 is the default. tinc will ask where you want to store the files, -but will default to the configuration directory (you can use the -c or -n option -in combination with -K). After that, tinc will quit. - -@item --help -Display a short reminder of these runtime options and terminate. - -@item -k, --kill[=SIGNAL] -Attempt to kill a running tincd (optionally with the specified SIGNAL instead of SIGTERM) and exit. -Use it in conjunction with the -n option to make sure you kill the right tinc daemon. - -@item -n, --net=NETNAME -Connect to net NETNAME. @xref{Multiple networks}. +@table @option +@item -c, --config=@var{path} +Read configuration options from the directory @var{path}. The default is +@file{@value{sysconfdir}/tinc/@var{netname}/}. @item -D, --no-detach Don't fork and detach. This will also disable the automatic restart mechanism for fatal errors. +@cindex debug level +@item -d, --debug=@var{level} +Set debug level to @var{level}. The higher the debug level, the more gets +logged. Everything goes via syslog. + +@item -k, --kill[=@var{signal}] +Attempt to kill a running tincd (optionally with the specified @var{signal} instead of SIGTERM) and exit. +Use it in conjunction with the -n option to make sure you kill the right tinc daemon. +Under native Windows the optional argument is ignored, +the service will always be stopped and removed. + +@item -n, --net=@var{netname} +Use configuration for net @var{netname}. +This will let tinc read all configuration files from +@file{@value{sysconfdir}/tinc/@var{netname}/}. +Specifying . for @var{netname} is the same as not specifying any @var{netname}. +@xref{Multiple networks}. + +@item -K, --generate-keys[=@var{bits}] +Generate public/private keypair of @var{bits} length. If @var{bits} is not specified, +2048 is the default. tinc will ask where you want to store the files, +but will default to the configuration directory (you can use the -c or -n option +in combination with -K). After that, tinc will quit. + +@item -o, --option=[@var{HOST}.]@var{KEY}=@var{VALUE} +Without specifying a @var{HOST}, this will set server configuration variable @var{KEY} to @var{VALUE}. +If specified as @var{HOST}.@var{KEY}=@var{VALUE}, +this will set the host configuration variable @var{KEY} of the host named @var{HOST} to @var{VALUE}. +This option can be used more than once to specify multiple configuration variables. + +@item -L, --mlock +Lock tinc into main memory. +This will prevent sensitive data like shared private keys to be written to the system swap files/partitions. + +@item --logfile[=@var{file}] +Write log entries to a file instead of to the system logging facility. +If @var{file} is omitted, the default is @file{@value{localstatedir}/log/tinc.@var{netname}.log}. + +@item --pidfile=@var{file} +Write PID to @var{file} instead of @file{@value{runstatedir}/tinc.@var{netname}.pid}. + +@item --bypass-security +Disables encryption and authentication. +Only useful for debugging. + +@item -R, --chroot +Change process root directory to the directory where the config file is +located (@file{@value{sysconfdir}/tinc/@var{netname}/} as determined by +-n/--net option or as given by -c/--config option), for added security. +The chroot is performed after all the initialization is done, after +writing pid files and opening network sockets. + +This option is best used in combination with the -U/--user option described below. + +You will need to ensure the chroot environment contains all the files necessary +for tinc to run correctly. +Most importantly, for tinc to be able to resolve hostnames inside the chroot environment, +you must copy @file{/etc/resolv.conf} into the chroot directory. +If you want to be able to run scripts other than @file{tinc-up} in the chroot, +you must ensure the appropriate shell is also installed in the chroot, along with all its dependencies. + +@item -U, --user=@var{user} +Switch to the given @var{user} after initialization, at the same time as +chroot is performed (see --chroot above). With this option tinc drops +privileges, for added security. + +@item --help +Display a short reminder of these runtime options and terminate. + @item --version Output version information and exit. @end table +@c ================================================================== +@node Signals +@section Signals + +@cindex signals +You can also send the following signals to a running tincd process: + +@c from the manpage +@table @samp + +@item ALRM +Forces tinc to try to connect to all uplinks immediately. +Usually tinc attempts to do this itself, +but increases the time it waits between the attempts each time it failed, +and if tinc didn't succeed to connect to an uplink the first time after it started, +it defaults to the maximum time of 15 minutes. + +@item HUP +Partially rereads configuration files. +Connections to hosts whose host config file are removed are closed. +New outgoing connections specified in @file{tinc.conf} will be made. +If the --logfile option is used, this will also close and reopen the log file, +useful when log rotation is used. + +@item INT +Temporarily increases debug level to 5. +Send this signal again to revert to the original level. + +@item USR1 +Dumps the connection list to syslog. + +@item USR2 +Dumps virtual network device statistics, all known nodes, edges and subnets to syslog. + +@item WINCH +Purges all information remembered about unreachable nodes. + +@end table @c ================================================================== -@node Error messages, , Runtime options, Running tinc +@node Debug levels +@section Debug levels + +@cindex debug levels +The tinc daemon can send a lot of messages to the syslog. +The higher the debug level, the more messages it will log. +Each level inherits all messages of the previous level: + +@c from the manpage +@table @samp + +@item 0 +This will log a message indicating tinc has started along with a version number. +It will also log any serious error. + +@item 1 +This will log all connections that are made with other tinc daemons. + +@item 2 +This will log status and error messages from scripts and other tinc daemons. + +@item 3 +This will log all requests that are exchanged with other tinc daemons. These include +authentication, key exchange and connection list updates. + +@item 4 +This will log a copy of everything received on the meta socket. + +@item 5 +This will log all network traffic over the virtual private network. + +@end table + +@c ================================================================== +@node Solving problems +@section Solving problems + +If tinc starts without problems, but if the VPN doesn't work, you will have to find the cause of the problem. +The first thing to do is to start tinc with a high debug level in the foreground, +so you can directly see everything tinc logs: + +@example +tincd -n @var{netname} -d5 -D +@end example + +If tinc does not log any error messages, then you might want to check the following things: + +@itemize +@item @file{tinc-up} script +Does this script contain the right commands? +Normally you must give the interface the address of this host on the VPN, and the netmask must be big enough so that the entire VPN is covered. + +@item Subnet +Does the Subnet (or Subnets) in the host configuration file of this host match the portion of the VPN that belongs to this host? + +@item Firewalls and NATs +Do you have a firewall or a NAT device (a masquerading firewall or perhaps an ADSL router that performs masquerading)? +If so, check that it allows TCP and UDP traffic on port 655. +If it masquerades and the host running tinc is behind it, make sure that it forwards TCP and UDP traffic to port 655 to the host running tinc. +You can add @samp{TCPOnly = yes} to your host config file to force tinc to only use a single TCP connection, +this works through most firewalls and NATs. Since version 1.0.10, tinc will automatically fall back to TCP if direct communication via UDP is not possible. + +@end itemize + + +@c ================================================================== +@node Error messages @section Error messages -What follows is a list of the most common error messages you can see -when configuring tinc. Most of these messages are visible in the syslog -only, so keep an eye on it! +What follows is a list of the most common error messages you might find in the logs. +Some of them will only be visible if the debug level is high enough. -@table @strong +@table @samp @item Could not open /dev/tap0: No such device @itemize @@ -1390,11 +1885,57 @@ only, so keep an eye on it! @item You forgot to compile `Netlink device emulation' in the kernel. @end itemize -@item Can't write to /dev/misc/net/tun: No such device +@item Can't write to /dev/net/tun: No such device @itemize @item You forgot to `modprobe tun'. @item You forgot to compile `Universal TUN/TAP driver' in the kernel. +@item The tun device is located somewhere else in @file{/dev/}. +@end itemize + +@item Network address and prefix length do not match! + +@itemize +@item The Subnet field must contain a @emph{network} address, trailing bits should be 0. +@item If you only want to use one IP address, set the netmask to /32. +@end itemize + +@item Error reading RSA key file `rsa_key.priv': No such file or directory + +@itemize +@item You forgot to create a public/private keypair. +@item Specify the complete pathname to the private key file with the @samp{PrivateKeyFile} option. +@end itemize + +@item Warning: insecure file permissions for RSA private key file `rsa_key.priv'! + +@itemize +@item The private key file is readable by users other than root. +Use chmod to correct the file permissions. +@end itemize + +@item Creating metasocket failed: Address family not supported + +@itemize +@item By default tinc tries to create both IPv4 and IPv6 sockets. +On some platforms this might not be implemented. +If the logs show @samp{Ready} later on, then at least one metasocket was created, +and you can ignore this message. +You can add @samp{AddressFamily = ipv4} to @file{tinc.conf} to prevent this from happening. +@end itemize + +@item Cannot route packet: unknown IPv4 destination 1.2.3.4 + +@itemize +@item You try to send traffic to a host on the VPN for which no Subnet is known. +@item If it is a broadcast address (ending in .255), it probably is a samba server or a Windows host sending broadcast packets. +You can ignore it. +@end itemize + +@item Cannot route packet: ARP request for unknown address 1.2.3.4 + +@itemize +@item You try to send traffic to a host on the VPN for which no Subnet is known. @end itemize @item Packet with destination 1.2.3.4 is looping back to us! @@ -1408,51 +1949,53 @@ just as large as the prefix of the virtual network interface. The latter should cases be larger. Rethink your configuration. Note that you will only see this message if you specified a debug level of 5 or higher! -@item Chances are that a `Subnet = ...' line in the host configuration file of this tinc daemon is wrong. +@item Chances are that a @samp{Subnet = ...} line in the host configuration file of this tinc daemon is wrong. Change it to a subnet that is accepted locally by another interface, -or if that is not the case, try changing the prefix length into /32. +or if that is not the case, try changing the prefix length into /32. @end itemize -@item Network doesn't work, syslog shows only packets of length 46 +@item Node foo (1.2.3.4) is not reachable -@cindex arp -@example -Jan 1 12:00:00 host tinc.net[1234]: Read packet of length 46 from tap device -Jan 1 12:00:00 host tinc.net[1234]: Trying to look up 0.0.192.168 in connection list failed! -@end example @itemize -@item Add the `ifconfig $INTERFACE -arp' to tinc-up. +@item Node foo does not have a connection anymore, its tinc daemon is not running or its connection to the Internet is broken. @end itemize -@item Network address and prefix length do not match! +@item Received UDP packet from unknown source 1.2.3.4 (port 12345) @itemize -@item The Subnet field must contain a @emph{network} address. -@item If you only want to use one IP address, set the netmask to /32. +@item If you see this only sporadically, it is harmless and caused by a node sending packets using an old key. @end itemize -@item This is a bug: net.c:253: 24: Some error +@item Got bad/bogus/unauthorized REQUEST from foo (1.2.3.4 port 12345) @itemize -@item This is something that should not have happened. -Please report this, and tell us exactly what went wrong before you got -this message. In normal operation, these errors should not occur. -@end itemize - -@item Error reading RSA key file `rsa_key.priv': No such file or directory - -@itemize -@item You must specify the complete pathname. -Specifying a relative path does not make sense here. tinc changes its -directory to / when starting (to avoid keeping a mount point busy); and -even if we built in a default directory to look for these files, the key -files are bound to be in a different directory. +@item Node foo does not have the right public/private keypair. +Generate new keypairs and distribute them again. +@item An attacker tries to gain access to your VPN. +@item A network error caused corruption of metadata sent from foo. @end itemize @end table @c ================================================================== -@node Technical information, About us, Running tinc, Top +@node Sending bug reports +@section Sending bug reports + +If you really can't find the cause of a problem, or if you suspect tinc is not working right, +you can send us a bugreport, see @ref{Contact information}. +Be sure to include the following information in your bugreport: + +@itemize +@item A clear description of what you are trying to achieve and what the problem is. +@item What platform (operating system, version, hardware architecture) and which version of tinc you use. +@item If compiling tinc fails, a copy of @file{config.log} and the error messages you get. +@item Otherwise, a copy of @file{tinc.conf}, @file{tinc-up} and all files in the @file{hosts/} directory. +@item The output of the commands @samp{ifconfig -a} and @samp{route -n} (or @samp{netstat -rn} if that doesn't work). +@item The output of any command that fails to work as it should (like ping or traceroute). +@end itemize + +@c ================================================================== +@node Technical information @chapter Technical information @@ -1464,11 +2007,11 @@ files are bound to be in a different directory. @c ================================================================== -@node The connection, The meta-protocol, Technical information, Technical information +@node The connection @section The connection @cindex connection -tinc is a daemon that takes VPN data and transmit that to another host +Tinc is a daemon that takes VPN data and transmit that to another host computer over the existing Internet infrastructure. @menu @@ -1478,7 +2021,7 @@ computer over the existing Internet infrastructure. @c ================================================================== -@node The UDP tunnel, The meta-connection, The connection, The connection +@node The UDP tunnel @subsection The UDP tunnel @cindex virtual network device @@ -1486,22 +2029,25 @@ computer over the existing Internet infrastructure. The data itself is read from a character device file, the so-called @emph{virtual network device}. This device is associated with a network interface. Any data sent to this interface can be read from the device, -and any data written to the device gets sent from the interface. Data to -and from the device is formatted as if it were a normal Ethernet card, -so a frame is preceded by two MAC addresses and a @emph{frame type} -field. +and any data written to the device gets sent from the interface. +There are two possible types of virtual network devices: +`tun' style, which are point-to-point devices which can only handle IPv4 and/or IPv6 packets, +and `tap' style, which are Ethernet devices and handle complete Ethernet frames. So when tinc reads an Ethernet frame from the device, it determines its -type. When tinc is in it's default routing mode, it can handle IPv4 and IPv6 -packets. Depending on the Subnet lines, it will send the packets off to their destination. +type. When tinc is in its default routing mode, it can handle IPv4 and IPv6 +packets. Depending on the Subnet lines, it will send the packets off to their destination IP address. In the `switch' and `hub' mode, tinc will use broadcasts and MAC address discovery to deduce the destination of the packets. Since the latter modes only depend on the link layer information, any protocol that runs over Ethernet is supported (for instance IPX and Appletalk). +However, only `tap' style devices provide this information. -After the destination has been determined, a sequence number will be added to the packet. -The packet will then be encrypted and a message authentication -code will be appended. +After the destination has been determined, +the packet will be compressed (optionally), +a sequence number will be added to the packet, +the packet will then be encrypted +and a message authentication code will be appended. @cindex encapsulating @cindex UDP @@ -1516,20 +2062,27 @@ in reverse. So it checks the message authentication code, decrypts the contents checks the sequence number and writes the decrypted information to its own virtual network device. -To let the kernel on the receiving end accept the packet, the destination MAC -address must match that of the virtual network interface. -If tinc is in it's default routing mode, ARP does not work, so the correct destination MAC cannot be set -by the sending daemons. -tinc solves this by always overwriting the -destination MAC address with fe:fd:0:0:0:0. That is also the reason why you must -set the MAC address of your tap interface to that address. +If the virtual network device is a `tun' device (a point-to-point tunnel), +there is no problem for the kernel to accept a packet. +However, if it is a `tap' device (this is the only available type on FreeBSD), +the destination MAC address must match that of the virtual network interface. +If tinc is in its default routing mode, ARP does not work, so the correct destination MAC +can not be known by the sending host. +Tinc solves this by letting the receiving end detect the MAC address of its own virtual network interface +and overwriting the destination MAC address of the received packet. + +In switch or hub modes ARP does work so the sender already knows the correct destination MAC address. +In those modes every interface should have a unique MAC address, so make sure they are not the same. +Because switch and hub modes rely on MAC addresses to function correctly, +these modes cannot be used on the following operating systems which don't have a `tap' style virtual network device: +NetBSD, Darwin and Solaris. @c ================================================================== -@node The meta-connection, , The UDP tunnel, The connection +@node The meta-connection @subsection The meta-connection -Having only an UDP connection available is not enough. Though suitable +Having only a UDP connection available is not enough. Though suitable for transmitting data, we want to be able to reliably send other information, such as routing and session key information to somebody. @@ -1560,7 +2113,7 @@ start re-sending packets. @c ================================================================== -@node The meta-protocol, Security, The connection, Technical information +@node The meta-protocol @section The meta-protocol The meta protocol is used to tie all tinc daemons together, and @@ -1571,7 +2124,8 @@ The meta protocol consists of requests that can be sent to the other side. Each request has a unique number and several parameters. All requests are represented in the standard ASCII character set. It is possible to use tools such as telnet or netcat to connect to a tinc -daemon and to read and write requests by hand, provided that one +daemon started with the --bypass-security option +and to read and write requests by hand, provided that one understands the numeric codes sent. The authentication scheme is described in @ref{Authentication protocol}. After a @@ -1583,57 +2137,89 @@ synchronised. @cindex ADD_EDGE @cindex ADD_SUBNET @example -daemon message --------------------------------------------------------------------------- -origin ADD_EDGE node1 12.23.34.45 655 node2 21.32.43.54 655 222 0 - | | | \___________________/ | +-> options - | | | | +----> weight - | | | +----------------> see below - | | +--> UDP port - | +----------> real address - +------------------> name of node on one side of the edge +message +------------------------------------------------------------------ +ADD_EDGE node1 node2 21.32.43.54 655 222 0 + | | | | | +-> options + | | | | +----> weight + | | | +--------> UDP port of node2 + | | +----------------> real address of node2 + | +-------------------------> name of destination node + +-------------------------------> name of source node -origin ADD_SUBNET node 192.168.1.0/24 - | | +--> prefixlength - | +--------> IPv4 network address - +------------------> owner of this subnet --------------------------------------------------------------------------- +ADD_SUBNET node 192.168.1.0/24 + | | +--> prefixlength + | +--------> network address + +------------------> owner of this subnet +------------------------------------------------------------------ @end example +The ADD_EDGE messages are to inform other tinc daemons that a connection between +two nodes exist. The address of the destination node is available so that +VPN packets can be sent directly to that node. + +The ADD_SUBNET messages inform other tinc daemons that certain subnets belong +to certain nodes. tinc will use it to determine to which node a VPN packet has +to be sent. + @cindex DEL_EDGE +@cindex DEL_SUBNET +@example +message +------------------------------------------------------------------ +DEL_EDGE node1 node2 + | +----> name of destination node + +----------> name of source node + +DEL_SUBNET node 192.168.1.0/24 + | | +--> prefixlength + | +--------> network address + +------------------> owner of this subnet +------------------------------------------------------------------ +@end example + In case a connection between two daemons is closed or broken, DEL_EDGE messages are sent to inform the other daemons of that fact. Each daemon will calculate a new route to the the daemons, or mark them unreachable if there isn't any. +@cindex REQ_KEY +@cindex ANS_KEY +@cindex KEY_CHANGED +@example +message +------------------------------------------------------------------ +REQ_KEY origin destination + | +--> name of the tinc daemon it wants the key from + +----------> name of the daemon that wants the key + +ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 + | | \______________/ | | +--> MAC length + | | | | +-----> digest algorithm + | | | +--------> cipher algorithm + | | +--> 128 bits key + | +--> name of the daemon that wants the key + +----------> name of the daemon that uses this key + +KEY_CHANGED origin + +--> daemon that has changed it's packet key +------------------------------------------------------------------ +@end example + The keys used to encrypt VPN packets are not sent out directly. This is because it would generate a lot of traffic on VPNs with many daemons, and chances are that not every tinc daemon will ever send a packet to every other daemon. Instead, if a daemon needs a key it sends a request for it via the meta connection of the nearest hop in the direction of the -destination. If any hop on the way has already learned the key, it will -act as a proxy and forward its copy back to the requester. +destination. -@cindex REQ_KEY -@cindex ANS_KEY -@cindex KEY_CHANGED +@cindex PING +@cindex PONG @example daemon message --------------------------------------------------------------------------- -daemon REQ_KEY origin destination - | +--> name of the tinc daemon it wants the key from - +----------> name of the daemon that wants the key - -daemon ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4 - | | \______________/ | | +--> MAC length - | | | | +-----> digest algorithm - | | | +--------> cipher algorithm - | | +--> 128 bits key - | +--> name of the daemon that wants the key - +----------> name of the daemon that uses this key - -daemon KEY_CHANGED origin - +--> daemon that has changed it's packet key --------------------------------------------------------------------------- +------------------------------------------------------------------ +origin PING +dest. PONG +------------------------------------------------------------------ @end example There is also a mechanism to check if hosts are still alive. Since network @@ -1644,27 +2230,16 @@ is also some other traffic. A little bit of salt (random data) is added with each PING and PONG message, to make sure that long sequences of PING/PONG messages without any other traffic won't result in known plaintext. -@cindex PING -@cindex PONG -@example -daemon message --------------------------------------------------------------------------- -origin PING -dest. PONG --------------------------------------------------------------------------- -@end example - -This basically covers what is sent over the meta connection by -tinc. +This basically covers what is sent over the meta connection by tinc. @c ================================================================== -@node Security, , The meta-protocol, Technical information -@section About tinc's encryption and other security-related issues. +@node Security +@section Security @cindex TINC @cindex Cabal -tinc got its name from ``TINC,'' short for @emph{There Is No Cabal}; the +Tinc got its name from ``TINC,'' short for @emph{There Is No Cabal}; the alleged Cabal was/is an organisation that was said to keep an eye on the entire Internet. As this is exactly what you @emph{don't} want, we named the tinc project after TINC. @@ -1673,22 +2248,23 @@ the tinc project after TINC. But in order to be ``immune'' to eavesdropping, you'll have to encrypt your data. Because tinc is a @emph{Secure} VPN (SVPN) daemon, it does exactly that: encrypt. -tinc by default uses blowfish encryption with 128 bit keys in CBC mode, 32 bit +Tinc by default uses blowfish encryption with 128 bit keys in CBC mode, 32 bit sequence numbers and 4 byte long message authentication codes to make sure eavesdroppers cannot get and cannot change any information at all from the packets they can intercept. The encryption algorithm and message authentication algorithm can be changed in the configuration. The length of the message authentication codes is also adjustable. The length of the key for the -encryption algorithm is always the default length used by OpenSSL. +encryption algorithm is always the default length used by LibreSSL/OpenSSL. @menu * Authentication protocol:: * Encryption of network packets:: +* Security issues:: @end menu @c ================================================================== -@node Authentication protocol, Encryption of network packets, Security, Security +@node Authentication protocol @subsection Authentication protocol @cindex authentication @@ -1747,17 +2323,15 @@ server CHAL_REPLY 928ffe After the correct challenge replies are received, both ends have proved their identity. Further information is exchanged. -client ACK 655 12.23.34.45 123 0 - | | | +-> options - | | +----> estimated weight - | +------------> IP address of server as seen by client - +--------------------> UDP port of client +client ACK 655 123 0 + | | +-> options + | +----> estimated weight + +--------> listening port of client -server ACK 655 21.32.43.54 321 0 - | | | +-> options - | | +----> estimated weight - | +------------> IP address of client as seen by server - +--------------------> UDP port of server +server ACK 655 321 0 + | | +-> options + | +----> estimated weight + +--------> listening port of server -------------------------------------------------------------------------- @end example @@ -1798,14 +2372,14 @@ known, because a challenge reply can only be sent back if the challenge is decrypted correctly, and that can only be done with knowledge of the private key. -Fourth: the first thing that is send via the symmetric cipher encrypted +Fourth: the first thing that is sent via the symmetric cipher encrypted connection is a totally random string, so that there is no known plaintext (for an attacker) in the beginning of the encrypted stream. @c ================================================================== -@node Encryption of network packets, , Authentication protocol, Security -@subsection Encryption of network packet +@node Encryption of network packets +@subsection Encryption of network packets @cindex encryption A data packet can only be sent if the encryption key is known to both @@ -1825,52 +2399,265 @@ The UDP packet containing the network packet from the VPN has the following layo Encrypted with symmetric cipher @end example -So, the entire VPN packet is encrypted using a symmetric cipher. A 32 bits -sequence number is added in front of the actual VPN packet, to act as a unique +So, the entire VPN packet is encrypted using a symmetric cipher, including a 32 bits +sequence number that is added in front of the actual VPN packet, to act as a unique IV for each packet and to prevent replay attacks. A message authentication code is added to the UDP packet to prevent alteration of packets. By default the first 4 bytes of the digest are used for this, but this can be changed using the MACLength configuration variable. @c ================================================================== -@node About us, Concept Index, Technical information, Top +@node Security issues +@subsection Security issues + +In August 2000, we discovered the existence of a security hole in all versions +of tinc up to and including 1.0pre2. This had to do with the way we exchanged +keys. Since then, we have been working on a new authentication scheme to make +tinc as secure as possible. The current version uses the LibreSSL or OpenSSL library and +uses strong authentication with RSA keys. + +On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc +1.0pre4. Due to a lack of sequence numbers and a message authentication code +for each packet, an attacker could possibly disrupt certain network services or +launch a denial of service attack by replaying intercepted packets. The current +version adds sequence numbers and message authentication codes to prevent such +attacks. + +On the 15th of September 2003, Peter Gutmann posted a security analysis of tinc +1.0.1. He argues that the 32 bit sequence number used by tinc is not a good IV, +that tinc's default length of 4 bytes for the MAC is too short, and he doesn't +like tinc's use of RSA during authentication. We do not know of a security hole +in this version of tinc, but tinc's security is not as strong as TLS or IPsec. +We will address these issues in tinc 2.0. + +Cryptography is a hard thing to get right. We cannot make any +guarantees. Time, review and feedback are the only things that can +prove the security of any cryptographic product. If you wish to review +tinc or give us feedback, you are strongly encouraged to do so. + + +@c ================================================================== +@node Platform specific information +@chapter Platform specific information + +@menu +* Interface configuration:: +* Routes:: +* Automatically starting tinc:: +@end menu + +@c ================================================================== +@node Interface configuration +@section Interface configuration + +When configuring an interface, one normally assigns it an address and a +netmask. The address uniquely identifies the host on the network attached to +the interface. The netmask, combined with the address, forms a subnet. It is +used to add a route to the routing table instructing the kernel to send all +packets which fall into that subnet to that interface. Because all packets for +the entire VPN should go to the virtual network interface used by tinc, the +netmask should be such that it encompasses the entire VPN. + +For IPv4 addresses: + +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item Linux iproute2 +@tab @code{ip addr add} @var{address}@code{/}@var{prefixlength} @code{dev} @var{interface} +@item FreeBSD +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item OpenBSD +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item NetBSD +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item Solaris +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item Darwin (Mac OS X) +@tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} +@item Windows +@tab @code{netsh interface ip set address} @var{interface} @code{static} @var{address} @var{netmask} +@end multitable + +For IPv6 addresses: + +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{ifconfig} @var{interface} @code{add} @var{address}@code{/}@var{prefixlength} +@item FreeBSD +@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} +@item OpenBSD +@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} +@item NetBSD +@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} +@item Solaris +@tab @code{ifconfig} @var{interface} @code{inet6 plumb up} +@item +@tab @code{ifconfig} @var{interface} @code{inet6 addif} @var{address} @var{address} +@item Darwin (Mac OS X) +@tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} +@item Windows +@tab @code{netsh interface ipv6 add address} @var{interface} @code{static} @var{address}/@var{prefixlength} +@end multitable + +On Linux, it is possible to create a persistent tun/tap interface which will +continue to exist even if tinc quit, although this is normally not required. +It can be useful to set up a tun/tap interface owned by a non-root user, so +tinc can be started without needing any root privileges at all. + +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{ip tuntap add dev} @var{interface} @code{mode} @var{tun|tap} @code{user} @var{username} +@end multitable + +@c ================================================================== +@node Routes +@section Routes + +In some cases it might be necessary to add more routes to the virtual network +interface. There are two ways to indicate which interface a packet should go +to, one is to use the name of the interface itself, another way is to specify +the (local) address that is assigned to that interface (@var{local_address}). The +former way is unambiguous and therefore preferable, but not all platforms +support this. + +Adding routes to IPv4 subnets: + +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{route add -net} @var{network_address} @code{netmask} @var{netmask} @var{interface} +@item Linux iproute2 +@tab @code{ip route add} @var{network_address}@code{/}@var{prefixlength} @code{dev} @var{interface} +@item FreeBSD +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} +@item OpenBSD +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} +@item NetBSD +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} +@item Solaris +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} +@item Darwin (Mac OS X) +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @code{-interface} @var{interface} +@item Windows +@tab @code{netsh routing ip add persistentroute} @var{network_address} @var{netmask} @var{interface} @var{local_address} +@end multitable + +Adding routes to IPv6 subnets: + +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{route add -A inet6} @var{network_address}@code{/}@var{prefixlength} @var{interface} +@item Linux iproute2 +@tab @code{ip route add} @var{network_address}@code{/}@var{prefixlength} @code{dev} @var{interface} +@item FreeBSD +@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @var{local_address} +@item OpenBSD +@tab @code{route add -inet6} @var{network_address} @var{local_address} @code{-prefixlen} @var{prefixlength} +@item NetBSD +@tab @code{route add -inet6} @var{network_address} @var{local_address} @code{-prefixlen} @var{prefixlength} +@item Solaris +@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} +@item Darwin (Mac OS X) +@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @code{-interface} @var{interface} +@item Windows +@tab @code{netsh interface ipv6 add route} @var{network address}/@var{prefixlength} @var{interface} +@end multitable + +@c ================================================================== +@node Automatically starting tinc +@section Automatically starting tinc + +@menu +* Linux:: +* Windows:: +* Other platforms:: +@end menu + +@c ================================================================== +@node Linux +@subsection Linux + +@cindex systemd +There are many Linux distributions, and historically, many of them had their +own way of starting programs at boot time. Today, a number of major Linux +distributions have chosen to use systemd as their init system. Tinc ships with +systemd service files that allow you to start and stop tinc using systemd. +There are two service files: @code{tinc.service} is used to globally enable or +disable all tinc daemons managed by systemd, and +@code{tinc@@@var{netname}.service} is used to enable or disable specific tinc +daemons. So if one has created a tinc network with netname @code{foo}, then +you have to run the following two commands to ensure it is started at boot +time: + +@example +systemctl enable tinc +systemctl enable tinc@@foo +@end example + +To start the tinc daemon immediately if it wasn't already running, use the +following command: + +@example +systemctl start tinc@@foo +@end example + +You can also use @samp{systemctl start tinc}, this will start all tinc daemons +that are enabled. You can stop and disable tinc networks in the same way. + +If your system is not using systemd, then you have to look up your +distribution's way of starting tinc at boot time. + +@c ================================================================== +@node Windows +@subsection Windows + +On Windows, if tinc is started without the @code{-D} or @code{--no-detach} +option, it will automatically register itself as a service that is started at +boot time. When tinc is stopped using the @code{-k} or @code{--kill}, it will +also automatically unregister itself. Once tinc is registered as a service, it +is also possible to stop and start tinc using the Windows Services Manager. + +@c ================================================================== +@node Other platforms +@subsection Other platforms + +On platforms other than the ones mentioned in the earlier sections, you have to +look up your platform's way of starting programs at boot time. + +@c ================================================================== +@node About us @chapter About us @menu -* Contact Information:: +* Contact information:: * Authors:: @end menu @c ================================================================== -@node Contact Information, Authors, About us, About us +@node Contact information @section Contact information @cindex website -tinc's website is at @url{http://tinc.nl.linux.org/}, +Tinc's website is at @url{https://www.tinc-vpn.org/}, this server is located in the Netherlands. @cindex IRC -We have an IRC channel on the Open Projects IRC network. Connect to -@uref{http://openprojects.nu/services/irc.html, irc.openprojects.net}, +We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to +@uref{https://freenode.net/, irc.freenode.net} +or +@uref{https://www.oftc.net/, irc.oftc.net} and join channel #tinc. @c ================================================================== -@node Authors, , Contact Information, About us +@node Authors @section Authors @table @asis -@item Ivo Timmermans (zarq) (@email{itimmermans@@bigfoot.com}) -Main coder/hacker and maintainer of the package. - -@item Guus Sliepen (guus) (@email{guus@@sliepen.warande.net}) -Originator of it all, co-author. - -@item Wessel Dankers (Ubiq) (@email{wsl@@nl.linux.org}) -For the name `tinc' and various suggestions. - +@item Ivo Timmermans (zarq) +@item Guus Sliepen (guus) (@email{guus@@tinc-vpn.org}) @end table We have received a lot of valuable input from users. With their help, @@ -1880,8 +2667,7 @@ the source distribution. @c ================================================================== -@node Concept Index, , About us, Top -@c node-name, next, previous, up +@node Concept Index @unnumbered Concept Index @c ================================================================== diff --git a/doc/tincd.8 b/doc/tincd.8.in similarity index 55% rename from doc/tincd.8 rename to doc/tincd.8.in index 831bbb1..bdccf9d 100644 --- a/doc/tincd.8 +++ b/doc/tincd.8.in @@ -1,22 +1,28 @@ -.Dd 2002-03-25 +.Dd 2014-05-11 .Dt TINCD 8 .\" Manual page created by: -.\" Ivo Timmermans -.\" Guus Sliepen +.\" Ivo Timmermans +.\" Guus Sliepen .Sh NAME .Nm tincd .Nd tinc VPN daemon .Sh SYNOPSIS .Nm -.Op Fl cdDkKn -.Op Fl -bypass-security +.Op Fl cdDkKnoLRU .Op Fl -config Ns = Ns Ar DIR -.Op Fl -debug Ns = Ns Ar LEVEL -.Op Fl -generate-keys Ns Op = Ns Ar BITS -.Op Fl -help -.Op Fl -kill Ns = Ns Ar SIGNAL -.Op Fl -net Ns = Ns Ar NETNAME .Op Fl -no-detach +.Op Fl -debug Ns Op = Ns Ar LEVEL +.Op Fl -kill Ns Op = Ns Ar SIGNAL +.Op Fl -net Ns = Ns Ar NETNAME +.Op Fl -generate-keys Ns Op = Ns Ar BITS +.Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE +.Op Fl -mlock +.Op Fl -logfile Ns Op = Ns Ar FILE +.Op Fl -pidfile Ns = Ns Ar FILE +.Op Fl -bypass-security +.Op Fl -chroot +.Op Fl -user Ns = Ns Ar USER +.Op Fl -help .Op Fl -version .Sh DESCRIPTION This is the daemon of tinc, a secure virtual private network (VPN) project. @@ -31,37 +37,93 @@ If that succeeds, it will detach from the controlling terminal and continue in the background, accepting and setting up connections to other tinc daemons that are part of the virtual private network. +Under Windows (not Cygwin) tinc will install itself as a service, +which will be restarted automatically after reboots. .Sh OPTIONS .Bl -tag -width indent -.It Fl -bypass-security -Disables encryption and authentication. -Only useful for debugging. .It Fl c, -config Ns = Ns Ar DIR -Read configuration options from -.Ar DIR . +Read configuration files from +.Ar DIR +instead of +.Pa @sysconfdir@/tinc/ . +.It Fl D, -no-detach +Don't fork and detach. +This will also disable the automatic restart mechanism for fatal errors. +If not mentioned otherwise, this will show log messages on the standard error output. .It Fl d, -debug Ns Op = Ns Ar LEVEL Increase debug level or set it to .Ar LEVEL (see below). -.It Fl K, -generate-keys Ns Op = Ns Ar BITS -Generate public/private RSA keypair and exit. -If -.Ar BITS -is omitted, the default length will be 1024 bits. -.It Fl -help -Display short list of options. .It Fl k, -kill Ns Op = Ns Ar SIGNAL Attempt to kill a running .Nm (optionally with the specified .Ar SIGNAL instead of SIGTERM) and exit. +Under Windows (not Cygwin) the optional argument is ignored, +the service will always be stopped and removed. .It Fl n, -net Ns = Ns Ar NETNAME Connect to net .Ar NETNAME . -.It Fl D, -no-detach -Don't fork and detach. -This will also disable the automatic restart mechanism for fatal errors. +This will let tinc read all configuration files from +.Pa @sysconfdir@/tinc/ Ar NETNAME . +Specifying +.Li . +for +.Ar NETNAME +is the same as not specifying any +.Ar NETNAME . +.It Fl K, -generate-keys Ns Op = Ns Ar BITS +Generate public/private RSA keypair and exit. +If +.Ar BITS +is omitted, the default length will be 2048 bits. +When saving keys to existing files, tinc will not delete the old keys, +you have to remove them manually. +.It Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE +Without specifying a +.Ar HOST , +this will set server configuration variable +.Ar KEY +to +.Ar VALUE . +If specified as +.Ar HOST.KEY=VALUE , +this will set the host configuration variable +.Ar KEY +of the host named +.Ar HOST +to +.Ar VALUE . +This option can be used more than once to specify multiple configuration variables. +.It Fl L, -mlock +Lock tinc into main memory. +This will prevent sensitive data like shared private keys to be written to the system swap files/partitions. +.It Fl -logfile Ns Op = Ns Ar FILE +Write log entries to a file instead of to the system logging facility. +If +.Ar FILE +is omitted, the default is +.Pa @localstatedir@/log/tinc. Ns Ar NETNAME Ns Pa .log. +.It Fl -pidfile Ns = Ns Ar FILE +Write PID to +.Ar FILE +instead of +.Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid. +Under Windows this option will be ignored. +.It Fl -bypass-security +Disables encryption and authentication of the meta protocol. +Only useful for debugging. +.It Fl R, -chroot +With this option tinc chroots into the directory where network +config is located (@sysconfdir@/tinc/NETNAME if -n option is used, +or to the directory specified with -c option) after initialization. +.It Fl U, -user Ns = Ns Ar USER +setuid to the specified +.Ar USER +after initialization. +.It Fl -help +Display short list of options. .It Fl -version Output version information and exit. .El @@ -80,7 +142,15 @@ and if didn't succeed to connect to an uplink the first time after it started, it defaults to the maximum time of 15 minutes. .It HUP -Closes all connections, rereads the configuration file and restarts the daemon. +Partially rereads configuration files. +Connections to hosts whose host config file are removed are closed. +New outgoing connections specified in +.Pa tinc.conf +will be made. +If the +.Fl -logfile +option is used, this will also close and reopen the log file, +useful when log rotation is used. .It INT Temporarily increases debug level to 5. Send this signal again to revert to the original level. @@ -101,11 +171,11 @@ Each level inherits all messages of the previous level: This will log a message indicating .Nm has started along with a version number. -It will also any serious error. +It will also log any serious error. .It 1 This will log all connections that are made with other tinc daemons. .It 2 -This will log status and error messages from other tinc daemons. +This will log status and error messages from scripts and other tinc daemons. .It 3 This will log all requests that are exchanged with other tinc daemons. These include authentication, key exchange and connection list updates. @@ -116,29 +186,11 @@ This will log all network traffic over the virtual private network. .El .Sh FILES .Bl -tag -width indent -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf -The configuration file for -.Nm . -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-up -Script which is executed as soon as the virtual network device has been allocated. -Purpose is to further configure that device. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-down -Script which is executed when -.Nm -exits. -Purpose is to cleanly shut down the virtual network device before it will be deallocated. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/* -The directory containing the host configuration files -used to authenticate other tinc daemons. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar NAME Ns Pa -up -Script which is executed as soon as host -.Ar NAME -becomes reachable. -.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar NAME Ns Pa -down -Script which is executed as soon as host -.Ar NAME -becomes unreachable. -.It Pa /var/run/tinc. Ns Ar NETNAME Ns Pa .pid +.It Pa @sysconfdir@/tinc/ +Directory containing the configuration files tinc uses. +For more information, see +.Xr tinc.conf 5 . +.It Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid The PID of the currently running .Nm is stored in this file. @@ -150,12 +202,12 @@ option may not work correctly. .Pp .Sy The cryptography in tinc is not well tested yet. Use it at your own risk! .Pp -If you find any bugs, report them to tinc@nl.linux.org. +If you find any bugs, report them to tinc@tinc-vpn.org. .Sh TODO A lot, especially security auditing. .Sh SEE ALSO .Xr tinc.conf 5 , -.Pa http://tinc.nl.linux.org/ , +.Pa https://www.tinc-vpn.org/ , .Pa http://www.cabal.org/ . .Pp The full documentation for tinc is maintained as a Texinfo manual. @@ -168,7 +220,7 @@ tinc comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details. .Sh AUTHORS -.An "Ivo Timmermans" Aq itimmermans@bigfoot.com -.An "Guus Sliepen" Aq guus@sliepen.warande.net +.An "Ivo Timmermans" +.An "Guus Sliepen" Aq guus@tinc-vpn.org .Pp And thanks to many others for their contributions to tinc! diff --git a/doc/tincinclude.texi b/doc/tincinclude.texi new file mode 100644 index 0000000..ab2a41a --- /dev/null +++ b/doc/tincinclude.texi @@ -0,0 +1,5 @@ +@set VERSION 1.0.36 +@set PACKAGE tinc +@set sysconfdir /etc +@set localstatedir /var +@set runstatedir /run diff --git a/doc/tincinclude.texi.in b/doc/tincinclude.texi.in new file mode 100644 index 0000000..01fee35 --- /dev/null +++ b/doc/tincinclude.texi.in @@ -0,0 +1,5 @@ +@set VERSION @VERSION@ +@set PACKAGE @PACKAGE@ +@set sysconfdir @sysconfdir@ +@set localstatedir @localstatedir@ +@set runstatedir @runstatedir@ diff --git a/install-sh b/install-sh index e9de238..20d8b2e 100755 --- a/install-sh +++ b/install-sh @@ -1,251 +1,529 @@ #!/bin/sh -# # install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). + +scriptversion=2018-03-11.20; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. # -# Copyright 1991 by the Massachusetts Institute of Technology +# Copyright (C) 1994 X Consortium # -# 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. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it +# '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. +# from scratch. - -# 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=' +tab=' ' +nl=' ' -IFS="${IFS-${defaultIFS}}" +IFS=" $tab$nl" -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" +# Set DOITPROG to "echo" to test this script. -pathcomp='' +doit=${DOITPROG-} +doit_exec=${doit:-exec} -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift +# Put in absolute file names if you don't have them in your path; +# or use environment vars. - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} - pathcomp="${pathcomp}/" +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi fi -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi - 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 test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi -# If we're going to rename the final executable, determine the name now. +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 -# don't allow the sed command to completely eliminate the filename + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi -# Make a temp file name in the proper directory. +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac - dsttmp=$dstdir/#inst.$$# + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else -# Move or copy the file name to the temp name + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi - $doit $instcmd $src $dsttmp && + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg - trap "rm -f ${dsttmp}" 0 && + # If destination is a directory, append the input filename. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi -# and set any options; do chmod last to preserve setuid bits + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac -# 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. + obsolete_mkdir_used=false - 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 && + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; -# Now rename the file to the real destination. + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi -fi && + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 -exit 0 + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && + + # 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 $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/intl/ChangeLog b/intl/ChangeLog deleted file mode 100644 index 84e2b37..0000000 --- a/intl/ChangeLog +++ /dev/null @@ -1,4 +0,0 @@ -2001-09-13 GNU - - * Version 0.10.40 released. - diff --git a/intl/Makefile.in b/intl/Makefile.in deleted file mode 100644 index 19ed4a7..0000000 --- a/intl/Makefile.in +++ /dev/null @@ -1,313 +0,0 @@ -# Makefile for directory with message catalog handling in GNU NLS Utilities. -# Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. - -PACKAGE = @PACKAGE@ -VERSION = @VERSION@ - -SHELL = /bin/sh - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = .. -VPATH = @srcdir@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -transform = @program_transform_name@ -libdir = @libdir@ -includedir = @includedir@ -datadir = @datadir@ -localedir = $(datadir)/locale -gettextsrcdir = $(datadir)/gettext/intl -aliaspath = $(localedir) -subdir = intl - -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` - -l = @INTL_LIBTOOL_SUFFIX_PREFIX@ - -AR = ar -CC = @CC@ -LIBTOOL = @LIBTOOL@ -RANLIB = @RANLIB@ -YACC = @INTLBISON@ -y -d -YFLAGS = --name-prefix=__gettext - -DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ --DLIBDIR=\"$(libdir)\" @DEFS@ -CPPFLAGS = @CPPFLAGS@ -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ - -COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) - -HEADERS = $(COMHDRS) libgnuintl.h libgettext.h loadinfo.h -COMHDRS = gettext.h gettextP.h hash-string.h -SOURCES = $(COMSRCS) intl-compat.c -COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \ -finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \ -explodename.c dcigettext.c dcngettext.c dngettext.c ngettext.c plural.y \ -localcharset.c -OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \ -finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \ -explodename.$lo dcigettext.$lo dcngettext.$lo dngettext.$lo ngettext.$lo \ -plural.$lo localcharset.$lo -GETTOBJS = intl-compat.$lo -DISTFILES.common = Makefile.in \ -config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) -DISTFILES.generated = plural.c -DISTFILES.normal = VERSION -DISTFILES.gettext = COPYING.LIB-2 COPYING.LIB-2.1 libintl.glibc -DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c - -# Libtool's library version information for libintl. -# Before making a gettext release, the gettext maintainer must change this -# according to the libtool documentation, section "Library interface versions". -# Maintainers of other packages that include the intl directory must *not* -# change these values. -LTV_CURRENT=1 -LTV_REVISION=1 -LTV_AGE=0 - -.SUFFIXES: -.SUFFIXES: .c .y .o .lo .sin .sed -.c.o: - $(COMPILE) $< -.c.lo: - $(LIBTOOL) --mode=compile $(COMPILE) $< - -.y.c: - $(YACC) $(YFLAGS) --output $@ $< - rm -f $*.h - -.sin.sed: - sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@ - mv t-$@ $@ - -INCLUDES = -I.. -I. -I$(top_srcdir)/intl - -all: all-@USE_INCLUDED_LIBINTL@ -all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed -all-no: all-no-@BUILD_INCLUDED_LIBINTL@ -all-no-yes: libgnuintl.$la -all-no-no: - -libintl.a libgnuintl.a: $(OBJECTS) - rm -f $@ - $(AR) cru $@ $(OBJECTS) - $(RANLIB) $@ - -libintl.la libgnuintl.la: $(OBJECTS) - $(LIBTOOL) --mode=link \ - $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ - $(OBJECTS) @LIBICONV@ \ - -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ - -rpath $(libdir) \ - -no-undefined - -libintl.h: libgnuintl.h - cp $(srcdir)/libgnuintl.h libintl.h - -charset.alias: config.charset - $(SHELL) $(srcdir)/config.charset '@host@' > t-$@ - mv t-$@ $@ - -check: all - -# This installation goal is only used in GNU gettext. Packages which -# only use the library should use install instead. - -# We must not install the libintl.h/libintl.a files if we are on a -# system which has the GNU gettext() function in its C library or in a -# separate library. -# If you want to use the one which comes with this version of the -# package, you have to use `configure --with-included-gettext'. -install: install-exec install-data -install-exec: all - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ - $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=install \ - $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir); \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - orig=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - if test @GLIBC21@ = no; then \ - orig=charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - fi; \ - fi; \ - $(mkinstalldirs) $(DESTDIR)$(localedir); \ - test -f $(DESTDIR)$(localedir)/locale.alias \ - && orig=$(DESTDIR)$(localedir)/locale.alias \ - || orig=$(srcdir)/locale.alias; \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - : ; \ - fi -install-data: all - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \ - $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \ - dists="COPYING.LIB-2 COPYING.LIB-2.1 $(DISTFILES.common)"; \ - for file in $$dists; do \ - $(INSTALL_DATA) $(srcdir)/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \ - dists="$(DISTFILES.generated)"; \ - for file in $$dists; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - $(INSTALL_DATA) $$dir/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - dists="$(DISTFILES.obsolete)"; \ - for file in $$dists; do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -# Define this as empty until I found a useful application. -installcheck: - -uninstall: - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - rm -f $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=uninstall \ - rm -f $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - if test -f $(DESTDIR)$(localedir)/locale.alias; then \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - else \ - : ; \ - fi - if test "$(PACKAGE)" = "gettext"; then \ - for file in VERSION ChangeLog COPYING.LIB-2 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -info dvi: - -$(OBJECTS): ../config.h libgnuintl.h -bindtextdom.$lo finddomain.$lo loadmsgcat.$lo: gettextP.h gettext.h loadinfo.h -dcgettext.$lo: gettextP.h gettext.h hash-string.h loadinfo.h - -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) - -id: ID - -ID: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) - - -mostlyclean: - rm -f *.a *.la *.o *.lo core core.* - rm -f libintl.h charset.alias ref-add.sed ref-del.sed - rm -f -r .libs _libs - -clean: mostlyclean - -distclean: clean - rm -f Makefile ID TAGS - if test "$(PACKAGE)" = gettext; then \ - rm -f ChangeLog.inst $(DISTFILES.normal); \ - else \ - : ; \ - fi - -maintainer-clean: distclean - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - - -# GNU gettext needs not contain the file `VERSION' but contains some -# other files which should not be distributed in other packages. -distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) -dist distdir: Makefile - if test "$(PACKAGE)" = gettext; then \ - additional="$(DISTFILES.gettext)"; \ - else \ - additional="$(DISTFILES.normal)"; \ - fi; \ - $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ - for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - ln $$dir/$$file $(distdir) 2> /dev/null \ - || cp -p $$dir/$$file $(distdir); \ - done - -Makefile: Makefile.in ../config.status - cd .. \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -# Tell versions [3.59,3.63) of GNU make not to export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/intl/VERSION b/intl/VERSION deleted file mode 100644 index cb8a01a..0000000 --- a/intl/VERSION +++ /dev/null @@ -1 +0,0 @@ -GNU gettext library from gettext-0.10.40 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c deleted file mode 100644 index c6a9bd1..0000000 --- a/intl/bindtextdom.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Implementation of the bindtextdomain(3) function - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_dirname _nl_default_dirname__ -# define _nl_domain_bindings _nl_domain_bindings__ -#endif - -/* Some compilers, like SunOS4 cc, don't have offsetof in . */ -#ifndef offsetof -# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) -#endif - -/* @@ end of prolog @@ */ - -/* Contains the default location of the message catalogs. */ -extern const char _nl_default_dirname[]; - -/* List with bindings of specific domains. */ -extern struct binding *_nl_domain_bindings; - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock) - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define BINDTEXTDOMAIN __bindtextdomain -# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define BINDTEXTDOMAIN bindtextdomain__ -# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__ -#endif - -/* Prototypes for local functions. */ -static void set_binding_values PARAMS ((const char *domainname, - const char **dirnamep, - const char **codesetp)); - -/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP - to be used for the DOMAINNAME message catalog. - If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not - modified, only the current value is returned. - If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither - modified nor returned. */ -static void -set_binding_values (domainname, dirnamep, codesetp) - const char *domainname; - const char **dirnamep; - const char **codesetp; -{ - struct binding *binding; - int modified; - - /* Some sanity checks. */ - if (domainname == NULL || domainname[0] == '\0') - { - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - return; - } - - __libc_rwlock_wrlock (_nl_state_lock); - - modified = 0; - - for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) - { - int compare = strcmp (domainname, binding->domainname); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It is not in the list. */ - binding = NULL; - break; - } - } - - if (binding != NULL) - { - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The current binding has be to returned. */ - *dirnamep = binding->dirname; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->dirname; - if (strcmp (dirname, result) != 0) - { - if (strcmp (dirname, _nl_default_dirname) == 0) - result = (char *) _nl_default_dirname; - else - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, dirname, len); -#endif - } - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->dirname != _nl_default_dirname) - free (binding->dirname); - - binding->dirname = result; - modified = 1; - } - } - *dirnamep = result; - } - } - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset == NULL) - /* The current binding has be to returned. */ - *codesetp = binding->codeset; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->codeset; - if (result == NULL || strcmp (codeset, result) != 0) - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, codeset, len); -#endif - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->codeset != NULL) - free (binding->codeset); - - binding->codeset = result; - binding->codeset_cntr++; - modified = 1; - } - } - *codesetp = result; - } - } - } - else if ((dirnamep == NULL || *dirnamep == NULL) - && (codesetp == NULL || *codesetp == NULL)) - { - /* Simply return the default values. */ - if (dirnamep) - *dirnamep = _nl_default_dirname; - if (codesetp) - *codesetp = NULL; - } - else - { - /* We have to create a new binding. */ - size_t len = strlen (domainname) + 1; - struct binding *new_binding = - (struct binding *) malloc (offsetof (struct binding, domainname) + len); - - if (__builtin_expect (new_binding == NULL, 0)) - goto failed; - - memcpy (new_binding->domainname, domainname, len); - - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The default value. */ - dirname = _nl_default_dirname; - else - { - if (strcmp (dirname, _nl_default_dirname) == 0) - dirname = _nl_default_dirname; - else - { - char *result; -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; - memcpy (result, dirname, len); -#endif - dirname = result; - } - } - *dirnamep = dirname; - new_binding->dirname = (char *) dirname; - } - else - /* The default value. */ - new_binding->dirname = (char *) _nl_default_dirname; - - new_binding->codeset_cntr = 0; - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset != NULL) - { - char *result; - -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; - memcpy (result, codeset, len); -#endif - codeset = result; - new_binding->codeset_cntr++; - } - *codesetp = codeset; - new_binding->codeset = (char *) codeset; - } - else - new_binding->codeset = NULL; - - /* Now enqueue it. */ - if (_nl_domain_bindings == NULL - || strcmp (domainname, _nl_domain_bindings->domainname) < 0) - { - new_binding->next = _nl_domain_bindings; - _nl_domain_bindings = new_binding; - } - else - { - binding = _nl_domain_bindings; - while (binding->next != NULL - && strcmp (domainname, binding->next->domainname) > 0) - binding = binding->next; - - new_binding->next = binding->next; - binding->next = new_binding; - } - - modified = 1; - - /* Here we deal with memory allocation failures. */ - if (0) - { - failed_codeset: - if (new_binding->dirname != _nl_default_dirname) - free (new_binding->dirname); - failed_dirname: - free (new_binding); - failed: - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - } - } - - /* If we modified any binding, we flush the caches. */ - if (modified) - ++_nl_msg_cat_cntr; - - __libc_rwlock_unlock (_nl_state_lock); -} - -/* Specify that the DOMAINNAME message catalog will be found - in DIRNAME rather than in the system locale data base. */ -char * -BINDTEXTDOMAIN (domainname, dirname) - const char *domainname; - const char *dirname; -{ - set_binding_values (domainname, &dirname, NULL); - return (char *) dirname; -} - -/* Specify the character encoding in which the messages from the - DOMAINNAME message catalog will be returned. */ -char * -BIND_TEXTDOMAIN_CODESET (domainname, codeset) - const char *domainname; - const char *codeset; -{ - set_binding_values (domainname, NULL, &codeset); - return (char *) codeset; -} - -#ifdef _LIBC -/* Aliases for function names in GNU C Library. */ -weak_alias (__bindtextdomain, bindtextdomain); -weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); -#endif diff --git a/intl/config.charset b/intl/config.charset deleted file mode 100755 index f4f2611..0000000 --- a/intl/config.charset +++ /dev/null @@ -1,438 +0,0 @@ -#! /bin/sh -# Output a system dependent table of character encoding aliases. -# -# Copyright (C) 2000-2001 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. -# -# The table consists of lines of the form -# ALIAS CANONICAL -# -# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". -# ALIAS is compared in a case sensitive way. -# -# CANONICAL is the GNU canonical name for this character encoding. -# It must be an encoding supported by libiconv. Support by GNU libc is -# also desirable. CANONICAL is case insensitive. Usually an upper case -# MIME charset name is preferred. -# The current list of GNU canonical charset names is as follows. -# -# name used by which systems a MIME name? -# ASCII, ANSI_X3.4-1968 glibc solaris freebsd -# ISO-8859-1 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-2 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-3 glibc yes -# ISO-8859-4 osf solaris freebsd yes -# ISO-8859-5 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-6 glibc aix hpux solaris yes -# ISO-8859-7 glibc aix hpux irix osf solaris yes -# ISO-8859-8 glibc aix hpux osf solaris yes -# ISO-8859-9 glibc aix hpux irix osf solaris yes -# ISO-8859-13 glibc -# ISO-8859-15 glibc aix osf solaris freebsd -# KOI8-R glibc solaris freebsd yes -# KOI8-U glibc freebsd yes -# CP437 dos -# CP775 dos -# CP850 aix osf dos -# CP852 dos -# CP855 dos -# CP856 aix -# CP857 dos -# CP861 dos -# CP862 dos -# CP864 dos -# CP865 dos -# CP866 freebsd dos -# CP869 dos -# CP874 win32 dos -# CP922 aix -# CP932 aix win32 dos -# CP943 aix -# CP949 osf win32 dos -# CP950 win32 dos -# CP1046 aix -# CP1124 aix -# CP1129 aix -# CP1250 win32 -# CP1251 glibc win32 -# CP1252 aix win32 -# CP1253 win32 -# CP1254 win32 -# CP1255 win32 -# CP1256 win32 -# CP1257 win32 -# GB2312 glibc aix hpux irix solaris freebsd yes -# EUC-JP glibc aix hpux irix osf solaris freebsd yes -# EUC-KR glibc aix hpux irix osf solaris freebsd yes -# EUC-TW glibc aix hpux irix osf solaris -# BIG5 glibc aix hpux osf solaris freebsd yes -# BIG5-HKSCS glibc -# GBK aix osf win32 dos -# GB18030 glibc -# SHIFT_JIS hpux osf solaris freebsd yes -# JOHAB glibc win32 -# TIS-620 glibc aix hpux osf solaris -# VISCII glibc yes -# HP-ROMAN8 hpux -# HP-ARABIC8 hpux -# HP-GREEK8 hpux -# HP-HEBREW8 hpux -# HP-TURKISH8 hpux -# HP-KANA8 hpux -# DEC-KANJI osf -# DEC-HANYU osf -# UTF-8 glibc aix hpux osf solaris yes -# -# Note: Names which are not marked as being a MIME name should not be used in -# Internet protocols for information interchange (mail, news, etc.). -# -# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications -# must understand both names and treat them as equivalent. -# -# The first argument passed to this file is the canonical host specification, -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM - -host="$1" -os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` -echo "# This file contains a table of character encoding aliases," -echo "# suitable for operating system '${os}'." -echo "# It was automatically generated from config.charset." -# List of references, updated during installation: -echo "# Packages using this file: " -case "$os" in - linux* | *-gnu*) - # With glibc-2.1 or newer, we don't need any canonicalization, - # because glibc has iconv and both glibc and libiconv support all - # GNU canonical names directly. Therefore, the Makefile does not - # need to install the alias file at all. - # The following applies only to glibc-2.0.x and older libcs. - echo "ISO_646.IRV:1983 ASCII" - ;; - aix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "IBM-850 CP850" - echo "IBM-856 CP856" - echo "IBM-921 ISO-8859-13" - echo "IBM-922 CP922" - echo "IBM-932 CP932" - echo "IBM-943 CP943" - echo "IBM-1046 CP1046" - echo "IBM-1124 CP1124" - echo "IBM-1129 CP1129" - echo "IBM-1252 CP1252" - echo "IBM-eucCN GB2312" - echo "IBM-eucJP EUC-JP" - echo "IBM-eucKR EUC-KR" - echo "IBM-eucTW EUC-TW" - echo "big5 BIG5" - echo "GBK GBK" - echo "TIS-620 TIS-620" - echo "UTF-8 UTF-8" - ;; - hpux*) - echo "iso88591 ISO-8859-1" - echo "iso88592 ISO-8859-2" - echo "iso88595 ISO-8859-5" - echo "iso88596 ISO-8859-6" - echo "iso88597 ISO-8859-7" - echo "iso88598 ISO-8859-8" - echo "iso88599 ISO-8859-9" - echo "iso885915 ISO-8859-15" - echo "roman8 HP-ROMAN8" - echo "arabic8 HP-ARABIC8" - echo "greek8 HP-GREEK8" - echo "hebrew8 HP-HEBREW8" - echo "turkish8 HP-TURKISH8" - echo "kana8 HP-KANA8" - echo "tis620 TIS-620" - echo "big5 BIG5" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "hp15CN GB2312" - #echo "ccdc ?" # what is this? - echo "SJIS SHIFT_JIS" - echo "utf8 UTF-8" - ;; - irix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-9 ISO-8859-9" - echo "eucCN GB2312" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - ;; - osf*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "cp850 CP850" - echo "big5 BIG5" - echo "dechanyu DEC-HANYU" - echo "dechanzi GB2312" - echo "deckanji DEC-KANJI" - echo "deckorean EUC-KR" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "GBK GBK" - echo "KSC5601 CP949" - echo "sdeckanji EUC-JP" - echo "SJIS SHIFT_JIS" - echo "TACTIS TIS-620" - echo "UTF-8 UTF-8" - ;; - solaris*) - echo "646 ASCII" - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "koi8-r KOI8-R" - echo "BIG5 BIG5" - echo "gb2312 GB2312" - echo "cns11643 EUC-TW" - echo "5601 EUC-KR" - echo "eucJP EUC-JP" - echo "PCK SHIFT_JIS" - echo "TIS620.2533 TIS-620" - #echo "sun_eu_greek ?" # what is this? - echo "UTF-8 UTF-8" - ;; - freebsd*) - # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "C ASCII" - echo "US-ASCII ASCII" - for l in la_LN lt_LN; do - echo "$l.ASCII ASCII" - done - for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ - fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ - lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do - echo "$l.ISO_8859-1 ISO-8859-1" - echo "$l.DIS_8859-15 ISO-8859-15" - done - for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do - echo "$l.ISO_8859-2 ISO-8859-2" - done - for l in la_LN lt_LT; do - echo "$l.ISO_8859-4 ISO-8859-4" - done - for l in ru_RU ru_SU; do - echo "$l.KOI8-R KOI8-R" - echo "$l.ISO_8859-5 ISO-8859-5" - echo "$l.CP866 CP866" - done - echo "uk_UA.KOI8-U KOI8-U" - echo "zh_TW.BIG5 BIG5" - echo "zh_TW.Big5 BIG5" - echo "zh_CN.EUC GB2312" - echo "ja_JP.EUC EUC-JP" - echo "ja_JP.SJIS SHIFT_JIS" - echo "ja_JP.Shift_JIS SHIFT_JIS" - echo "ko_KR.EUC EUC-KR" - ;; - beos*) - # BeOS has a single locale, and it has UTF-8 encoding. - echo "* UTF-8" - ;; - msdosdjgpp*) - # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "#" - echo "# The encodings given here may not all be correct." - echo "# If you find that the encoding given for your language and" - echo "# country is not the one your DOS machine actually uses, just" - echo "# correct it in this file, and send a mail to" - echo "# Juan Manuel Guerrero " - echo "# and Bruno Haible ." - echo "#" - echo "C ASCII" - # ISO-8859-1 languages - echo "ca CP850" - echo "ca_ES CP850" - echo "da CP865" # not CP850 ?? - echo "da_DK CP865" # not CP850 ?? - echo "de CP850" - echo "de_AT CP850" - echo "de_CH CP850" - echo "de_DE CP850" - echo "en CP850" - echo "en_AU CP850" # not CP437 ?? - echo "en_CA CP850" - echo "en_GB CP850" - echo "en_NZ CP437" - echo "en_US CP437" - echo "en_ZA CP850" # not CP437 ?? - echo "es CP850" - echo "es_AR CP850" - echo "es_BO CP850" - echo "es_CL CP850" - echo "es_CO CP850" - echo "es_CR CP850" - echo "es_CU CP850" - echo "es_DO CP850" - echo "es_EC CP850" - echo "es_ES CP850" - echo "es_GT CP850" - echo "es_HN CP850" - echo "es_MX CP850" - echo "es_NI CP850" - echo "es_PA CP850" - echo "es_PY CP850" - echo "es_PE CP850" - echo "es_SV CP850" - echo "es_UY CP850" - echo "es_VE CP850" - echo "et CP850" - echo "et_EE CP850" - echo "eu CP850" - echo "eu_ES CP850" - echo "fi CP850" - echo "fi_FI CP850" - echo "fr CP850" - echo "fr_BE CP850" - echo "fr_CA CP850" - echo "fr_CH CP850" - echo "fr_FR CP850" - echo "ga CP850" - echo "ga_IE CP850" - echo "gd CP850" - echo "gd_GB CP850" - echo "gl CP850" - echo "gl_ES CP850" - echo "id CP850" # not CP437 ?? - echo "id_ID CP850" # not CP437 ?? - echo "is CP861" # not CP850 ?? - echo "is_IS CP861" # not CP850 ?? - echo "it CP850" - echo "it_CH CP850" - echo "it_IT CP850" - echo "lt CP775" - echo "lt_LT CP775" - echo "lv CP775" - echo "lv_LV CP775" - echo "nb CP865" # not CP850 ?? - echo "nb_NO CP865" # not CP850 ?? - echo "nl CP850" - echo "nl_BE CP850" - echo "nl_NL CP850" - echo "nn CP865" # not CP850 ?? - echo "nn_NO CP865" # not CP850 ?? - echo "no CP865" # not CP850 ?? - echo "no_NO CP865" # not CP850 ?? - echo "pt CP850" - echo "pt_BR CP850" - echo "pt_PT CP850" - echo "sv CP850" - echo "sv_SE CP850" - # ISO-8859-2 languages - echo "cs CP852" - echo "cs_CZ CP852" - echo "hr CP852" - echo "hr_HR CP852" - echo "hu CP852" - echo "hu_HU CP852" - echo "pl CP852" - echo "pl_PL CP852" - echo "ro CP852" - echo "ro_RO CP852" - echo "sk CP852" - echo "sk_SK CP852" - echo "sl CP852" - echo "sl_SI CP852" - echo "sq CP852" - echo "sq_AL CP852" - echo "sr CP852" # CP852 or CP866 or CP855 ?? - echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? - # ISO-8859-3 languages - echo "mt CP850" - echo "mt_MT CP850" - # ISO-8859-5 languages - echo "be CP866" - echo "be_BE CP866" - echo "bg CP866" # not CP855 ?? - echo "bg_BG CP866" # not CP855 ?? - echo "mk CP866" # not CP855 ?? - echo "mk_MK CP866" # not CP855 ?? - echo "ru KOI8-R" # not CP866 ?? - echo "ru_RU KOI8-R" # not CP866 ?? - # ISO-8859-6 languages - echo "ar CP864" - echo "ar_AE CP864" - echo "ar_DZ CP864" - echo "ar_EG CP864" - echo "ar_IQ CP864" - echo "ar_IR CP864" - echo "ar_JO CP864" - echo "ar_KW CP864" - echo "ar_MA CP864" - echo "ar_OM CP864" - echo "ar_QA CP864" - echo "ar_SA CP864" - echo "ar_SY CP864" - # ISO-8859-7 languages - echo "el CP869" - echo "el_GR CP869" - # ISO-8859-8 languages - echo "he CP862" - echo "he_IL CP862" - # ISO-8859-9 languages - echo "tr CP857" - echo "tr_TR CP857" - # Japanese - echo "ja CP932" - echo "ja_JP CP932" - # Chinese - echo "zh_CN GBK" - echo "zh_TW CP950" # not CP938 ?? - # Korean - echo "kr CP949" # not CP934 ?? - echo "kr_KR CP949" # not CP934 ?? - # Thai - echo "th CP874" - echo "th_TH CP874" - # Other - echo "eo CP850" - echo "eo_EO CP850" - ;; -esac diff --git a/intl/dcgettext.c b/intl/dcgettext.c deleted file mode 100644 index b7c9652..0000000 --- a/intl/dcgettext.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Implementation of the dcgettext(3) function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCGETTEXT __dcgettext -# define DCIGETTEXT __dcigettext -#else -# define DCGETTEXT dcgettext__ -# define DCIGETTEXT dcigettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -char * -DCGETTEXT (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dcgettext, dcgettext); -#endif diff --git a/intl/dcigettext.c b/intl/dcigettext.c deleted file mode 100644 index 6acde19..0000000 --- a/intl/dcigettext.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* Implementation of the internal dcigettext function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#ifndef errno -extern int errno; -#endif -#ifndef __set_errno -# define __set_errno(val) errno = (val) -#endif - -#include -#include - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#include - -#if defined HAVE_SYS_PARAM_H || defined _LIBC -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "hash-string.h" - -/* Thread safetyness. */ -#ifdef _LIBC -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_lock_define_initialized(CLASS, NAME) -# define __libc_lock_lock(NAME) -# define __libc_lock_unlock(NAME) -# define __libc_rwlock_define_initialized(CLASS, NAME) -# define __libc_rwlock_rdlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* Alignment of types. */ -#if defined __GNUC__ && __GNUC__ >= 2 -# define alignof(TYPE) __alignof__ (TYPE) -#else -# define alignof(TYPE) \ - ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_default_domain _nl_default_default_domain__ -# define _nl_current_default_domain _nl_current_default_domain__ -# define _nl_default_dirname _nl_default_dirname__ -# define _nl_domain_bindings _nl_domain_bindings__ -#endif - -/* Some compilers, like SunOS4 cc, don't have offsetof in . */ -#ifndef offsetof -# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# define getcwd __getcwd -# ifndef stpcpy -# define stpcpy __stpcpy -# endif -# define tfind __tfind -#else -# if !defined HAVE_GETCWD -char *getwd (); -# define getcwd(buf, max) getwd (buf) -# else -char *getcwd (); -# endif -# ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -# endif -# ifndef HAVE_MEMPCPY -static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); -# endif -#endif - -/* Amount to increase buffer size by in each try. */ -#define PATH_INCR 32 - -/* The following is from pathmax.h. */ -/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define - PATH_MAX but might cause redefinition warnings when sys/param.h is - later included (as on MORE/BSD 4.3). */ -#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) -# include -#endif - -#ifndef _POSIX_PATH_MAX -# define _POSIX_PATH_MAX 255 -#endif - -#if !defined PATH_MAX && defined _PC_PATH_MAX -# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) -#endif - -/* Don't include sys/param.h if it already has been. */ -#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN -# include -#endif - -#if !defined PATH_MAX && defined MAXPATHLEN -# define PATH_MAX MAXPATHLEN -#endif - -#ifndef PATH_MAX -# define PATH_MAX _POSIX_PATH_MAX -#endif - -/* Pathname support. - ISSLASH(C) tests whether C is a directory separator character. - IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, - it may be concatenated to a directory pathname. - IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. - */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -# define HAS_DEVICE(P) \ - ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ - && (P)[1] == ':') -# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) -# define IS_PATH_WITH_DIR(P) \ - (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) -#else - /* Unix */ -# define ISSLASH(C) ((C) == '/') -# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) -# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) -#endif - -/* XPG3 defines the result of `setlocale (category, NULL)' as: - ``Directs `setlocale()' to query `category' and return the current - setting of `local'.'' - However it does not specify the exact format. Neither do SUSV2 and - ISO C 99. So we can use this feature only on selected systems (e.g. - those using GNU C Library). */ -#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2) -# define HAVE_LOCALE_NULL -#endif - -/* This is the type used for the search tree where known translations - are stored. */ -struct known_translation_t -{ - /* Domain in which to search. */ - char *domainname; - - /* The category. */ - int category; - - /* State of the catalog counter at the point the string was found. */ - int counter; - - /* Catalog where the string was found. */ - struct loaded_l10nfile *domain; - - /* And finally the translation. */ - const char *translation; - size_t translation_length; - - /* Pointer to the string in question. */ - char msgid[ZERO]; -}; - -/* Root of the search tree with known translations. We can use this - only if the system provides the `tsearch' function family. */ -#if defined HAVE_TSEARCH || defined _LIBC -# include - -static void *root; - -# ifdef _LIBC -# define tsearch __tsearch -# endif - -/* Function to compare two entries in the table of known translations. */ -static int transcmp PARAMS ((const void *p1, const void *p2)); -static int -transcmp (p1, p2) - const void *p1; - const void *p2; -{ - const struct known_translation_t *s1; - const struct known_translation_t *s2; - int result; - - s1 = (const struct known_translation_t *) p1; - s2 = (const struct known_translation_t *) p2; - - result = strcmp (s1->msgid, s2->msgid); - if (result == 0) - { - result = strcmp (s1->domainname, s2->domainname); - if (result == 0) - /* We compare the category last (though this is the cheapest - operation) since it is hopefully always the same (namely - LC_MESSAGES). */ - result = s1->category - s2->category; - } - - return result; -} -#endif - -/* Name of the default domain used for gettext(3) prior any call to - textdomain(3). The default value for this is "messages". */ -const char _nl_default_default_domain[] = "messages"; - -/* Value used as the default domain for gettext(3). */ -const char *_nl_current_default_domain = _nl_default_default_domain; - -/* Contains the default location of the message catalogs. */ -const char _nl_default_dirname[] = LOCALEDIR; - -/* List with bindings of specific domains created by bindtextdomain() - calls. */ -struct binding *_nl_domain_bindings; - -/* Prototypes for local functions. */ -static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, - unsigned long int n, - const char *translation, - size_t translation_len)) - internal_function; -static unsigned long int plural_eval PARAMS ((struct expression *pexp, - unsigned long int n)) - internal_function; -static const char *category_to_name PARAMS ((int category)) internal_function; -static const char *guess_category_value PARAMS ((int category, - const char *categoryname)) - internal_function; - - -/* For those loosing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -/* Nothing has to be done. */ -# define ADD_BLOCK(list, address) /* nothing */ -# define FREE_BLOCKS(list) /* nothing */ -#else -struct block_list -{ - void *address; - struct block_list *next; -}; -# define ADD_BLOCK(list, addr) \ - do { \ - struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ - /* If we cannot get a free block we cannot add the new element to \ - the list. */ \ - if (newp != NULL) { \ - newp->address = (addr); \ - newp->next = (list); \ - (list) = newp; \ - } \ - } while (0) -# define FREE_BLOCKS(list) \ - do { \ - while (list != NULL) { \ - struct block_list *old = list; \ - list = list->next; \ - free (old); \ - } \ - } while (0) -# undef alloca -# define alloca(size) (malloc (size)) -#endif /* have alloca */ - - -#ifdef _LIBC -/* List of blocks allocated for translations. */ -typedef struct transmem_list -{ - struct transmem_list *next; - char data[ZERO]; -} transmem_block_t; -static struct transmem_list *transmem_list; -#else -typedef unsigned char transmem_block_t; -#endif - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCIGETTEXT __dcigettext -#else -# define DCIGETTEXT dcigettext__ -#endif - -/* Lock variable to protect the global data in the gettext implementation. */ -#ifdef _LIBC -__libc_rwlock_define_initialized (, _nl_state_lock) -#endif - -/* Checking whether the binaries runs SUID must be done and glibc provides - easier methods therefore we make a difference here. */ -#ifdef _LIBC -# define ENABLE_SECURE __libc_enable_secure -# define DETERMINE_SECURE -#else -# ifndef HAVE_GETUID -# define getuid() 0 -# endif -# ifndef HAVE_GETGID -# define getgid() 0 -# endif -# ifndef HAVE_GETEUID -# define geteuid() getuid() -# endif -# ifndef HAVE_GETEGID -# define getegid() getgid() -# endif -static int enable_secure; -# define ENABLE_SECURE (enable_secure == 1) -# define DETERMINE_SECURE \ - if (enable_secure == 0) \ - { \ - if (getuid () != geteuid () || getgid () != getegid ()) \ - enable_secure = 1; \ - else \ - enable_secure = -1; \ - } -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current - CATEGORY locale and, if PLURAL is nonzero, search over string - depending on the plural form determined by N. */ -char * -DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - int plural; - unsigned long int n; - int category; -{ -#ifndef HAVE_ALLOCA - struct block_list *block_list = NULL; -#endif - struct loaded_l10nfile *domain; - struct binding *binding; - const char *categoryname; - const char *categoryvalue; - char *dirname, *xdomainname; - char *single_locale; - char *retval; - size_t retlen; - int saved_errno; -#if defined HAVE_TSEARCH || defined _LIBC - struct known_translation_t *search; - struct known_translation_t **foundp = NULL; - size_t msgid_len; -#endif - size_t domainname_len; - - /* If no real MSGID is given return NULL. */ - if (msgid1 == NULL) - return NULL; - - __libc_rwlock_rdlock (_nl_state_lock); - - /* If DOMAINNAME is NULL, we are interested in the default domain. If - CATEGORY is not LC_MESSAGES this might not make much sense but the - definition left this undefined. */ - if (domainname == NULL) - domainname = _nl_current_default_domain; - -#if defined HAVE_TSEARCH || defined _LIBC - msgid_len = strlen (msgid1) + 1; - - /* Try to find the translation among those which we found at - some time. */ - search = (struct known_translation_t *) - alloca (offsetof (struct known_translation_t, msgid) + msgid_len); - memcpy (search->msgid, msgid1, msgid_len); - search->domainname = (char *) domainname; - search->category = category; - - foundp = (struct known_translation_t **) tfind (search, &root, transcmp); - if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) - { - /* Now deal with plural. */ - if (plural) - retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, - (*foundp)->translation_length); - else - retval = (char *) (*foundp)->translation; - - __libc_rwlock_unlock (_nl_state_lock); - return retval; - } -#endif - - /* Preserve the `errno' value. */ - saved_errno = errno; - - /* See whether this is a SUID binary or not. */ - DETERMINE_SECURE; - - /* First find matching binding. */ - for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) - { - int compare = strcmp (domainname, binding->domainname); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It is not in the list. */ - binding = NULL; - break; - } - } - - if (binding == NULL) - dirname = (char *) _nl_default_dirname; - else if (IS_ABSOLUTE_PATH (binding->dirname)) - dirname = binding->dirname; - else - { - /* We have a relative path. Make it absolute now. */ - size_t dirname_len = strlen (binding->dirname) + 1; - size_t path_max; - char *ret; - - path_max = (unsigned int) PATH_MAX; - path_max += 2; /* The getcwd docs say to do this. */ - - for (;;) - { - dirname = (char *) alloca (path_max + dirname_len); - ADD_BLOCK (block_list, dirname); - - __set_errno (0); - ret = getcwd (dirname, path_max); - if (ret != NULL || errno != ERANGE) - break; - - path_max += path_max / 2; - path_max += PATH_INCR; - } - - if (ret == NULL) - { - /* We cannot get the current working directory. Don't signal an - error but simply return the default string. */ - FREE_BLOCKS (block_list); - __libc_rwlock_unlock (_nl_state_lock); - __set_errno (saved_errno); - return (plural == 0 - ? (char *) msgid1 - /* Use the Germanic plural rule. */ - : n == 1 ? (char *) msgid1 : (char *) msgid2); - } - - stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); - } - - /* Now determine the symbolic name of CATEGORY and its value. */ - categoryname = category_to_name (category); - categoryvalue = guess_category_value (category, categoryname); - - domainname_len = strlen (domainname); - xdomainname = (char *) alloca (strlen (categoryname) - + domainname_len + 5); - ADD_BLOCK (block_list, xdomainname); - - stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), - domainname, domainname_len), - ".mo"); - - /* Creating working area. */ - single_locale = (char *) alloca (strlen (categoryvalue) + 1); - ADD_BLOCK (block_list, single_locale); - - - /* Search for the given string. This is a loop because we perhaps - got an ordered list of languages to consider for the translation. */ - while (1) - { - /* Make CATEGORYVALUE point to the next element of the list. */ - while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') - ++categoryvalue; - if (categoryvalue[0] == '\0') - { - /* The whole contents of CATEGORYVALUE has been searched but - no valid entry has been found. We solve this situation - by implicitly appending a "C" entry, i.e. no translation - will take place. */ - single_locale[0] = 'C'; - single_locale[1] = '\0'; - } - else - { - char *cp = single_locale; - while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') - *cp++ = *categoryvalue++; - *cp = '\0'; - - /* When this is a SUID binary we must not allow accessing files - outside the dedicated directories. */ - if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) - /* Ingore this entry. */ - continue; - } - - /* If the current locale value is C (or POSIX) we don't load a - domain. Return the MSGID. */ - if (strcmp (single_locale, "C") == 0 - || strcmp (single_locale, "POSIX") == 0) - { - FREE_BLOCKS (block_list); - __libc_rwlock_unlock (_nl_state_lock); - __set_errno (saved_errno); - return (plural == 0 - ? (char *) msgid1 - /* Use the Germanic plural rule. */ - : n == 1 ? (char *) msgid1 : (char *) msgid2); - } - - - /* Find structure describing the message catalog matching the - DOMAINNAME and CATEGORY. */ - domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); - - if (domain != NULL) - { - retval = _nl_find_msg (domain, binding, msgid1, &retlen); - - if (retval == NULL) - { - int cnt; - - for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) - { - retval = _nl_find_msg (domain->successor[cnt], binding, - msgid1, &retlen); - - if (retval != NULL) - { - domain = domain->successor[cnt]; - break; - } - } - } - - if (retval != NULL) - { - /* Found the translation of MSGID1 in domain DOMAIN: - starting at RETVAL, RETLEN bytes. */ - FREE_BLOCKS (block_list); - __set_errno (saved_errno); -#if defined HAVE_TSEARCH || defined _LIBC - if (foundp == NULL) - { - /* Create a new entry and add it to the search tree. */ - struct known_translation_t *newp; - - newp = (struct known_translation_t *) - malloc (offsetof (struct known_translation_t, msgid) - + msgid_len + domainname_len + 1); - if (newp != NULL) - { - newp->domainname = - mempcpy (newp->msgid, msgid1, msgid_len); - memcpy (newp->domainname, domainname, domainname_len + 1); - newp->category = category; - newp->counter = _nl_msg_cat_cntr; - newp->domain = domain; - newp->translation = retval; - newp->translation_length = retlen; - - /* Insert the entry in the search tree. */ - foundp = (struct known_translation_t **) - tsearch (newp, &root, transcmp); - if (foundp == NULL - || __builtin_expect (*foundp != newp, 0)) - /* The insert failed. */ - free (newp); - } - } - else - { - /* We can update the existing entry. */ - (*foundp)->counter = _nl_msg_cat_cntr; - (*foundp)->domain = domain; - (*foundp)->translation = retval; - (*foundp)->translation_length = retlen; - } -#endif - /* Now deal with plural. */ - if (plural) - retval = plural_lookup (domain, n, retval, retlen); - - __libc_rwlock_unlock (_nl_state_lock); - return retval; - } - } - } - /* NOTREACHED */ -} - - -char * -internal_function -_nl_find_msg (domain_file, domainbinding, msgid, lengthp) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; - const char *msgid; - size_t *lengthp; -{ - struct loaded_domain *domain; - size_t act; - char *result; - size_t resultlen; - - if (domain_file->decided == 0) - _nl_load_domain (domain_file, domainbinding); - - if (domain_file->data == NULL) - return NULL; - - domain = (struct loaded_domain *) domain_file->data; - - /* Locate the MSGID and its translation. */ - if (domain->hash_size > 2 && domain->hash_tab != NULL) - { - /* Use the hashing table. */ - nls_uint32 len = strlen (msgid); - nls_uint32 hash_val = hash_string (msgid); - nls_uint32 idx = hash_val % domain->hash_size; - nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); - - while (1) - { - nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); - - if (nstr == 0) - /* Hash table entry is empty. */ - return NULL; - - /* Compare msgid with the original string at index nstr-1. - We compare the lengths with >=, not ==, because plural entries - are represented by strings with an embedded NUL. */ - if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len - && (strcmp (msgid, - domain->data + W (domain->must_swap, - domain->orig_tab[nstr - 1].offset)) - == 0)) - { - act = nstr - 1; - goto found; - } - - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; - } - /* NOTREACHED */ - } - else - { - /* Try the default method: binary search in the sorted array of - messages. */ - size_t top, bottom; - - bottom = 0; - top = domain->nstrings; - while (bottom < top) - { - int cmp_val; - - act = (bottom + top) / 2; - cmp_val = strcmp (msgid, (domain->data - + W (domain->must_swap, - domain->orig_tab[act].offset))); - if (cmp_val < 0) - top = act; - else if (cmp_val > 0) - bottom = act + 1; - else - goto found; - } - /* No translation was found. */ - return NULL; - } - - found: - /* The translation was found at index ACT. If we have to convert the - string to use a different character set, this is the time. */ - result = ((char *) domain->data - + W (domain->must_swap, domain->trans_tab[act].offset)); - resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; - -#if defined _LIBC || HAVE_ICONV - if (domain->codeset_cntr - != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) - { - /* The domain's codeset has changed through bind_textdomain_codeset() - since the message catalog was initialized or last accessed. We - have to reinitialize the converter. */ - _nl_free_domain_conv (domain); - _nl_init_domain_conv (domain_file, domain, domainbinding); - } - - if ( -# ifdef _LIBC - domain->conv != (__gconv_t) -1 -# else -# if HAVE_ICONV - domain->conv != (iconv_t) -1 -# endif -# endif - ) - { - /* We are supposed to do a conversion. First allocate an - appropriate table with the same structure as the table - of translations in the file, where we can put the pointers - to the converted strings in. - There is a slight complication with plural entries. They - are represented by consecutive NUL terminated strings. We - handle this case by converting RESULTLEN bytes, including - NULs. */ - - if (domain->conv_tab == NULL - && ((domain->conv_tab = (char **) calloc (domain->nstrings, - sizeof (char *))) - == NULL)) - /* Mark that we didn't succeed allocating a table. */ - domain->conv_tab = (char **) -1; - - if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) - /* Nothing we can do, no more memory. */ - goto converted; - - if (domain->conv_tab[act] == NULL) - { - /* We haven't used this string so far, so it is not - translated yet. Do this now. */ - /* We use a bit more efficient memory handling. - We allocate always larger blocks which get used over - time. This is faster than many small allocations. */ - __libc_lock_define_initialized (static, lock) -# define INITIAL_BLOCK_SIZE 4080 - static unsigned char *freemem; - static size_t freemem_size; - - const unsigned char *inbuf; - unsigned char *outbuf; - int malloc_count; -# ifndef _LIBC - transmem_block_t *transmem_list = NULL; -# endif - - __libc_lock_lock (lock); - - inbuf = (const unsigned char *) result; - outbuf = freemem + sizeof (size_t); - - malloc_count = 0; - while (1) - { - transmem_block_t *newmem; -# ifdef _LIBC - size_t non_reversible; - int res; - - if (freemem_size < sizeof (size_t)) - goto resize_freemem; - - res = __gconv (domain->conv, - &inbuf, inbuf + resultlen, - &outbuf, - outbuf + freemem_size - sizeof (size_t), - &non_reversible); - - if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) - break; - - if (res != __GCONV_FULL_OUTPUT) - { - __libc_lock_unlock (lock); - goto converted; - } - - inbuf = result; -# else -# if HAVE_ICONV - const char *inptr = (const char *) inbuf; - size_t inleft = resultlen; - char *outptr = (char *) outbuf; - size_t outleft; - - if (freemem_size < sizeof (size_t)) - goto resize_freemem; - - outleft = freemem_size - sizeof (size_t); - if (iconv (domain->conv, - (ICONV_CONST char **) &inptr, &inleft, - &outptr, &outleft) - != (size_t) (-1)) - { - outbuf = (unsigned char *) outptr; - break; - } - if (errno != E2BIG) - { - __libc_lock_unlock (lock); - goto converted; - } -# endif -# endif - - resize_freemem: - /* We must allocate a new buffer or resize the old one. */ - if (malloc_count > 0) - { - ++malloc_count; - freemem_size = malloc_count * INITIAL_BLOCK_SIZE; - newmem = (transmem_block_t *) realloc (transmem_list, - freemem_size); -# ifdef _LIBC - if (newmem != NULL) - transmem_list = transmem_list->next; - else - { - struct transmem_list *old = transmem_list; - - transmem_list = transmem_list->next; - free (old); - } -# endif - } - else - { - malloc_count = 1; - freemem_size = INITIAL_BLOCK_SIZE; - newmem = (transmem_block_t *) malloc (freemem_size); - } - if (__builtin_expect (newmem == NULL, 0)) - { - freemem = NULL; - freemem_size = 0; - __libc_lock_unlock (lock); - goto converted; - } - -# ifdef _LIBC - /* Add the block to the list of blocks we have to free - at some point. */ - newmem->next = transmem_list; - transmem_list = newmem; - - freemem = newmem->data; - freemem_size -= offsetof (struct transmem_list, data); -# else - transmem_list = newmem; - freemem = newmem; -# endif - - outbuf = freemem + sizeof (size_t); - } - - /* We have now in our buffer a converted string. Put this - into the table of conversions. */ - *(size_t *) freemem = outbuf - freemem - sizeof (size_t); - domain->conv_tab[act] = (char *) freemem; - /* Shrink freemem, but keep it aligned. */ - freemem_size -= outbuf - freemem; - freemem = outbuf; - freemem += freemem_size & (alignof (size_t) - 1); - freemem_size = freemem_size & ~ (alignof (size_t) - 1); - - __libc_lock_unlock (lock); - } - - /* Now domain->conv_tab[act] contains the translation of all - the plural variants. */ - result = domain->conv_tab[act] + sizeof (size_t); - resultlen = *(size_t *) domain->conv_tab[act]; - } - - converted: - /* The result string is converted. */ - -#endif /* _LIBC || HAVE_ICONV */ - - *lengthp = resultlen; - return result; -} - - -/* Look up a plural variant. */ -static char * -internal_function -plural_lookup (domain, n, translation, translation_len) - struct loaded_l10nfile *domain; - unsigned long int n; - const char *translation; - size_t translation_len; -{ - struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; - unsigned long int index; - const char *p; - - index = plural_eval (domaindata->plural, n); - if (index >= domaindata->nplurals) - /* This should never happen. It means the plural expression and the - given maximum value do not match. */ - index = 0; - - /* Skip INDEX strings at TRANSLATION. */ - p = translation; - while (index-- > 0) - { -#ifdef _LIBC - p = __rawmemchr (p, '\0'); -#else - p = strchr (p, '\0'); -#endif - /* And skip over the NUL byte. */ - p++; - - if (p >= translation + translation_len) - /* This should never happen. It means the plural expression - evaluated to a value larger than the number of variants - available for MSGID1. */ - return (char *) translation; - } - return (char *) p; -} - - -/* Function to evaluate the plural expression and return an index value. */ -static unsigned long int -internal_function -plural_eval (pexp, n) - struct expression *pexp; - unsigned long int n; -{ - switch (pexp->nargs) - { - case 0: - switch (pexp->operation) - { - case var: - return n; - case num: - return pexp->val.num; - default: - break; - } - /* NOTREACHED */ - break; - case 1: - { - /* pexp->operation must be lnot. */ - unsigned long int arg = plural_eval (pexp->val.args[0], n); - return ! arg; - } - case 2: - { - unsigned long int leftarg = plural_eval (pexp->val.args[0], n); - if (pexp->operation == lor) - return leftarg || plural_eval (pexp->val.args[1], n); - else if (pexp->operation == land) - return leftarg && plural_eval (pexp->val.args[1], n); - else - { - unsigned long int rightarg = plural_eval (pexp->val.args[1], n); - - switch (pexp->operation) - { - case mult: - return leftarg * rightarg; - case divide: - return leftarg / rightarg; - case module: - return leftarg % rightarg; - case plus: - return leftarg + rightarg; - case minus: - return leftarg - rightarg; - case less_than: - return leftarg < rightarg; - case greater_than: - return leftarg > rightarg; - case less_or_equal: - return leftarg <= rightarg; - case greater_or_equal: - return leftarg >= rightarg; - case equal: - return leftarg == rightarg; - case not_equal: - return leftarg != rightarg; - default: - break; - } - } - /* NOTREACHED */ - break; - } - case 3: - { - /* pexp->operation must be qmop. */ - unsigned long int boolarg = plural_eval (pexp->val.args[0], n); - return plural_eval (pexp->val.args[boolarg ? 1 : 2], n); - } - } - /* NOTREACHED */ - return 0; -} - - -/* Return string representation of locale CATEGORY. */ -static const char * -internal_function -category_to_name (category) - int category; -{ - const char *retval; - - switch (category) - { -#ifdef LC_COLLATE - case LC_COLLATE: - retval = "LC_COLLATE"; - break; -#endif -#ifdef LC_CTYPE - case LC_CTYPE: - retval = "LC_CTYPE"; - break; -#endif -#ifdef LC_MONETARY - case LC_MONETARY: - retval = "LC_MONETARY"; - break; -#endif -#ifdef LC_NUMERIC - case LC_NUMERIC: - retval = "LC_NUMERIC"; - break; -#endif -#ifdef LC_TIME - case LC_TIME: - retval = "LC_TIME"; - break; -#endif -#ifdef LC_MESSAGES - case LC_MESSAGES: - retval = "LC_MESSAGES"; - break; -#endif -#ifdef LC_RESPONSE - case LC_RESPONSE: - retval = "LC_RESPONSE"; - break; -#endif -#ifdef LC_ALL - case LC_ALL: - /* This might not make sense but is perhaps better than any other - value. */ - retval = "LC_ALL"; - break; -#endif - default: - /* If you have a better idea for a default value let me know. */ - retval = "LC_XXX"; - } - - return retval; -} - -/* Guess value of current locale from value of the environment variables. */ -static const char * -internal_function -guess_category_value (category, categoryname) - int category; - const char *categoryname; -{ - const char *language; - const char *retval; - - /* The highest priority value is the `LANGUAGE' environment - variable. But we don't use the value if the currently selected - locale is the C locale. This is a GNU extension. */ - language = getenv ("LANGUAGE"); - if (language != NULL && language[0] == '\0') - language = NULL; - - /* We have to proceed with the POSIX methods of looking to `LC_ALL', - `LC_xxx', and `LANG'. On some systems this can be done by the - `setlocale' function itself. */ -#if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL) - retval = setlocale (category, NULL); -#else - /* Setting of LC_ALL overwrites all other. */ - retval = getenv ("LC_ALL"); - if (retval == NULL || retval[0] == '\0') - { - /* Next comes the name of the desired category. */ - retval = getenv (categoryname); - if (retval == NULL || retval[0] == '\0') - { - /* Last possibility is the LANG environment variable. */ - retval = getenv ("LANG"); - if (retval == NULL || retval[0] == '\0') - /* We use C as the default domain. POSIX says this is - implementation defined. */ - return "C"; - } - } -#endif - - return language != NULL && strcmp (retval, "C") != 0 ? language : retval; -} - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif - -#if !_LIBC && !HAVE_MEMPCPY -static void * -mempcpy (dest, src, n) - void *dest; - const void *src; - size_t n; -{ - return (void *) ((char *) memcpy (dest, src, n) + n); -} -#endif - - -#ifdef _LIBC -/* If we want to free all resources we have to do some work at - program's end. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - void *old; - - while (_nl_domain_bindings != NULL) - { - struct binding *oldp = _nl_domain_bindings; - _nl_domain_bindings = _nl_domain_bindings->next; - if (oldp->dirname != _nl_default_dirname) - /* Yes, this is a pointer comparison. */ - free (oldp->dirname); - free (oldp->codeset); - free (oldp); - } - - if (_nl_current_default_domain != _nl_default_default_domain) - /* Yes, again a pointer comparison. */ - free ((char *) _nl_current_default_domain); - - /* Remove the search tree with the known translations. */ - __tdestroy (root, free); - root = NULL; - - while (transmem_list != NULL) - { - old = transmem_list; - transmem_list = transmem_list->next; - free (old); - } -} - -text_set_element (__libc_subfreeres, free_mem); -#endif diff --git a/intl/dcngettext.c b/intl/dcngettext.c deleted file mode 100644 index c16af21..0000000 --- a/intl/dcngettext.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Implementation of the dcngettext(3) function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCNGETTEXT __dcngettext -# define DCIGETTEXT __dcigettext -#else -# define DCNGETTEXT dcngettext__ -# define DCIGETTEXT dcigettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -char * -DCNGETTEXT (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; -{ - return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dcngettext, dcngettext); -#endif diff --git a/intl/dgettext.c b/intl/dgettext.c deleted file mode 100644 index 3651207..0000000 --- a/intl/dgettext.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Implementation of the dgettext(3) function. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DGETTEXT __dgettext -# define DCGETTEXT __dcgettext -#else -# define DGETTEXT dgettext__ -# define DCGETTEXT dcgettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog of the current - LC_MESSAGES locale. */ -char * -DGETTEXT (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return DCGETTEXT (domainname, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dgettext, dgettext); -#endif diff --git a/intl/dngettext.c b/intl/dngettext.c deleted file mode 100644 index f214e95..0000000 --- a/intl/dngettext.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Implementation of the dngettext(3) function. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DNGETTEXT __dngettext -# define DCNGETTEXT __dcngettext -#else -# define DNGETTEXT dngettext__ -# define DCNGETTEXT dcngettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog of the current - LC_MESSAGES locale and skip message according to the plural form. */ -char * -DNGETTEXT (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dngettext, dngettext); -#endif diff --git a/intl/explodename.c b/intl/explodename.c deleted file mode 100644 index 2985064..0000000 --- a/intl/explodename.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include "loadinfo.h" - -/* On some strange systems still no definition of NULL is found. Sigh! */ -#ifndef NULL -# if defined __STDC__ && __STDC__ -# define NULL ((void *) 0) -# else -# define NULL 0 -# endif -#endif - -/* @@ end of prolog @@ */ - -char * -_nl_find_language (name) - const char *name; -{ - while (name[0] != '\0' && name[0] != '_' && name[0] != '@' - && name[0] != '+' && name[0] != ',') - ++name; - - return (char *) name; -} - - -int -_nl_explode_name (name, language, modifier, territory, codeset, - normalized_codeset, special, sponsor, revision) - char *name; - const char **language; - const char **modifier; - const char **territory; - const char **codeset; - const char **normalized_codeset; - const char **special; - const char **sponsor; - const char **revision; -{ - enum { undecided, xpg, cen } syntax; - char *cp; - int mask; - - *modifier = NULL; - *territory = NULL; - *codeset = NULL; - *normalized_codeset = NULL; - *special = NULL; - *sponsor = NULL; - *revision = NULL; - - /* Now we determine the single parts of the locale name. First - look for the language. Termination symbols are `_' and `@' if - we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = 0; - syntax = undecided; - *language = cp = name; - cp = _nl_find_language (*language); - - if (*language == cp) - /* This does not make sense: language has to be specified. Use - this entry as it is without exploding. Perhaps it is an alias. */ - cp = strchr (*language, '\0'); - else if (cp[0] == '_') - { - /* Next is the territory. */ - cp[0] = '\0'; - *territory = ++cp; - - while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' - && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= TERRITORY; - - if (cp[0] == '.') - { - /* Next is the codeset. */ - syntax = xpg; - cp[0] = '\0'; - *codeset = ++cp; - - while (cp[0] != '\0' && cp[0] != '@') - ++cp; - - mask |= XPG_CODESET; - - if (*codeset != cp && (*codeset)[0] != '\0') - { - *normalized_codeset = _nl_normalize_codeset (*codeset, - cp - *codeset); - if (strcmp (*codeset, *normalized_codeset) == 0) - free ((char *) *normalized_codeset); - else - mask |= XPG_NORM_CODESET; - } - } - } - - if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) - { - /* Next is the modifier. */ - syntax = cp[0] == '@' ? xpg : cen; - cp[0] = '\0'; - *modifier = ++cp; - - while (syntax == cen && cp[0] != '\0' && cp[0] != '+' - && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= XPG_MODIFIER | CEN_AUDIENCE; - } - - if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) - { - syntax = cen; - - if (cp[0] == '+') - { - /* Next is special application (CEN syntax). */ - cp[0] = '\0'; - *special = ++cp; - - while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= CEN_SPECIAL; - } - - if (cp[0] == ',') - { - /* Next is sponsor (CEN syntax). */ - cp[0] = '\0'; - *sponsor = ++cp; - - while (cp[0] != '\0' && cp[0] != '_') - ++cp; - - mask |= CEN_SPONSOR; - } - - if (cp[0] == '_') - { - /* Next is revision (CEN syntax). */ - cp[0] = '\0'; - *revision = ++cp; - - mask |= CEN_REVISION; - } - } - - /* For CEN syntax values it might be important to have the - separator character in the file name, not for XPG syntax. */ - if (syntax == xpg) - { - if (*territory != NULL && (*territory)[0] == '\0') - mask &= ~TERRITORY; - - if (*codeset != NULL && (*codeset)[0] == '\0') - mask &= ~XPG_CODESET; - - if (*modifier != NULL && (*modifier)[0] == '\0') - mask &= ~XPG_MODIFIER; - } - - return mask; -} diff --git a/intl/finddomain.c b/intl/finddomain.c deleted file mode 100644 index 2f103d5..0000000 --- a/intl/finddomain.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Handle list of needed message catalogs - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ -/* List of already loaded domains. */ -static struct loaded_l10nfile *_nl_loaded_domains; - - -/* Return a data structure describing the message catalog described by - the DOMAINNAME and CATEGORY parameters with respect to the currently - established bindings. */ -struct loaded_l10nfile * -internal_function -_nl_find_domain (dirname, locale, domainname, domainbinding) - const char *dirname; - char *locale; - const char *domainname; - struct binding *domainbinding; -{ - struct loaded_l10nfile *retval; - const char *language; - const char *modifier; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *special; - const char *sponsor; - const char *revision; - const char *alias_value; - int mask; - - /* LOCALE can consist of up to four recognized parts for the XPG syntax: - - language[_territory[.codeset]][@modifier] - - and six parts for the CEN syntax: - - language[_territory][+audience][+special][,[sponsor][_revision]] - - Beside the first part all of them are allowed to be missing. If - the full specified locale is not found, the less specific one are - looked for. The various parts will be stripped off according to - the following order: - (1) revision - (2) sponsor - (3) special - (4) codeset - (5) normalized codeset - (6) territory - (7) audience/modifier - */ - - /* If we have already tested for this locale entry there has to - be one data set in the list of loaded domains. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, 0, locale, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, domainname, 0); - if (retval != NULL) - { - /* We know something about this locale. */ - int cnt; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - - if (retval->data != NULL) - return retval; - - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - - if (retval->successor[cnt]->data != NULL) - break; - } - return cnt >= 0 ? retval : NULL; - /* NOTREACHED */ - } - - /* See whether the locale value is an alias. If yes its value - *overwrites* the alias name. No test for the original value is - done. */ - alias_value = _nl_expand_alias (locale); - if (alias_value != NULL) - { -#if defined _LIBC || defined HAVE_STRDUP - locale = strdup (alias_value); - if (locale == NULL) - return NULL; -#else - size_t len = strlen (alias_value) + 1; - locale = (char *) malloc (len); - if (locale == NULL) - return NULL; - - memcpy (locale, alias_value, len); -#endif - } - - /* Now we determine the single parts of the locale name. First - look for the language. Termination symbols are `_' and `@' if - we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = _nl_explode_name (locale, &language, &modifier, &territory, - &codeset, &normalized_codeset, &special, - &sponsor, &revision); - - /* Create all possible locale entries which might be interested in - generalization. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, mask, language, territory, - codeset, normalized_codeset, modifier, special, - sponsor, revision, domainname, 1); - if (retval == NULL) - /* This means we are out of core. */ - return NULL; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - if (retval->data == NULL) - { - int cnt; - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - if (retval->successor[cnt]->data != NULL) - break; - } - } - - /* The room for an alias was dynamically allocated. Free it now. */ - if (alias_value != NULL) - free (locale); - - /* The space for normalized_codeset is dynamically allocated. Free it. */ - if (mask & XPG_NORM_CODESET) - free ((void *) normalized_codeset); - - return retval; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - struct loaded_l10nfile *runp = _nl_loaded_domains; - - while (runp != NULL) - { - struct loaded_l10nfile *here = runp; - if (runp->data != NULL) - _nl_unload_domain ((struct loaded_domain *) runp->data); - runp = runp->next; - free ((char *) here->filename); - free (here); - } -} - -text_set_element (__libc_subfreeres, free_mem); -#endif diff --git a/intl/gettext.c b/intl/gettext.c deleted file mode 100644 index 22a6c24..0000000 --- a/intl/gettext.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Implementation of gettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef _LIBC -# define __need_NULL -# include -#else -# include /* Just for NULL. */ -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define GETTEXT __gettext -# define DCGETTEXT __dcgettext -#else -# define GETTEXT gettext__ -# define DCGETTEXT dcgettext__ -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -char * -GETTEXT (msgid) - const char *msgid; -{ - return DCGETTEXT (NULL, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__gettext, gettext); -#endif diff --git a/intl/gettext.h b/intl/gettext.h deleted file mode 100644 index 6f5d760..0000000 --- a/intl/gettext.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Description of GNU message catalog format: general file layout. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXT_H -#define _GETTEXT_H 1 - -#if HAVE_LIMITS_H || _LIBC -# include -#endif - -/* @@ end of prolog @@ */ - -/* The magic number of the GNU message catalog format. */ -#define _MAGIC 0x950412de -#define _MAGIC_SWAPPED 0xde120495 - -/* Revision number of the currently used .mo (binary) file format. */ -#define MO_REVISION_NUMBER 0 - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work - when cross-compiling. */ - -#if __STDC__ -# define UINT_MAX_32_BITS 4294967295U -#else -# define UINT_MAX_32_BITS 0xFFFFFFFF -#endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -#ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -#endif - -#if UINT_MAX == UINT_MAX_32_BITS -typedef unsigned nls_uint32; -#else -# if USHRT_MAX == UINT_MAX_32_BITS -typedef unsigned short nls_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS -typedef unsigned long nls_uint32; -# else - /* The following line is intended to throw an error. Using #error is - not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -#endif - - -/* Header for binary .mo file format. */ -struct mo_file_header -{ - /* The magic number. */ - nls_uint32 magic; - /* The revision number of the file format. */ - nls_uint32 revision; - /* The number of strings pairs. */ - nls_uint32 nstrings; - /* Offset of table with start offsets of original strings. */ - nls_uint32 orig_tab_offset; - /* Offset of table with start offsets of translation strings. */ - nls_uint32 trans_tab_offset; - /* Size of hashing table. */ - nls_uint32 hash_tab_size; - /* Offset of first hashing entry. */ - nls_uint32 hash_tab_offset; -}; - -struct string_desc -{ - /* Length of addressed string. */ - nls_uint32 length; - /* Offset of string in file. */ - nls_uint32 offset; -}; - -/* @@ begin of epilog @@ */ - -#endif /* gettext.h */ diff --git a/intl/gettextP.h b/intl/gettextP.h deleted file mode 100644 index 43de1cd..0000000 --- a/intl/gettextP.h +++ /dev/null @@ -1,252 +0,0 @@ -/* Header describing internals of libintl library. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXTP_H -#define _GETTEXTP_H - -#include /* Get size_t. */ - -#ifdef _LIBC -# include "../iconv/gconv_int.h" -#else -# if HAVE_ICONV -# include -# endif -#endif - -#include "loadinfo.h" - -#include "gettext.h" /* Get nls_uint32. */ - -/* @@ end of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -#ifndef W -# define W(flag, data) ((flag) ? SWAP (data) : (data)) -#endif - - -#ifdef _LIBC -# include -# define SWAP(i) bswap_32 (i) -#else -static inline nls_uint32 -SWAP (i) - nls_uint32 i; -{ - return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); -} -#endif - - -/* This is the representation of the expressions to determine the - plural form. */ -struct expression -{ - int nargs; /* Number of arguments. */ - enum operator - { - /* Without arguments: */ - var, /* The variable "n". */ - num, /* Decimal number. */ - /* Unary operators: */ - lnot, /* Logical NOT. */ - /* Binary operators: */ - mult, /* Multiplication. */ - divide, /* Division. */ - module, /* Module operation. */ - plus, /* Addition. */ - minus, /* Subtraction. */ - less_than, /* Comparison. */ - greater_than, /* Comparison. */ - less_or_equal, /* Comparison. */ - greater_or_equal, /* Comparison. */ - equal, /* Comparision for equality. */ - not_equal, /* Comparision for inequality. */ - land, /* Logical AND. */ - lor, /* Logical OR. */ - /* Ternary operators: */ - qmop /* Question mark operator. */ - } operation; - union - { - unsigned long int num; /* Number value for `num'. */ - struct expression *args[3]; /* Up to three arguments. */ - } val; -}; - -/* This is the data structure to pass information to the parser and get - the result in a thread-safe way. */ -struct parse_args -{ - const char *cp; - struct expression *res; -}; - - -/* The representation of an opened message catalog. */ -struct loaded_domain -{ - const char *data; - int use_mmap; - size_t mmap_size; - int must_swap; - nls_uint32 nstrings; - struct string_desc *orig_tab; - struct string_desc *trans_tab; - nls_uint32 hash_size; - nls_uint32 *hash_tab; - int codeset_cntr; -#ifdef _LIBC - __gconv_t conv; -#else -# if HAVE_ICONV - iconv_t conv; -# endif -#endif - char **conv_tab; - - struct expression *plural; - unsigned long int nplurals; -}; - -/* We want to allocate a string at the end of the struct. But ISO C - doesn't allow zero sized arrays. */ -#ifdef __GNUC__ -# define ZERO 0 -#else -# define ZERO 1 -#endif - -/* A set of settings bound to a message domain. Used to store settings - from bindtextdomain() and bind_textdomain_codeset(). */ -struct binding -{ - struct binding *next; - char *dirname; - int codeset_cntr; /* Incremented each time codeset changes. */ - char *codeset; - char domainname[ZERO]; -}; - -/* A counter which is incremented each time some previous translations - become invalid. - This variable is part of the external ABI of the GNU libintl. */ -extern int _nl_msg_cat_cntr; - -struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, - char *__locale, - const char *__domainname, - struct binding *__domainbinding)) - internal_function; -void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) - internal_function; -const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, - struct loaded_domain *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) - internal_function; - -char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, - struct binding *domainbinding, - const char *msgid, size_t *lengthp)) - internal_function; - -#ifdef _LIBC -extern char *__gettext PARAMS ((const char *__msgid)); -extern char *__dgettext PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *__dcgettext PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *__dngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int n)); -extern char *__dcngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *__dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *__textdomain PARAMS ((const char *__domainname)); -extern char *__bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); -#else -extern char *gettext__ PARAMS ((const char *__msgid)); -extern char *dgettext__ PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *dcgettext__ PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *ngettext__ PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *dngettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *dcngettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *dcigettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *textdomain__ PARAMS ((const char *__domainname)); -extern char *bindtextdomain__ PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *bind_textdomain_codeset__ PARAMS ((const char *__domainname, - const char *__codeset)); -#endif - -#ifdef _LIBC -extern void __gettext_free_exp PARAMS ((struct expression *exp)) - internal_function; -extern int __gettextparse PARAMS ((void *arg)); -#else -extern void gettext_free_exp__ PARAMS ((struct expression *exp)) - internal_function; -extern int gettextparse__ PARAMS ((void *arg)); -#endif - -/* @@ begin of epilog @@ */ - -#endif /* gettextP.h */ diff --git a/intl/hash-string.h b/intl/hash-string.h deleted file mode 100644 index ccb7acc..0000000 --- a/intl/hash-string.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Description of GNU message catalog format: string hashing function. - Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* @@ end of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif -#endif - -/* We assume to have `unsigned long int' value with at least 32 bits. */ -#define HASHWORDBITS 32 - - -/* Defines the so called `hashpjw' function by P.J. Weinberger - [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, - 1986, 1987 Bell Telephone Laboratories, Inc.] */ -static unsigned long int hash_string PARAMS ((const char *__str_param)); - -static inline unsigned long int -hash_string (str_param) - const char *str_param; -{ - unsigned long int hval, g; - const char *str = str_param; - - /* Compute the hash value for the given string. */ - hval = 0; - while (*str != '\0') - { - hval <<= 4; - hval += (unsigned long int) *str++; - g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); - if (g != 0) - { - hval ^= g >> (HASHWORDBITS - 8); - hval ^= g; - } - } - return hval; -} diff --git a/intl/intl-compat.c b/intl/intl-compat.c deleted file mode 100644 index 0a06ce9..0000000 --- a/intl/intl-compat.c +++ /dev/null @@ -1,166 +0,0 @@ -/* intl-compat.c - Stub functions to call gettext functions from GNU gettext - Library. - Copyright (C) 1995, 2000, 2001 Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "libgnuintl.h" -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -/* This file redirects the gettext functions (without prefix or suffix) to - those defined in the included GNU gettext library (with "__" suffix). - It is compiled into libintl when the included GNU gettext library is - configured --with-included-gettext. - - This redirection works also in the case that the system C library or - the system libintl library contain gettext/textdomain/... functions. - If it didn't, we would need to add preprocessor level redirections to - libgnuintl.h of the following form: - -# define gettext gettext__ -# define dgettext dgettext__ -# define dcgettext dcgettext__ -# define ngettext ngettext__ -# define dngettext dngettext__ -# define dcngettext dcngettext__ -# define textdomain textdomain__ -# define bindtextdomain bindtextdomain__ -# define bind_textdomain_codeset bind_textdomain_codeset__ - - How does this redirection work? There are two cases. - A. When libintl.a is linked into an executable, it works because - functions defined in the executable always override functions in - the shared libraries. - B. When libintl.so is used, it works because - 1. those systems defining gettext/textdomain/... in the C library - (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer) are - ELF systems and define these symbols as weak, thus explicitly - letting other shared libraries override it. - 2. those systems defining gettext/textdomain/... in a standalone - libintl.so library (namely, Solaris 2.3 and newer) have this - shared library in /usr/lib, and the linker will search /usr/lib - *after* the directory where the GNU gettext library is installed. - - A third case, namely when libintl.a is linked into a shared library - whose name is not libintl.so, is not supported. In this case, on - Solaris, when -lintl precedes the linker option for the shared library - containing GNU gettext, the system's gettext would indeed override - the GNU gettext. Anyone doing this kind of stuff must be clever enough - to 1. compile libintl.a with -fPIC, 2. remove -lintl from his linker - command line. */ - - -#undef gettext -#undef dgettext -#undef dcgettext -#undef ngettext -#undef dngettext -#undef dcngettext -#undef textdomain -#undef bindtextdomain -#undef bind_textdomain_codeset - - -char * -gettext (msgid) - const char *msgid; -{ - return gettext__ (msgid); -} - - -char * -dgettext (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return dgettext__ (domainname, msgid); -} - - -char * -dcgettext (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return dcgettext__ (domainname, msgid, category); -} - - -char * -ngettext (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return ngettext__ (msgid1, msgid2, n); -} - - -char * -dngettext (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return dngettext__ (domainname, msgid1, msgid2, n); -} - - -char * -dcngettext (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; -{ - return dcngettext__ (domainname, msgid1, msgid2, n, category); -} - - -char * -textdomain (domainname) - const char *domainname; -{ - return textdomain__ (domainname); -} - - -char * -bindtextdomain (domainname, dirname) - const char *domainname; - const char *dirname; -{ - return bindtextdomain__ (domainname, dirname); -} - - -char * -bind_textdomain_codeset (domainname, codeset) - const char *domainname; - const char *codeset; -{ - return bind_textdomain_codeset__ (domainname, codeset); -} diff --git a/intl/l10nflist.c b/intl/l10nflist.c deleted file mode 100644 index 533e94b..0000000 --- a/intl/l10nflist.c +++ /dev/null @@ -1,405 +0,0 @@ -/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for stpcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#if defined _LIBC || defined HAVE_ARGZ_H -# include -#endif -#include -#include -#include - -#include "loadinfo.h" - -/* On some strange systems still no definition of NULL is found. Sigh! */ -#ifndef NULL -# if defined __STDC__ && __STDC__ -# define NULL ((void *) 0) -# else -# define NULL 0 -# endif -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# ifndef stpcpy -# define stpcpy(dest, src) __stpcpy(dest, src) -# endif -#else -# ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -# endif -#endif - -/* Define function which are usually not available. */ - -#if !defined _LIBC && !defined HAVE___ARGZ_COUNT -/* Returns the number of strings in ARGZ. */ -static size_t argz_count__ PARAMS ((const char *argz, size_t len)); - -static size_t -argz_count__ (argz, len) - const char *argz; - size_t len; -{ - size_t count = 0; - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len + 1; - len -= part_len + 1; - count++; - } - return count; -} -# undef __argz_count -# define __argz_count(argz, len) argz_count__ (argz, len) -#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ - -#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY -/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's - except the last into the character SEP. */ -static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); - -static void -argz_stringify__ (argz, len, sep) - char *argz; - size_t len; - int sep; -{ - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len; - len -= part_len + 1; - if (len > 0) - *argz++ = sep; - } -} -# undef __argz_stringify -# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) -#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ - -#if !defined _LIBC && !defined HAVE___ARGZ_NEXT -static char *argz_next__ PARAMS ((char *argz, size_t argz_len, - const char *entry)); - -static char * -argz_next__ (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; -{ - if (entry) - { - if (entry < argz + argz_len) - entry = strchr (entry, '\0') + 1; - - return entry >= argz + argz_len ? NULL : (char *) entry; - } - else - if (argz_len > 0) - return argz; - else - return 0; -} -# undef __argz_next -# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) -#endif /* !_LIBC && !HAVE___ARGZ_NEXT */ - - -/* Return number of bits set in X. */ -static int pop PARAMS ((int x)); - -static inline int -pop (x) - int x; -{ - /* We assume that no more than 16 bits are used. */ - x = ((x & ~0x5555) >> 1) + (x & 0x5555); - x = ((x & ~0x3333) >> 2) + (x & 0x3333); - x = ((x >> 4) + x) & 0x0f0f; - x = ((x >> 8) + x) & 0xff; - - return x; -} - - -struct loaded_l10nfile * -_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, - territory, codeset, normalized_codeset, modifier, special, - sponsor, revision, filename, do_allocate) - struct loaded_l10nfile **l10nfile_list; - const char *dirlist; - size_t dirlist_len; - int mask; - const char *language; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *modifier; - const char *special; - const char *sponsor; - const char *revision; - const char *filename; - int do_allocate; -{ - char *abs_filename; - struct loaded_l10nfile *last = NULL; - struct loaded_l10nfile *retval; - char *cp; - size_t entries; - int cnt; - - /* Allocate room for the full file name. */ - abs_filename = (char *) malloc (dirlist_len - + strlen (language) - + ((mask & TERRITORY) != 0 - ? strlen (territory) + 1 : 0) - + ((mask & XPG_CODESET) != 0 - ? strlen (codeset) + 1 : 0) - + ((mask & XPG_NORM_CODESET) != 0 - ? strlen (normalized_codeset) + 1 : 0) - + (((mask & XPG_MODIFIER) != 0 - || (mask & CEN_AUDIENCE) != 0) - ? strlen (modifier) + 1 : 0) - + ((mask & CEN_SPECIAL) != 0 - ? strlen (special) + 1 : 0) - + (((mask & CEN_SPONSOR) != 0 - || (mask & CEN_REVISION) != 0) - ? (1 + ((mask & CEN_SPONSOR) != 0 - ? strlen (sponsor) + 1 : 0) - + ((mask & CEN_REVISION) != 0 - ? strlen (revision) + 1 : 0)) : 0) - + 1 + strlen (filename) + 1); - - if (abs_filename == NULL) - return NULL; - - retval = NULL; - last = NULL; - - /* Construct file name. */ - memcpy (abs_filename, dirlist, dirlist_len); - __argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR); - cp = abs_filename + (dirlist_len - 1); - *cp++ = '/'; - cp = stpcpy (cp, language); - - if ((mask & TERRITORY) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, territory); - } - if ((mask & XPG_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, codeset); - } - if ((mask & XPG_NORM_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, normalized_codeset); - } - if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) - { - /* This component can be part of both syntaces but has different - leading characters. For CEN we use `+', else `@'. */ - *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; - cp = stpcpy (cp, modifier); - } - if ((mask & CEN_SPECIAL) != 0) - { - *cp++ = '+'; - cp = stpcpy (cp, special); - } - if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) - { - *cp++ = ','; - if ((mask & CEN_SPONSOR) != 0) - cp = stpcpy (cp, sponsor); - if ((mask & CEN_REVISION) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, revision); - } - } - - *cp++ = '/'; - stpcpy (cp, filename); - - /* Look in list of already loaded domains whether it is already - available. */ - last = NULL; - for (retval = *l10nfile_list; retval != NULL; retval = retval->next) - if (retval->filename != NULL) - { - int compare = strcmp (retval->filename, abs_filename); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It's not in the list. */ - retval = NULL; - break; - } - - last = retval; - } - - if (retval != NULL || do_allocate == 0) - { - free (abs_filename); - return retval; - } - - retval = (struct loaded_l10nfile *) - malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len) - * (1 << pop (mask)) - * sizeof (struct loaded_l10nfile *))); - if (retval == NULL) - return NULL; - - retval->filename = abs_filename; - retval->decided = (__argz_count (dirlist, dirlist_len) != 1 - || ((mask & XPG_CODESET) != 0 - && (mask & XPG_NORM_CODESET) != 0)); - retval->data = NULL; - - if (last == NULL) - { - retval->next = *l10nfile_list; - *l10nfile_list = retval; - } - else - { - retval->next = last->next; - last->next = retval; - } - - entries = 0; - /* If the DIRLIST is a real list the RETVAL entry corresponds not to - a real file. So we have to use the DIRLIST separation mechanism - of the inner loop. */ - cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask; - for (; cnt >= 0; --cnt) - if ((cnt & ~mask) == 0 - && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) - && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) - { - /* Iterate over all elements of the DIRLIST. */ - char *dir = NULL; - - while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) - != NULL) - retval->successor[entries++] - = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt, - language, territory, codeset, - normalized_codeset, modifier, special, - sponsor, revision, filename, 1); - } - retval->successor[entries] = NULL; - - return retval; -} - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -const char * -_nl_normalize_codeset (codeset, name_len) - const char *codeset; - size_t name_len; -{ - int len = 0; - int only_digit = 1; - char *retval; - char *wp; - size_t cnt; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalnum (codeset[cnt])) - { - ++len; - - if (isalpha (codeset[cnt])) - only_digit = 0; - } - - retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); - - if (retval != NULL) - { - if (only_digit) - wp = stpcpy (retval, "iso"); - else - wp = retval; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalpha (codeset[cnt])) - *wp++ = tolower (codeset[cnt]); - else if (isdigit (codeset[cnt])) - *wp++ = codeset[cnt]; - - *wp = '\0'; - } - - return (const char *) retval; -} - - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif diff --git a/intl/libgettext.h b/intl/libgettext.h deleted file mode 100644 index c5be54a..0000000 --- a/intl/libgettext.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -#else - -# define gettext(Msgid) (Msgid) -# define dgettext(Domainname, Msgid) (Msgid) -# define dcgettext(Domainname, Msgid, Category) (Msgid) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define textdomain(Domainname) ((char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) ((char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) ((char *) (Codeset)) - -#endif - -/* For automatical extraction of messages sometimes no real - translation is needed. Instead the string itself is the result. */ -#define gettext_noop(Str) (Str) - -#endif /* _LIBGETTEXT_H */ diff --git a/intl/libgnuintl.h b/intl/libgnuintl.h deleted file mode 100644 index f891deb..0000000 --- a/intl/libgnuintl.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Message catalogs for internationalization. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LIBINTL_H -#define _LIBINTL_H 1 - -#include - -/* The LC_MESSAGES locale category is the category used by the functions - gettext() and dgettext(). It is specified in POSIX, but not in ANSI C. - On systems that don't define it, use an arbitrary value instead. - On Solaris, defines __LOCALE_H then includes (i.e. - this file!) and then only defines LC_MESSAGES. To avoid a redefinition - warning, don't define LC_MESSAGES in this case. */ -#if !defined LC_MESSAGES && !defined __LOCALE_H -# define LC_MESSAGES 1729 -#endif - -/* We define an additional symbol to signal that we use the GNU - implementation of gettext. */ -#define __USE_GNU_GETTEXT 1 - -/* Resolve a platform specific conflict on DJGPP. GNU gettext takes - precedence over _conio_gettext. */ -#ifdef __DJGPP__ -# undef gettext -# define gettext gettext -#endif - -#ifndef PARAMS -# if __STDC__ || defined __cplusplus -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -extern char *gettext PARAMS ((const char *__msgid)); - -/* Look up MSGID in the DOMAINNAME message catalog for the current - LC_MESSAGES locale. */ -extern char *dgettext PARAMS ((const char *__domainname, const char *__msgid)); - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -extern char *dcgettext PARAMS ((const char *__domainname, const char *__msgid, - int __category)); - - -/* Similar to `gettext' but select the plural form corresponding to the - number N. */ -extern char *ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); - -/* Similar to `dgettext' but select the plural form corresponding to the - number N. */ -extern char *dngettext PARAMS ((const char *__domainname, const char *__msgid1, - const char *__msgid2, unsigned long int __n)); - -/* Similar to `dcgettext' but select the plural form corresponding to the - number N. */ -extern char *dcngettext PARAMS ((const char *__domainname, const char *__msgid1, - const char *__msgid2, unsigned long int __n, - int __category)); - - -/* Set the current default message catalog to DOMAINNAME. - If DOMAINNAME is null, return the current default. - If DOMAINNAME is "", reset to the default of "messages". */ -extern char *textdomain PARAMS ((const char *__domainname)); - -/* Specify that the DOMAINNAME message catalog will be found - in DIRNAME rather than in the system locale data base. */ -extern char *bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); - -/* Specify the character encoding in which the messages from the - DOMAINNAME message catalog will be returned. */ -extern char *bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); - - -/* Optimized version of the functions above. */ -#if defined __OPTIMIZED -/* These are macros, but could also be inline functions. */ - -# define gettext(msgid) \ - dgettext (NULL, msgid) - -# define dgettext(domainname, msgid) \ - dcgettext (domainname, msgid, LC_MESSAGES) - -# define ngettext(msgid1, msgid2, n) \ - dngettext (NULL, msgid1, msgid2, n) - -# define dngettext(domainname, msgid1, msgid2, n) \ - dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES) - -#endif /* Optimizing. */ - - -#ifdef __cplusplus -} -#endif - -#endif /* libintl.h */ diff --git a/intl/loadinfo.h b/intl/loadinfo.h deleted file mode 100644 index b861260..0000000 --- a/intl/loadinfo.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 1996-1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 1996. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LOADINFO_H -#define _LOADINFO_H 1 - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -/* Separator in PATH like lists of pathnames. */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define PATH_SEPARATOR ';' -#else - /* Unix */ -# define PATH_SEPARATOR ':' -#endif - -/* Encoding of locale name parts. */ -#define CEN_REVISION 1 -#define CEN_SPONSOR 2 -#define CEN_SPECIAL 4 -#define XPG_NORM_CODESET 8 -#define XPG_CODESET 16 -#define TERRITORY 32 -#define CEN_AUDIENCE 64 -#define XPG_MODIFIER 128 - -#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) -#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) - - -struct loaded_l10nfile -{ - const char *filename; - int decided; - - const void *data; - - struct loaded_l10nfile *next; - struct loaded_l10nfile *successor[1]; -}; - - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, - size_t name_len)); - -extern struct loaded_l10nfile * -_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, - const char *dirlist, size_t dirlist_len, int mask, - const char *language, const char *territory, - const char *codeset, - const char *normalized_codeset, - const char *modifier, const char *special, - const char *sponsor, const char *revision, - const char *filename, int do_allocate)); - - -extern const char *_nl_expand_alias PARAMS ((const char *name)); - -/* normalized_codeset is dynamically allocated and has to be freed by - the caller. */ -extern int _nl_explode_name PARAMS ((char *name, const char **language, - const char **modifier, - const char **territory, - const char **codeset, - const char **normalized_codeset, - const char **special, - const char **sponsor, - const char **revision)); - -extern char *_nl_find_language PARAMS ((const char *name)); - -#endif /* loadinfo.h */ diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c deleted file mode 100644 index f99ebee..0000000 --- a/intl/loadmsgcat.c +++ /dev/null @@ -1,567 +0,0 @@ -/* Load needed message catalogs. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#ifdef _LIBC -# include -# include -#endif - -#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ - || (defined _LIBC && defined _POSIX_MAPPED_FILES) -# include -# undef HAVE_MMAP -# define HAVE_MMAP 1 -#else -# undef HAVE_MMAP -#endif - -#include "gettext.h" -#include "gettextP.h" - -#ifdef _LIBC -# include "../locale/localeinfo.h" -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ISO C functions. This is required by the standard - because some ISO C functions will require linking with this object - file and the name space must not be polluted. */ -# define open __open -# define close __close -# define read __read -# define mmap __mmap -# define munmap __munmap -#endif - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define PLURAL_PARSE __gettextparse -#else -# define PLURAL_PARSE gettextparse__ -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -/* For systems that distinguish between text and binary I/O. - O_BINARY is usually declared in . */ -#if !defined O_BINARY && defined _O_BINARY - /* For MSC-compatible compilers. */ -# define O_BINARY _O_BINARY -# define O_TEXT _O_TEXT -#endif -#ifdef __BEOS__ - /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ -# undef O_BINARY -# undef O_TEXT -#endif -/* On reasonable systems, binary I/O is the default. */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -/* We need a sign, whether a new catalog was loaded, which can be associated - with all translations. This is important if the translations are - cached by one of GCC's features. */ -int _nl_msg_cat_cntr; - -#if (defined __GNUC__ && !defined __APPLE_CC__) \ - || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - -/* These structs are the constant expression for the germanic plural - form determination. It represents the expression "n != 1". */ -static const struct expression plvar = -{ - .nargs = 0, - .operation = var, -}; -static const struct expression plone = -{ - .nargs = 0, - .operation = num, - .val = - { - .num = 1 - } -}; -static struct expression germanic_plural = -{ - .nargs = 2, - .operation = not_equal, - .val = - { - .args = - { - [0] = (struct expression *) &plvar, - [1] = (struct expression *) &plone - } - } -}; - -# define INIT_GERMANIC_PLURAL() - -#else - -/* For compilers without support for ISO C 99 struct/union initializers: - Initialization at run-time. */ - -static struct expression plvar; -static struct expression plone; -static struct expression germanic_plural; - -static void -init_germanic_plural () -{ - if (plone.val.num == 0) - { - plvar.nargs = 0; - plvar.operation = var; - - plone.nargs = 0; - plone.operation = num; - plone.val.num = 1; - - germanic_plural.nargs = 2; - germanic_plural.operation = not_equal; - germanic_plural.val.args[0] = &plvar; - germanic_plural.val.args[1] = &plone; - } -} - -# define INIT_GERMANIC_PLURAL() init_germanic_plural () - -#endif - - -/* Initialize the codeset dependent parts of an opened message catalog. - Return the header entry. */ -const char * -internal_function -_nl_init_domain_conv (domain_file, domain, domainbinding) - struct loaded_l10nfile *domain_file; - struct loaded_domain *domain; - struct binding *domainbinding; -{ - /* Find out about the character set the file is encoded with. - This can be found (in textual form) in the entry "". If this - entry does not exist or if this does not contain the `charset=' - information, we will assume the charset matches the one the - current locale and we don't have to perform any conversion. */ - char *nullentry; - size_t nullentrylen; - - /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ - domain->codeset_cntr = - (domainbinding != NULL ? domainbinding->codeset_cntr : 0); -#ifdef _LIBC - domain->conv = (__gconv_t) -1; -#else -# if HAVE_ICONV - domain->conv = (iconv_t) -1; -# endif -#endif - domain->conv_tab = NULL; - - /* Get the header entry. */ - nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); - - if (nullentry != NULL) - { -#if defined _LIBC || HAVE_ICONV - const char *charsetstr; - - charsetstr = strstr (nullentry, "charset="); - if (charsetstr != NULL) - { - size_t len; - char *charset; - const char *outcharset; - - charsetstr += strlen ("charset="); - len = strcspn (charsetstr, " \t\n"); - - charset = (char *) alloca (len + 1); -# if defined _LIBC || HAVE_MEMPCPY - *((char *) mempcpy (charset, charsetstr, len)) = '\0'; -# else - memcpy (charset, charsetstr, len); - charset[len] = '\0'; -# endif - - /* The output charset should normally be determined by the - locale. But sometimes the locale is not used or not correctly - set up, so we provide a possibility for the user to override - this. Moreover, the value specified through - bind_textdomain_codeset overrides both. */ - if (domainbinding != NULL && domainbinding->codeset != NULL) - outcharset = domainbinding->codeset; - else - { - outcharset = getenv ("OUTPUT_CHARSET"); - if (outcharset == NULL || outcharset[0] == '\0') - { -# ifdef _LIBC - outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; -# else -# if HAVE_ICONV - extern const char *locale_charset (void); - outcharset = locale_charset (); -# endif -# endif - } - } - -# ifdef _LIBC - /* We always want to use transliteration. */ - outcharset = norm_add_slashes (outcharset, "TRANSLIT"); - charset = norm_add_slashes (charset, NULL); - if (__gconv_open (outcharset, charset, &domain->conv, - GCONV_AVOID_NOCONV) - != __GCONV_OK) - domain->conv = (__gconv_t) -1; -# else -# if HAVE_ICONV - /* When using GNU libiconv, we want to use transliteration. */ -# if _LIBICONV_VERSION >= 0x0105 - len = strlen (outcharset); - { - char *tmp = (char *) alloca (len + 10 + 1); - memcpy (tmp, outcharset, len); - memcpy (tmp + len, "//TRANSLIT", 10 + 1); - outcharset = tmp; - } -# endif - domain->conv = iconv_open (outcharset, charset); -# if _LIBICONV_VERSION >= 0x0105 - freea (outcharset); -# endif -# endif -# endif - - freea (charset); - } -#endif /* _LIBC || HAVE_ICONV */ - } - - return nullentry; -} - -/* Frees the codeset dependent parts of an opened message catalog. */ -void -internal_function -_nl_free_domain_conv (domain) - struct loaded_domain *domain; -{ - if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) - free (domain->conv_tab); - -#ifdef _LIBC - if (domain->conv != (__gconv_t) -1) - __gconv_close (domain->conv); -#else -# if HAVE_ICONV - if (domain->conv != (iconv_t) -1) - iconv_close (domain->conv); -# endif -#endif -} - -/* Load the message catalogs specified by FILENAME. If it is no valid - message catalog do nothing. */ -void -internal_function -_nl_load_domain (domain_file, domainbinding) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; -{ - int fd; - size_t size; -#ifdef _LIBC - struct stat64 st; -#else - struct stat st; -#endif - struct mo_file_header *data = (struct mo_file_header *) -1; - int use_mmap = 0; - struct loaded_domain *domain; - const char *nullentry; - - domain_file->decided = 1; - domain_file->data = NULL; - - /* Note that it would be useless to store domainbinding in domain_file - because domainbinding might be == NULL now but != NULL later (after - a call to bind_textdomain_codeset). */ - - /* If the record does not represent a valid locale the FILENAME - might be NULL. This can happen when according to the given - specification the locale file name is different for XPG and CEN - syntax. */ - if (domain_file->filename == NULL) - return; - - /* Try to open the addressed file. */ - fd = open (domain_file->filename, O_RDONLY | O_BINARY); - if (fd == -1) - return; - - /* We must know about the size of the file. */ - if ( -#ifdef _LIBC - __builtin_expect (fstat64 (fd, &st) != 0, 0) -#else - __builtin_expect (fstat (fd, &st) != 0, 0) -#endif - || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) - || __builtin_expect (size < sizeof (struct mo_file_header), 0)) - { - /* Something went wrong. */ - close (fd); - return; - } - -#ifdef HAVE_MMAP - /* Now we are ready to load the file. If mmap() is available we try - this first. If not available or it failed we try to load it. */ - data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, - MAP_PRIVATE, fd, 0); - - if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) - { - /* mmap() call was successful. */ - close (fd); - use_mmap = 1; - } -#endif - - /* If the data is not yet available (i.e. mmap'ed) we try to load - it manually. */ - if (data == (struct mo_file_header *) -1) - { - size_t to_read; - char *read_ptr; - - data = (struct mo_file_header *) malloc (size); - if (data == NULL) - return; - - to_read = size; - read_ptr = (char *) data; - do - { - long int nb = (long int) read (fd, read_ptr, to_read); - if (nb <= 0) - { -#ifdef EINTR - if (nb == -1 && errno == EINTR) - continue; -#endif - close (fd); - return; - } - read_ptr += nb; - to_read -= nb; - } - while (to_read > 0); - - close (fd); - } - - /* Using the magic number we can test whether it really is a message - catalog file. */ - if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, - 0)) - { - /* The magic number is wrong: not a message catalog file. */ -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - return; - } - - domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); - if (domain == NULL) - return; - domain_file->data = domain; - - domain->data = (char *) data; - domain->use_mmap = use_mmap; - domain->mmap_size = size; - domain->must_swap = data->magic != _MAGIC; - - /* Fill in the information about the available tables. */ - switch (W (domain->must_swap, data->revision)) - { - case 0: - domain->nstrings = W (domain->must_swap, data->nstrings); - domain->orig_tab = (struct string_desc *) - ((char *) data + W (domain->must_swap, data->orig_tab_offset)); - domain->trans_tab = (struct string_desc *) - ((char *) data + W (domain->must_swap, data->trans_tab_offset)); - domain->hash_size = W (domain->must_swap, data->hash_tab_size); - domain->hash_tab = (nls_uint32 *) - ((char *) data + W (domain->must_swap, data->hash_tab_offset)); - break; - default: - /* This is an invalid revision. */ -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - free (domain); - domain_file->data = NULL; - return; - } - - /* Now initialize the character set converter from the character set - the file is encoded with (found in the header entry) to the domain's - specified character set or the locale's character set. */ - nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); - - /* Also look for a plural specification. */ - if (nullentry != NULL) - { - const char *plural; - const char *nplurals; - - plural = strstr (nullentry, "plural="); - nplurals = strstr (nullentry, "nplurals="); - if (plural == NULL || nplurals == NULL) - goto no_plural; - else - { - /* First get the number. */ - char *endp; - unsigned long int n; - struct parse_args args; - - nplurals += 9; - while (*nplurals != '\0' && isspace (*nplurals)) - ++nplurals; -#if defined HAVE_STRTOUL || defined _LIBC - n = strtoul (nplurals, &endp, 10); -#else - for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) - n = n * 10 + (*endp - '0'); -#endif - domain->nplurals = n; - if (nplurals == endp) - goto no_plural; - - /* Due to the restrictions bison imposes onto the interface of the - scanner function we have to put the input string and the result - passed up from the parser into the same structure which address - is passed down to the parser. */ - plural += 7; - args.cp = plural; - if (PLURAL_PARSE (&args) != 0) - goto no_plural; - domain->plural = args.res; - } - } - else - { - /* By default we are using the Germanic form: singular form only - for `one', the plural form otherwise. Yes, this is also what - English is using since English is a Germanic language. */ - no_plural: - INIT_GERMANIC_PLURAL (); - domain->plural = &germanic_plural; - domain->nplurals = 2; - } -} - - -#ifdef _LIBC -void -internal_function -_nl_unload_domain (domain) - struct loaded_domain *domain; -{ - if (domain->plural != &germanic_plural) - __gettext_free_exp (domain->plural); - - _nl_free_domain_conv (domain); - -# ifdef _POSIX_MAPPED_FILES - if (domain->use_mmap) - munmap ((caddr_t) domain->data, domain->mmap_size); - else -# endif /* _POSIX_MAPPED_FILES */ - free ((void *) domain->data); - - free (domain); -} -#endif diff --git a/intl/localcharset.c b/intl/localcharset.c deleted file mode 100644 index 61f8f3e..0000000 --- a/intl/localcharset.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - - Copyright (C) 2000-2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Written by Bruno Haible . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if HAVE_STDDEF_H -# include -#endif - -#include -#if HAVE_STRING_H -# include -#else -# include -#endif -#if HAVE_STDLIB_H -# include -#endif - -#if defined _WIN32 || defined __WIN32__ -# undef WIN32 /* avoid warning on mingw32 */ -# define WIN32 -#endif - -#ifndef WIN32 -# if HAVE_LANGINFO_CODESET -# include -# else -# if HAVE_SETLOCALE -# include -# endif -# endif -#else /* WIN32 */ -# define WIN32_LEAN_AND_MEAN -# include -#endif - -#ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -#endif - -#ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -#endif - -/* The following static variable is declared 'volatile' to avoid a - possible multithread problem in the function get_charset_aliases. If we - are running in a threaded environment, and if two threads initialize - 'charset_aliases' simultaneously, both will produce the same value, - and everything will be ok if the two assignments to 'charset_aliases' - are atomic. But I don't know what will happen if the two assignments mix. */ -#if __STDC__ != 1 -# define volatile /* empty */ -#endif -/* Pointer to the contents of the charset.alias file, if it has already been - read, else NULL. Its format is: - ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ -static const char * volatile charset_aliases; - -/* Return a pointer to the contents of the charset.alias file. */ -static const char * -get_charset_aliases () -{ - const char *cp; - - cp = charset_aliases; - if (cp == NULL) - { -#ifndef WIN32 - FILE *fp; - const char *dir = LIBDIR; - const char *base = "charset.alias"; - char *file_name; - - /* Concatenate dir and base into freshly allocated file_name. */ - { - size_t dir_len = strlen (dir); - size_t base_len = strlen (base); - int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); - file_name = (char *) malloc (dir_len + add_slash + base_len + 1); - if (file_name != NULL) - { - memcpy (file_name, dir, dir_len); - if (add_slash) - file_name[dir_len] = DIRECTORY_SEPARATOR; - memcpy (file_name + dir_len + add_slash, base, base_len + 1); - } - } - - if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) - /* Out of memory or file not found, treat it as empty. */ - cp = ""; - else - { - /* Parse the file's contents. */ - int c; - char buf1[50+1]; - char buf2[50+1]; - char *res_ptr = NULL; - size_t res_size = 0; - size_t l1, l2; - - for (;;) - { - c = getc (fp); - if (c == EOF) - break; - if (c == '\n' || c == ' ' || c == '\t') - continue; - if (c == '#') - { - /* Skip comment, to end of line. */ - do - c = getc (fp); - while (!(c == EOF || c == '\n')); - if (c == EOF) - break; - continue; - } - ungetc (c, fp); - if (fscanf(fp, "%50s %50s", buf1, buf2) < 2) - break; - l1 = strlen (buf1); - l2 = strlen (buf2); - if (res_size == 0) - { - res_size = l1 + 1 + l2 + 1; - res_ptr = malloc (res_size + 1); - } - else - { - res_size += l1 + 1 + l2 + 1; - res_ptr = realloc (res_ptr, res_size + 1); - } - if (res_ptr == NULL) - { - /* Out of memory. */ - res_size = 0; - break; - } - strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); - strcpy (res_ptr + res_size - (l2 + 1), buf2); - } - fclose (fp); - if (res_size == 0) - cp = ""; - else - { - *(res_ptr + res_size) = '\0'; - cp = res_ptr; - } - } - - if (file_name != NULL) - free (file_name); - -#else /* WIN32 */ - - /* To avoid the troubles of installing a separate file in the same - directory as the DLL and of retrieving the DLL's directory at - runtime, simply inline the aliases here. */ - - cp = "CP936" "\0" "GBK" "\0" - "CP1361" "\0" "JOHAB" "\0"; -#endif - - charset_aliases = cp; - } - - return cp; -} - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ - -#ifdef STATIC -STATIC -#endif -const char * -locale_charset () -{ - const char *codeset; - const char *aliases; - -#ifndef WIN32 - -# if HAVE_LANGINFO_CODESET - - /* Most systems support nl_langinfo (CODESET) nowadays. */ - codeset = nl_langinfo (CODESET); - -# else - - /* On old systems which lack it, use setlocale or getenv. */ - const char *locale = NULL; - - /* But most old systems don't have a complete set of locales. Some - (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't - use setlocale here; it would return "C" when it doesn't support the - locale name the user has set. */ -# if HAVE_SETLOCALE && 0 - locale = setlocale (LC_CTYPE, NULL); -# endif - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - } - - /* On some old systems, one used to set locale = "iso8859_1". On others, - you set it to "language_COUNTRY.charset". In any case, we resolve it - through the charset.alias file. */ - codeset = locale; - -# endif - -#else /* WIN32 */ - - static char buf[2 + 10 + 1]; - - /* Win32 has a function returning the locale's codepage as a number. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - -#endif - - if (codeset == NULL) - /* The canonical name cannot be determined. */ - codeset = ""; - - /* Resolve alias. */ - for (aliases = get_charset_aliases (); - *aliases != '\0'; - aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) - if (strcmp (codeset, aliases) == 0 - || (aliases[0] == '*' && aliases[1] == '\0')) - { - codeset = aliases + strlen (aliases) + 1; - break; - } - - return codeset; -} diff --git a/intl/locale.alias b/intl/locale.alias deleted file mode 100644 index bd7b9b3..0000000 --- a/intl/locale.alias +++ /dev/null @@ -1,78 +0,0 @@ -# Locale name alias data base. -# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. - -# The format of this file is the same as for the corresponding file of -# the X Window System, which normally can be found in -# /usr/lib/X11/locale/locale.alias -# A single line contains two fields: an alias and a substitution value. -# All entries are case independent. - -# Note: This file is far from being complete. If you have a value for -# your own site which you think might be useful for others too, share -# it with the rest of us. Send it using the `glibcbug' script to -# bugs@gnu.org. - -# Packages using this file: - -bokmal no_NO.ISO-8859-1 -bokmål no_NO.ISO-8859-1 -catalan ca_ES.ISO-8859-1 -croatian hr_HR.ISO-8859-2 -czech cs_CZ.ISO-8859-2 -danish da_DK.ISO-8859-1 -dansk da_DK.ISO-8859-1 -deutsch de_DE.ISO-8859-1 -dutch nl_NL.ISO-8859-1 -eesti et_EE.ISO-8859-1 -estonian et_EE.ISO-8859-1 -finnish fi_FI.ISO-8859-1 -français fr_FR.ISO-8859-1 -french fr_FR.ISO-8859-1 -galego gl_ES.ISO-8859-1 -galician gl_ES.ISO-8859-1 -german de_DE.ISO-8859-1 -greek el_GR.ISO-8859-7 -hebrew he_IL.ISO-8859-8 -hrvatski hr_HR.ISO-8859-2 -hungarian hu_HU.ISO-8859-2 -icelandic is_IS.ISO-8859-1 -italian it_IT.ISO-8859-1 -japanese ja_JP.eucJP -japanese.euc ja_JP.eucJP -ja_JP ja_JP.eucJP -ja_JP.ujis ja_JP.eucJP -japanese.sjis ja_JP.SJIS -korean ko_KR.eucKR -korean.euc ko_KR.eucKR -ko_KR ko_KR.eucKR -lithuanian lt_LT.ISO-8859-13 -nb_NO no_NO.ISO-8859-1 -nb_NO.ISO-8859-1 no_NO.ISO-8859-1 -norwegian no_NO.ISO-8859-1 -nynorsk nn_NO.ISO-8859-1 -polish pl_PL.ISO-8859-2 -portuguese pt_PT.ISO-8859-1 -romanian ro_RO.ISO-8859-2 -russian ru_RU.ISO-8859-5 -slovak sk_SK.ISO-8859-2 -slovene sl_SI.ISO-8859-2 -slovenian sl_SI.ISO-8859-2 -spanish es_ES.ISO-8859-1 -swedish sv_SE.ISO-8859-1 -thai th_TH.TIS-620 -turkish tr_TR.ISO-8859-9 diff --git a/intl/localealias.c b/intl/localealias.c deleted file mode 100644 index 91e7acc..0000000 --- a/intl/localealias.c +++ /dev/null @@ -1,404 +0,0 @@ -/* Handle aliases for locale names. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# define strcasecmp __strcasecmp - -# ifndef mempcpy -# define mempcpy __mempcpy -# endif -# define HAVE_MEMPCPY 1 - -/* We need locking here since we can be called from different places. */ -# include - -__libc_lock_define_initialized (static, lock); -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED -# undef fgets -# define fgets(buf, len, s) fgets_unlocked (buf, len, s) -#endif -#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED -# undef feof -# define feof(s) feof_unlocked (s) -#endif - - -struct alias_map -{ - const char *alias; - const char *value; -}; - - -static char *string_space; -static size_t string_space_act; -static size_t string_space_max; -static struct alias_map *map; -static size_t nmap; -static size_t maxmap; - - -/* Prototypes for local functions. */ -static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) - internal_function; -static int extend_alias_table PARAMS ((void)); -static int alias_compare PARAMS ((const struct alias_map *map1, - const struct alias_map *map2)); - - -const char * -_nl_expand_alias (name) - const char *name; -{ - static const char *locale_alias_path = LOCALE_ALIAS_PATH; - struct alias_map *retval; - const char *result = NULL; - size_t added; - -#ifdef _LIBC - __libc_lock_lock (lock); -#endif - - do - { - struct alias_map item; - - item.alias = name; - - if (nmap > 0) - retval = (struct alias_map *) bsearch (&item, map, nmap, - sizeof (struct alias_map), - (int (*) PARAMS ((const void *, - const void *)) - ) alias_compare); - else - retval = NULL; - - /* We really found an alias. Return the value. */ - if (retval != NULL) - { - result = retval->value; - break; - } - - /* Perhaps we can find another alias file. */ - added = 0; - while (added == 0 && locale_alias_path[0] != '\0') - { - const char *start; - - while (locale_alias_path[0] == PATH_SEPARATOR) - ++locale_alias_path; - start = locale_alias_path; - - while (locale_alias_path[0] != '\0' - && locale_alias_path[0] != PATH_SEPARATOR) - ++locale_alias_path; - - if (start < locale_alias_path) - added = read_alias_file (start, locale_alias_path - start); - } - } - while (added != 0); - -#ifdef _LIBC - __libc_lock_unlock (lock); -#endif - - return result; -} - - -static size_t -internal_function -read_alias_file (fname, fname_len) - const char *fname; - int fname_len; -{ - FILE *fp; - char *full_fname; - size_t added; - static const char aliasfile[] = "/locale.alias"; - - full_fname = (char *) alloca (fname_len + sizeof aliasfile); -#ifdef HAVE_MEMPCPY - mempcpy (mempcpy (full_fname, fname, fname_len), - aliasfile, sizeof aliasfile); -#else - memcpy (full_fname, fname, fname_len); - memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); -#endif - - fp = fopen (full_fname, "r"); - freea (full_fname); - if (fp == NULL) - return 0; - - added = 0; - while (!feof (fp)) - { - /* It is a reasonable approach to use a fix buffer here because - a) we are only interested in the first two fields - b) these fields must be usable as file names and so must not - be that long - */ - char buf[BUFSIZ]; - char *alias; - char *value; - char *cp; - - if (fgets (buf, sizeof buf, fp) == NULL) - /* EOF reached. */ - break; - - /* Possibly not the whole line fits into the buffer. Ignore - the rest of the line. */ - if (strchr (buf, '\n') == NULL) - { - char altbuf[BUFSIZ]; - do - if (fgets (altbuf, sizeof altbuf, fp) == NULL) - /* Make sure the inner loop will be left. The outer loop - will exit at the `feof' test. */ - break; - while (strchr (altbuf, '\n') == NULL); - } - - cp = buf; - /* Ignore leading white space. */ - while (isspace (cp[0])) - ++cp; - - /* A leading '#' signals a comment line. */ - if (cp[0] != '\0' && cp[0] != '#') - { - alias = cp++; - while (cp[0] != '\0' && !isspace (cp[0])) - ++cp; - /* Terminate alias name. */ - if (cp[0] != '\0') - *cp++ = '\0'; - - /* Now look for the beginning of the value. */ - while (isspace (cp[0])) - ++cp; - - if (cp[0] != '\0') - { - size_t alias_len; - size_t value_len; - - value = cp++; - while (cp[0] != '\0' && !isspace (cp[0])) - ++cp; - /* Terminate value. */ - if (cp[0] == '\n') - { - /* This has to be done to make the following test - for the end of line possible. We are looking for - the terminating '\n' which do not overwrite here. */ - *cp++ = '\0'; - *cp = '\n'; - } - else if (cp[0] != '\0') - *cp++ = '\0'; - - if (nmap >= maxmap) - if (__builtin_expect (extend_alias_table (), 0)) - return added; - - alias_len = strlen (alias) + 1; - value_len = strlen (value) + 1; - - if (string_space_act + alias_len + value_len > string_space_max) - { - /* Increase size of memory pool. */ - size_t new_size = (string_space_max - + (alias_len + value_len > 1024 - ? alias_len + value_len : 1024)); - char *new_pool = (char *) realloc (string_space, new_size); - if (new_pool == NULL) - return added; - - if (__builtin_expect (string_space != new_pool, 0)) - { - size_t i; - - for (i = 0; i < nmap; i++) - { - map[i].alias += new_pool - string_space; - map[i].value += new_pool - string_space; - } - } - - string_space = new_pool; - string_space_max = new_size; - } - - map[nmap].alias = memcpy (&string_space[string_space_act], - alias, alias_len); - string_space_act += alias_len; - - map[nmap].value = memcpy (&string_space[string_space_act], - value, value_len); - string_space_act += value_len; - - ++nmap; - ++added; - } - } - } - - /* Should we test for ferror()? I think we have to silently ignore - errors. --drepper */ - fclose (fp); - - if (added > 0) - qsort (map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, const void *))) alias_compare); - - return added; -} - - -static int -extend_alias_table () -{ - size_t new_size; - struct alias_map *new_map; - - new_size = maxmap == 0 ? 100 : 2 * maxmap; - new_map = (struct alias_map *) realloc (map, (new_size - * sizeof (struct alias_map))); - if (new_map == NULL) - /* Simply don't extend: we don't have any more core. */ - return -1; - - map = new_map; - maxmap = new_size; - return 0; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - if (string_space != NULL) - free (string_space); - if (map != NULL) - free (map); -} -text_set_element (__libc_subfreeres, free_mem); -#endif - - -static int -alias_compare (map1, map2) - const struct alias_map *map1; - const struct alias_map *map2; -{ -#if defined _LIBC || defined HAVE_STRCASECMP - return strcasecmp (map1->alias, map2->alias); -#else - const unsigned char *p1 = (const unsigned char *) map1->alias; - const unsigned char *p2 = (const unsigned char *) map2->alias; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - /* I know this seems to be odd but the tolower() function in - some systems libc cannot handle nonalpha characters. */ - c1 = isupper (*p1) ? tolower (*p1) : *p1; - c2 = isupper (*p2) ? tolower (*p2) : *p2; - if (c1 == '\0') - break; - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -#endif -} diff --git a/intl/ngettext.c b/intl/ngettext.c deleted file mode 100644 index fb3ec5a..0000000 --- a/intl/ngettext.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Implementation of ngettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef _LIBC -# define __need_NULL -# include -#else -# include /* Just for NULL. */ -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -#include - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define NGETTEXT __ngettext -# define DCNGETTEXT __dcngettext -#else -# define NGETTEXT ngettext__ -# define DCNGETTEXT dcngettext__ -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -char * -NGETTEXT (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__ngettext, ngettext); -#endif diff --git a/intl/plural.c b/intl/plural.c deleted file mode 100644 index 640d43c..0000000 --- a/intl/plural.c +++ /dev/null @@ -1,1326 +0,0 @@ - -/* A Bison parser, made from plural.y - by GNU Bison version 1.28 */ - -#define YYBISON 1 /* Identify Bison output. */ - -#define yyparse __gettextparse -#define yylex __gettextlex -#define yyerror __gettexterror -#define yylval __gettextlval -#define yychar __gettextchar -#define yydebug __gettextdebug -#define yynerrs __gettextnerrs -#define EQUOP2 257 -#define CMPOP2 258 -#define ADDOP2 259 -#define MULOP2 260 -#define NUMBER 261 - -#line 1 "plural.y" - -/* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 2000. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* The bison generated parser uses alloca. AIX 3 forces us to put this - declaration at the beginning of the file. The declaration in bison's - skeleton file comes too late. This must come before - because may include arbitrary system headers. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "gettextP.h" - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define FREE_EXPRESSION __gettext_free_exp -#else -# define FREE_EXPRESSION gettext_free_exp__ -# define __gettextparse gettextparse__ -#endif - -#define YYLEX_PARAM &((struct parse_args *) arg)->cp -#define YYPARSE_PARAM arg - -#line 53 "plural.y" -typedef union { - unsigned long int num; - enum operator op; - struct expression *exp; -} YYSTYPE; -#line 59 "plural.y" - -/* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); - -/* Allocation of expressions. */ - -static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; -{ - int i; - struct expression *newp; - - /* If any of the argument could not be malloc'ed, just return NULL. */ - for (i = nargs - 1; i >= 0; i--) - if (args[i] == NULL) - goto fail; - - /* Allocate a new expression. */ - newp = (struct expression *) malloc (sizeof (*newp)); - if (newp != NULL) - { - newp->nargs = nargs; - newp->operation = op; - for (i = nargs - 1; i >= 0; i--) - newp->val.args[i] = args[i]; - return newp; - } - - fail: - for (i = nargs - 1; i >= 0; i--) - FREE_EXPRESSION (args[i]); - - return NULL; -} - -static inline struct expression * -new_exp_0 (op) - enum operator op; -{ - return new_exp (0, op, NULL); -} - -static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; -{ - struct expression *args[1]; - - args[0] = right; - return new_exp (1, op, args); -} - -static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; -{ - struct expression *args[2]; - - args[0] = left; - args[1] = right; - return new_exp (2, op, args); -} - -static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; -{ - struct expression *args[3]; - - args[0] = bexp; - args[1] = tbranch; - args[2] = fbranch; - return new_exp (3, op, args); -} - -#include - -#ifndef __cplusplus -#ifndef __STDC__ -#define const -#endif -#endif - - - -#define YYFINAL 27 -#define YYFLAG -32768 -#define YYNTBASE 16 - -#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) - -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, 10, 2, 2, 2, 2, 5, 2, 14, - 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 12, 2, 2, - 2, 2, 3, 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, 13, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 4, 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, 6, 7, 8, 9, - 11 -}; - -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 2, 8, 12, 16, 20, 24, 28, 32, 35, - 37, 39 -}; - -static const short yyrhs[] = { 17, - 0, 17, 3, 17, 12, 17, 0, 17, 4, 17, - 0, 17, 5, 17, 0, 17, 6, 17, 0, 17, - 7, 17, 0, 17, 8, 17, 0, 17, 9, 17, - 0, 10, 17, 0, 13, 0, 11, 0, 14, 17, - 15, 0 -}; - -#endif - -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 178, 186, 190, 194, 198, 202, 206, 210, 214, 218, - 222, 227 -}; -#endif - - -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","'?'","'|'", -"'&'","EQUOP2","CMPOP2","ADDOP2","MULOP2","'!'","NUMBER","':'","'n'","'('","')'", -"start","exp", NULL -}; -#endif - -static const short yyr1[] = { 0, - 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17 -}; - -static const short yyr2[] = { 0, - 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, - 1, 3 -}; - -static const short yydefact[] = { 0, - 0, 11, 10, 0, 1, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 12, 0, 3, 4, 5, 6, - 7, 8, 0, 2, 0, 0, 0 -}; - -static const short yydefgoto[] = { 25, - 5 -}; - -static const short yypact[] = { -9, - -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, -9, - -9, -9, -9, -9,-32768, 24, 39, 43, 16, 26, - -3,-32768, -9, 34, 21, 53,-32768 -}; - -static const short yypgoto[] = {-32768, - -1 -}; - - -#define YYLAST 53 - - -static const short yytable[] = { 6, - 1, 2, 7, 3, 4, 14, 16, 17, 18, 19, - 20, 21, 22, 8, 9, 10, 11, 12, 13, 14, - 26, 24, 12, 13, 14, 15, 8, 9, 10, 11, - 12, 13, 14, 13, 14, 23, 8, 9, 10, 11, - 12, 13, 14, 10, 11, 12, 13, 14, 11, 12, - 13, 14, 27 -}; - -static const short yycheck[] = { 1, - 10, 11, 4, 13, 14, 9, 8, 9, 10, 11, - 12, 13, 14, 3, 4, 5, 6, 7, 8, 9, - 0, 23, 7, 8, 9, 15, 3, 4, 5, 6, - 7, 8, 9, 8, 9, 12, 3, 4, 5, 6, - 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, - 8, 9, 0 -}; -#define YYPURE 1 - -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/home/haible/gnu/arch/linuxlibc6/share/bison.simple" -/* This file comes from bison-1.28. */ - -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 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. */ - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc -#endif - -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ - -#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 - -#ifndef YYPURE -#define YYLEX yylex() -#endif - -#ifdef YYPURE -#ifdef YYLSP_NEEDED -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval, &yylloc) -#endif -#else /* not YYLSP_NEEDED */ -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval) -#endif -#endif /* not YYLSP_NEEDED */ -#endif - -/* If nonreentrant, generate the variables here */ - -#ifndef YYPURE - -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ - -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ -#endif - -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ - -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ -#endif - -/* YYINITDEPTH indicates the initial size of the parser's stacks */ - -#ifndef YYINITDEPTH -#define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ - -#if YYMAXDEPTH == 0 -#undef YYMAXDEPTH -#endif - -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 -#endif - -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ - -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; -{ - register char *f = from; - register char *t = to; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#else /* __cplusplus */ - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (char *to, char *from, unsigned int count) -{ - register char *t = to; - register char *f = from; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#endif -#endif - -#line 217 "/home/haible/gnu/arch/linuxlibc6/share/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 -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -#ifdef YYPARSE_PARAM -int yyparse (void *); -#else -int yyparse (void); -#endif -#endif - -int -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - register int yystate; - register int yyn; - register short *yyssp; - register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ - - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ - -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else -#define YYPOPSTACK (yyvsp--, yyssp--) -#endif - - int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; - -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif - - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ - - int yylen; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif - - 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 - 1; - yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif - -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: - - *++yyssp = yystate; - - if (yyssp >= yyss + yystacksize - 1) - { - /* 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; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif - - /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; - -#ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* 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, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif - - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif -#else /* no yyoverflow */ - /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 2; - } - yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) - yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif -#endif /* no yyoverflow */ - - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - - if (yyssp >= yyss + yystacksize - 1) - YYABORT; - } - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif - - goto 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) - { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif - 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 */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif - } - else - { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (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 - fprintf (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. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; - - yystate = yyn; - goto yynewstate; - -/* Do the default action for the current state. */ -yydefault: - - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - -/* Do a reduction. yyn is the number of a rule to reduce with. */ -yyreduce: - yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ - -#if YYDEBUG != 0 - if (yydebug) - { - int i; - - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif - - - switch (yyn) { - -case 1: -#line 179 "plural.y" -{ - if (yyvsp[0].exp == NULL) - YYABORT; - ((struct parse_args *) arg)->res = yyvsp[0].exp; - ; - break;} -case 2: -#line 187 "plural.y" -{ - yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 3: -#line 191 "plural.y" -{ - yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 4: -#line 195 "plural.y" -{ - yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 5: -#line 199 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 6: -#line 203 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 7: -#line 207 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 8: -#line 211 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 9: -#line 215 "plural.y" -{ - yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); - ; - break;} -case 10: -#line 219 "plural.y" -{ - yyval.exp = new_exp_0 (var); - ; - break;} -case 11: -#line 223 "plural.y" -{ - if ((yyval.exp = new_exp_0 (num)) != NULL) - yyval.exp->val.num = yyvsp[0].num; - ; - break;} -case 12: -#line 228 "plural.y" -{ - yyval.exp = yyvsp[-1].exp; - ; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 543 "/home/haible/gnu/arch/linuxlibc6/share/bison.simple" - - yyvsp -= yylen; - yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - - *++yyvsp = yyval; - -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#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 */ - - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ - { - ++yynerrs; - -#ifdef YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (yyn > YYFLAG && yyn < YYLAST) - { - int size = 0; - char *msg; - int x, count; - - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) - { - strcpy(msg, "parse error"); - - if (count < 5) - { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; - } - } - yyerror(msg); - free(msg); - } - else - yyerror ("parse error; also virtual memory exceeded"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror("parse error"); - } - - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ - - 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; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif - - 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. */ - -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; -#endif - -yyerrpop: /* pop the current state because it cannot handle the error token */ - - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - -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; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - yystate = yyn; - goto yynewstate; - - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 1; -} -#line 233 "plural.y" - - -void -internal_function -FREE_EXPRESSION (exp) - struct expression *exp; -{ - if (exp == NULL) - return; - - /* Handle the recursive case. */ - switch (exp->nargs) - { - case 3: - FREE_EXPRESSION (exp->val.args[2]); - /* FALLTHROUGH */ - case 2: - FREE_EXPRESSION (exp->val.args[1]); - /* FALLTHROUGH */ - case 1: - FREE_EXPRESSION (exp->val.args[0]); - /* FALLTHROUGH */ - default: - break; - } - - free (exp); -} - - -static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; -{ - const char *exp = *pexp; - int result; - - while (1) - { - if (exp[0] == '\0') - { - *pexp = exp; - return YYEOF; - } - - if (exp[0] != ' ' && exp[0] != '\t') - break; - - ++exp; - } - - result = *exp++; - switch (result) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - unsigned long int n = result - '0'; - while (exp[0] >= '0' && exp[0] <= '9') - { - n *= 10; - n += exp[0] - '0'; - ++exp; - } - lval->num = n; - result = NUMBER; - } - break; - - case '=': - if (exp[0] == '=') - { - ++exp; - lval->op = equal; - result = EQUOP2; - } - else - result = YYERRCODE; - break; - - case '!': - if (exp[0] == '=') - { - ++exp; - lval->op = not_equal; - result = EQUOP2; - } - break; - - case '&': - case '|': - if (exp[0] == result) - ++exp; - else - result = YYERRCODE; - break; - - case '<': - if (exp[0] == '=') - { - ++exp; - lval->op = less_or_equal; - } - else - lval->op = less_than; - result = CMPOP2; - break; - - case '>': - if (exp[0] == '=') - { - ++exp; - lval->op = greater_or_equal; - } - else - lval->op = greater_than; - result = CMPOP2; - break; - - case '*': - lval->op = mult; - result = MULOP2; - break; - - case '/': - lval->op = divide; - result = MULOP2; - break; - - case '%': - lval->op = module; - result = MULOP2; - break; - - case '+': - lval->op = plus; - result = ADDOP2; - break; - - case '-': - lval->op = minus; - result = ADDOP2; - break; - - case 'n': - case '?': - case ':': - case '(': - case ')': - /* Nothing, just return the character. */ - break; - - case ';': - case '\n': - case '\0': - /* Be safe and let the user call this function again. */ - --exp; - result = YYEOF; - break; - - default: - result = YYERRCODE; -#if YYDEBUG != 0 - --exp; -#endif - break; - } - - *pexp = exp; - - return result; -} - - -static void -yyerror (str) - const char *str; -{ - /* Do nothing. We don't print error messages here. */ -} diff --git a/intl/plural.y b/intl/plural.y deleted file mode 100644 index be049a6..0000000 --- a/intl/plural.y +++ /dev/null @@ -1,413 +0,0 @@ -%{ -/* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 2000. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* The bison generated parser uses alloca. AIX 3 forces us to put this - declaration at the beginning of the file. The declaration in bison's - skeleton file comes too late. This must come before - because may include arbitrary system headers. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "gettextP.h" - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define FREE_EXPRESSION __gettext_free_exp -#else -# define FREE_EXPRESSION gettext_free_exp__ -# define __gettextparse gettextparse__ -#endif - -#define YYLEX_PARAM &((struct parse_args *) arg)->cp -#define YYPARSE_PARAM arg -%} -%pure_parser -%expect 10 - -%union { - unsigned long int num; - enum operator op; - struct expression *exp; -} - -%{ -/* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); - -/* Allocation of expressions. */ - -static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; -{ - int i; - struct expression *newp; - - /* If any of the argument could not be malloc'ed, just return NULL. */ - for (i = nargs - 1; i >= 0; i--) - if (args[i] == NULL) - goto fail; - - /* Allocate a new expression. */ - newp = (struct expression *) malloc (sizeof (*newp)); - if (newp != NULL) - { - newp->nargs = nargs; - newp->operation = op; - for (i = nargs - 1; i >= 0; i--) - newp->val.args[i] = args[i]; - return newp; - } - - fail: - for (i = nargs - 1; i >= 0; i--) - FREE_EXPRESSION (args[i]); - - return NULL; -} - -static inline struct expression * -new_exp_0 (op) - enum operator op; -{ - return new_exp (0, op, NULL); -} - -static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; -{ - struct expression *args[1]; - - args[0] = right; - return new_exp (1, op, args); -} - -static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; -{ - struct expression *args[2]; - - args[0] = left; - args[1] = right; - return new_exp (2, op, args); -} - -static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; -{ - struct expression *args[3]; - - args[0] = bexp; - args[1] = tbranch; - args[2] = fbranch; - return new_exp (3, op, args); -} - -%} - -/* This declares that all operators have the same associativity and the - precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. - There is no unary minus and no bitwise operators. - Operators with the same syntactic behaviour have been merged into a single - token, to save space in the array generated by bison. */ -%right '?' /* ? */ -%left '|' /* || */ -%left '&' /* && */ -%left EQUOP2 /* == != */ -%left CMPOP2 /* < > <= >= */ -%left ADDOP2 /* + - */ -%left MULOP2 /* * / % */ -%right '!' /* ! */ - -%token EQUOP2 CMPOP2 ADDOP2 MULOP2 -%token NUMBER -%type exp - -%% - -start: exp - { - if ($1 == NULL) - YYABORT; - ((struct parse_args *) arg)->res = $1; - } - ; - -exp: exp '?' exp ':' exp - { - $$ = new_exp_3 (qmop, $1, $3, $5); - } - | exp '|' exp - { - $$ = new_exp_2 (lor, $1, $3); - } - | exp '&' exp - { - $$ = new_exp_2 (land, $1, $3); - } - | exp EQUOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp CMPOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp ADDOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp MULOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | '!' exp - { - $$ = new_exp_1 (lnot, $2); - } - | 'n' - { - $$ = new_exp_0 (var); - } - | NUMBER - { - if (($$ = new_exp_0 (num)) != NULL) - $$->val.num = $1; - } - | '(' exp ')' - { - $$ = $2; - } - ; - -%% - -void -internal_function -FREE_EXPRESSION (exp) - struct expression *exp; -{ - if (exp == NULL) - return; - - /* Handle the recursive case. */ - switch (exp->nargs) - { - case 3: - FREE_EXPRESSION (exp->val.args[2]); - /* FALLTHROUGH */ - case 2: - FREE_EXPRESSION (exp->val.args[1]); - /* FALLTHROUGH */ - case 1: - FREE_EXPRESSION (exp->val.args[0]); - /* FALLTHROUGH */ - default: - break; - } - - free (exp); -} - - -static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; -{ - const char *exp = *pexp; - int result; - - while (1) - { - if (exp[0] == '\0') - { - *pexp = exp; - return YYEOF; - } - - if (exp[0] != ' ' && exp[0] != '\t') - break; - - ++exp; - } - - result = *exp++; - switch (result) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - unsigned long int n = result - '0'; - while (exp[0] >= '0' && exp[0] <= '9') - { - n *= 10; - n += exp[0] - '0'; - ++exp; - } - lval->num = n; - result = NUMBER; - } - break; - - case '=': - if (exp[0] == '=') - { - ++exp; - lval->op = equal; - result = EQUOP2; - } - else - result = YYERRCODE; - break; - - case '!': - if (exp[0] == '=') - { - ++exp; - lval->op = not_equal; - result = EQUOP2; - } - break; - - case '&': - case '|': - if (exp[0] == result) - ++exp; - else - result = YYERRCODE; - break; - - case '<': - if (exp[0] == '=') - { - ++exp; - lval->op = less_or_equal; - } - else - lval->op = less_than; - result = CMPOP2; - break; - - case '>': - if (exp[0] == '=') - { - ++exp; - lval->op = greater_or_equal; - } - else - lval->op = greater_than; - result = CMPOP2; - break; - - case '*': - lval->op = mult; - result = MULOP2; - break; - - case '/': - lval->op = divide; - result = MULOP2; - break; - - case '%': - lval->op = module; - result = MULOP2; - break; - - case '+': - lval->op = plus; - result = ADDOP2; - break; - - case '-': - lval->op = minus; - result = ADDOP2; - break; - - case 'n': - case '?': - case ':': - case '(': - case ')': - /* Nothing, just return the character. */ - break; - - case ';': - case '\n': - case '\0': - /* Be safe and let the user call this function again. */ - --exp; - result = YYEOF; - break; - - default: - result = YYERRCODE; -#if YYDEBUG != 0 - --exp; -#endif - break; - } - - *pexp = exp; - - return result; -} - - -static void -yyerror (str) - const char *str; -{ - /* Do nothing. We don't print error messages here. */ -} diff --git a/intl/ref-add.sin b/intl/ref-add.sin deleted file mode 100644 index 167374e..0000000 --- a/intl/ref-add.sin +++ /dev/null @@ -1,31 +0,0 @@ -# Add this package to a list of references stored in a text file. -# -# Copyright (C) 2000 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. -# -# Written by Bruno Haible . -# -/^# Packages using this file: / { - s/# Packages using this file:// - ta - :a - s/ @PACKAGE@ / @PACKAGE@ / - tb - s/ $/ @PACKAGE@ / - :b - s/^/# Packages using this file:/ -} diff --git a/intl/ref-del.sin b/intl/ref-del.sin deleted file mode 100644 index 613cf37..0000000 --- a/intl/ref-del.sin +++ /dev/null @@ -1,26 +0,0 @@ -# Remove this package from a list of references stored in a text file. -# -# Copyright (C) 2000 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. -# -# Written by Bruno Haible . -# -/^# Packages using this file: / { - s/# Packages using this file:// - s/ @PACKAGE@ / / - s/^/# Packages using this file:/ -} diff --git a/intl/textdomain.c b/intl/textdomain.c deleted file mode 100644 index 2e420ad..0000000 --- a/intl/textdomain.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Implementation of the textdomain(3) function. - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_default_domain _nl_default_default_domain__ -# define _nl_current_default_domain _nl_current_default_domain__ -#endif - -/* @@ end of prolog @@ */ - -/* Name of the default text domain. */ -extern const char _nl_default_default_domain[]; - -/* Default text domain in which entries for gettext(3) are to be found. */ -extern const char *_nl_current_default_domain; - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define TEXTDOMAIN __textdomain -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define TEXTDOMAIN textdomain__ -#endif - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock) - -/* Set the current default message catalog to DOMAINNAME. - If DOMAINNAME is null, return the current default. - If DOMAINNAME is "", reset to the default of "messages". */ -char * -TEXTDOMAIN (domainname) - const char *domainname; -{ - char *new_domain; - char *old_domain; - - /* A NULL pointer requests the current setting. */ - if (domainname == NULL) - return (char *) _nl_current_default_domain; - - __libc_rwlock_wrlock (_nl_state_lock); - - old_domain = (char *) _nl_current_default_domain; - - /* If domain name is the null string set to default domain "messages". */ - if (domainname[0] == '\0' - || strcmp (domainname, _nl_default_default_domain) == 0) - { - _nl_current_default_domain = _nl_default_default_domain; - new_domain = (char *) _nl_current_default_domain; - } - else if (strcmp (domainname, old_domain) == 0) - /* This can happen and people will use it to signal that some - environment variable changed. */ - new_domain = old_domain; - else - { - /* If the following malloc fails `_nl_current_default_domain' - will be NULL. This value will be returned and so signals we - are out of core. */ -#if defined _LIBC || defined HAVE_STRDUP - new_domain = strdup (domainname); -#else - size_t len = strlen (domainname) + 1; - new_domain = (char *) malloc (len); - if (new_domain != NULL) - memcpy (new_domain, domainname, len); -#endif - - if (new_domain != NULL) - _nl_current_default_domain = new_domain; - } - - /* We use this possibility to signal a change of the loaded catalogs - since this is most likely the case and there is no other easy we - to do it. Do it only when the call was successful. */ - if (new_domain != NULL) - { - ++_nl_msg_cat_cntr; - - if (old_domain != new_domain && old_domain != _nl_default_default_domain) - free (old_domain); - } - - __libc_rwlock_unlock (_nl_state_lock); - - return new_domain; -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__textdomain, textdomain); -#endif diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index aa4d55a..0000000 --- a/lib/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -## Process this file with automake to produce Makefile.in -# $Id: Makefile.am,v 1.2.4.7 2001/02/11 11:50:09 guus Exp $ - -noinst_LIBRARIES = libvpn.a - -INCLUDES = @INCLUDES@ -I. -I$(top_builddir) -I$(top_srcdir)/intl - -libvpn_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c list.c avl_tree.c dropin.c - -libvpn_a_LIBADD = @LIBOBJS@ @ALLOCA@ -libvpn_a_DEPENDENCIES = $(libvpn_a_LIBADD) - -noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h dropin.h - -EXTRA_DIST = README diff --git a/lib/Makefile.in b/lib/Makefile.in deleted file mode 100644 index 0ae461d..0000000 --- a/lib/Makefile.in +++ /dev/null @@ -1,338 +0,0 @@ -# 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@ - -# $Id: Makefile.am,v 1.2.4.7 2001/02/11 11:50:09 guus Exp $ - -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 = : -host_alias = @host_alias@ -host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ - -INCLUDES = @INCLUDES@ -I. -I$(top_builddir) -I$(top_srcdir)/intl - -noinst_LIBRARIES = libvpn.a - -libvpn_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c list.c avl_tree.c dropin.c - -libvpn_a_LIBADD = @LIBOBJS@ @ALLOCA@ -libvpn_a_DEPENDENCIES = $(libvpn_a_LIBADD) - -noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h dropin.h - -EXTRA_DIST = README -subdir = lib -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -LIBRARIES = $(noinst_LIBRARIES) - -libvpn_a_AR = $(AR) cru -am_libvpn_a_OBJECTS = xmalloc.$(OBJEXT) pidfile.$(OBJEXT) \ - utils.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \ - list.$(OBJEXT) avl_tree.$(OBJEXT) dropin.$(OBJEXT) -libvpn_a_OBJECTS = $(am_libvpn_a_OBJECTS) - -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)/alloca.Po $(DEPDIR)/avl_tree.Po \ -@AMDEP_TRUE@ $(DEPDIR)/dropin.Po $(DEPDIR)/getopt.Po \ -@AMDEP_TRUE@ $(DEPDIR)/getopt1.Po $(DEPDIR)/list.Po \ -@AMDEP_TRUE@ $(DEPDIR)/malloc.Po $(DEPDIR)/memcmp.Po \ -@AMDEP_TRUE@ $(DEPDIR)/pidfile.Po $(DEPDIR)/realloc.Po \ -@AMDEP_TRUE@ $(DEPDIR)/utils.Po $(DEPDIR)/xmalloc.Po -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -CFLAGS = @CFLAGS@ -DIST_SOURCES = $(libvpn_a_SOURCES) -HEADERS = $(noinst_HEADERS) - -DIST_COMMON = README $(noinst_HEADERS) Makefile.am Makefile.in alloca.c \ - malloc.c memcmp.c realloc.c -SOURCES = $(libvpn_a_SOURCES) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && \ - CONFIG_HEADERS= CONFIG_LINKS= \ - CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status - -AR = ar - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libvpn.a: $(libvpn_a_OBJECTS) $(libvpn_a_DEPENDENCIES) - -rm -f libvpn.a - $(libvpn_a_AR) libvpn.a $(libvpn_a_OBJECTS) $(libvpn_a_LIBADD) - $(RANLIB) libvpn.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) core *.core - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/avl_tree.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dropin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/malloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memcmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pidfile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/realloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/xmalloc.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 $<` -CCDEPMODE = @CCDEPMODE@ -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 $(LIBRARIES) $(HEADERS) - -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-noinstLIBRARIES mostlyclean-am - -distclean: distclean-am - -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags - -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-compile mostlyclean-generic - -uninstall-am: uninstall-info-am - -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags 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-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am - -# 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/lib/README b/lib/README deleted file mode 100644 index d842e59..0000000 --- a/lib/README +++ /dev/null @@ -1 +0,0 @@ -The files in this directory were merely copied from fileutils 4.0. \ No newline at end of file diff --git a/lib/alloca.c b/lib/alloca.c deleted file mode 100644 index 10e5d65..0000000 --- a/lib/alloca.c +++ /dev/null @@ -1,494 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef emacs -# include "blockinput.h" -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -# ifndef alloca - -# ifdef emacs -# ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -# ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -# endif /* STACK_DIRECTION undefined */ -# endif /* static */ -# endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -# else -# define ADDRESS_FUNCTION(arg) &(arg) -# endif - -# if __STDC__ -typedef void *pointer; -# else -typedef char *pointer; -# endif - -# ifndef NULL -# define NULL 0 -# endif - -/* Different portions of Emacs need to call different versions of - malloc. The Emacs executable needs alloca to call xmalloc, because - ordinary malloc isn't protected from input signals. On the other - hand, the utilities in lib-src need alloca to call malloc; some of - them are very simple, and don't have an xmalloc routine. - - Non-Emacs programs expect this to call xmalloc. - - Callers below should use malloc. */ - -# ifndef emacs -# define malloc xmalloc -# endif -extern pointer malloc (); - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -# ifndef STACK_DIRECTION -# define STACK_DIRECTION 0 /* Direction unknown. */ -# endif - -# if STACK_DIRECTION != 0 - -# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -# else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -# define STACK_DIR stack_dir - -static void -find_stack_direction () -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -# endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -# ifndef ALIGN_SIZE -# define ALIGN_SIZE sizeof(double) -# endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -pointer -alloca (size) - unsigned size; -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -# if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -# endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -# ifdef emacs - BLOCK_INPUT; -# endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free ((pointer) hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -# ifdef emacs - UNBLOCK_INPUT; -# endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - register pointer new = malloc (sizeof (header) + size); - /* Address of header. */ - - ((header *) new)->h.next = last_alloca_header; - ((header *) new)->h.deep = depth; - - last_alloca_header = (header *) new; - - /* User storage begins just after header. */ - - return (pointer) ((char *) new + sizeof (header)); - } -} - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) - -# ifdef DEBUG_I00AFUNC -# include -# endif - -# ifndef CRAY_STACK -# define CRAY_STACK -# ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -# else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -# endif /* CRAY2 */ -# endif /* not CRAY_STACK */ - -# ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -# else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -# endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -# endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -# endif /* not CRAY2 */ -# endif /* CRAY */ - -# endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/lib/avl_tree.c b/lib/avl_tree.c deleted file mode 100644 index a4f0051..0000000 --- a/lib/avl_tree.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - avl_tree.c -- avl_ tree and linked list convenience - Copyright (C) 1998 Michael H. Buselli - 2000,2001 Ivo Timmermans , - 2000,2001 Guus Sliepen - 2000,2001 Wessel Dankers - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Original AVL tree library by Michael H. Buselli . - - Modified 2000-11-28 by Wessel Dankers to use counts - instead of depths, to add the ->next and ->prev and to generally obfuscate - the code. Mail me if you found a bug. - - Cleaned up and incorporated some of the ideas from the red-black tree - library for inclusion into tinc (http://tinc.nl.linux.org/) by - Guus Sliepen . - - $Id: avl_tree.c,v 1.1.2.8 2002/02/10 21:57:51 guus Exp $ -*/ - -#include -#include -#include - -#include "avl_tree.h" - -#ifdef AVL_COUNT -#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0) -#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left)) -#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right)) -#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1) -#endif - -#ifdef AVL_DEPTH -#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0) -#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left)) -#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right)) -#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1) -#endif - -#ifndef AVL_DEPTH -int lg(unsigned int u) -{ - int r = 1; - if (!u) - return 0; - if (u & 0xffff0000) - { - u >>= 16; - r += 16; - } - if (u & 0x0000ff00) - { - u >>= 8; - r += 8; - } - if (u & 0x000000f0) - { - u >>= 4; - r += 4; - } - if (u & 0x0000000c) - { - u >>= 2; - r += 2; - } - if (u & 0x00000002) - r++; - return r; -} -#endif - -/* Internal helper functions */ - -int avl_check_balance(avl_node_t *node) -{ -#ifdef AVL_DEPTH - int d; - d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node); - return d < -1 ? -1 : d > 1 ? 1 : 0; -#else -/* int d; - * d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node)); - * d = d<-1?-1:d>1?1:0; - */ - int pl, r; - - pl = lg(AVL_L_COUNT(node)); - r = AVL_R_COUNT(node); - - if (r >> pl + 1) - return 1; - if (pl < 2 || r >> pl - 2) - return 0; - return -1; -#endif -} - -void avl_rebalance(avl_tree_t *tree, avl_node_t *node) -{ - avl_node_t *child; - avl_node_t *gchild; - avl_node_t *parent; - avl_node_t **superparent; - - parent = node; - - while (node) - { - parent = node->parent; - - superparent = parent ? node == parent->left ? &parent->left : &parent->right : &tree->root; - - switch (avl_check_balance(node)) - { - case -1: - child = node->left; -#ifdef AVL_DEPTH - if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) { -#else - if (AVL_L_COUNT(child) >= AVL_R_COUNT(child)) - { -#endif - node->left = child->right; - if (node->left) - node->left->parent = node; - child->right = node; - node->parent = child; - *superparent = child; - child->parent = parent; -#ifdef AVL_COUNT - node->count = AVL_CALC_COUNT(node); - child->count = AVL_CALC_COUNT(child); -#endif -#ifdef AVL_DEPTH - node->depth = AVL_CALC_DEPTH(node); - child->depth = AVL_CALC_DEPTH(child); -#endif - } else - { - gchild = child->right; - node->left = gchild->right; - if (node->left) - node->left->parent = node; - child->right = gchild->left; - if (child->right) - child->right->parent = child; - gchild->right = node; - if (gchild->right) - gchild->right->parent = gchild; - gchild->left = child; - if (gchild->left) - gchild->left->parent = gchild; - *superparent = gchild; - gchild->parent = parent; -#ifdef AVL_COUNT - node->count = AVL_CALC_COUNT(node); - child->count = AVL_CALC_COUNT(child); - gchild->count = AVL_CALC_COUNT(gchild); -#endif -#ifdef AVL_DEPTH - node->depth = AVL_CALC_DEPTH(node); - child->depth = AVL_CALC_DEPTH(child); - gchild->depth = AVL_CALC_DEPTH(gchild); -#endif - } - break; - case 1: - child = node->right; -#ifdef AVL_DEPTH - if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) { -#else - if (AVL_R_COUNT(child) >= AVL_L_COUNT(child)) - { -#endif - node->right = child->left; - if (node->right) - node->right->parent = node; - child->left = node; - node->parent = child; - *superparent = child; - child->parent = parent; -#ifdef AVL_COUNT - node->count = AVL_CALC_COUNT(node); - child->count = AVL_CALC_COUNT(child); -#endif -#ifdef AVL_DEPTH - node->depth = AVL_CALC_DEPTH(node); - child->depth = AVL_CALC_DEPTH(child); -#endif - } else - { - gchild = child->left; - node->right = gchild->left; - if (node->right) - node->right->parent = node; - child->left = gchild->right; - if (child->left) - child->left->parent = child; - gchild->left = node; - if (gchild->left) - gchild->left->parent = gchild; - gchild->right = child; - if (gchild->right) - gchild->right->parent = gchild; - *superparent = gchild; - gchild->parent = parent; -#ifdef AVL_COUNT - node->count = AVL_CALC_COUNT(node); - child->count = AVL_CALC_COUNT(child); - gchild->count = AVL_CALC_COUNT(gchild); -#endif -#ifdef AVL_DEPTH - node->depth = AVL_CALC_DEPTH(node); - child->depth = AVL_CALC_DEPTH(child); - gchild->depth = AVL_CALC_DEPTH(gchild); -#endif - } - break; - default: -#ifdef AVL_COUNT - node->count = AVL_CALC_COUNT(node); -#endif -#ifdef AVL_DEPTH - node->depth = AVL_CALC_DEPTH(node); -#endif - } - node = parent; - } -} - -/* (De)constructors */ - -avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete) -{ - avl_tree_t *tree; - - tree = xmalloc_and_zero(sizeof(avl_tree_t)); - tree->compare = compare; - tree->delete = delete; - - return tree; -} - -void avl_free_tree(avl_tree_t *tree) -{ - free(tree); -} - -avl_node_t *avl_alloc_node(void) -{ - avl_node_t *node; - - node = xmalloc_and_zero(sizeof(avl_node_t)); - - return node; -} - -void avl_free_node(avl_tree_t *tree, avl_node_t *node) -{ - if(node->data && tree->delete) - tree->delete(node->data); - free(node); -} - -/* Searching */ - -void *avl_search(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - - node = avl_search_node(tree, data); - - return node?node->data:NULL; -} - -void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result) -{ - avl_node_t *node; - - node = avl_search_closest_node(tree, data, result); - - return node?node->data:NULL; -} - -void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - - node = avl_search_closest_smaller_node(tree, data); - - return node?node->data:NULL; -} - -void *avl_search_closest_greater(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - - node = avl_search_closest_greater_node(tree, data); - - return node?node->data:NULL; -} - -avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - int result; - - node = avl_search_closest_node(tree, data, &result); - - return result?NULL:node; -} - -avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, int *result) -{ - avl_node_t *node; - int c; - - node = tree->root; - - if (!node) - { - if(result) - *result = 0; - return NULL; - } - - for (;;) - { - c = tree->compare(data, node->data); - - if (c < 0) - { - if (node->left) - node = node->left; - else - { - if(result) - *result = -1; - break; - } - } - else if (c > 0) - { - if (node->right) - node = node->right; - else - { - if(result) - *result = 1; - break; - } - } - else - { - if(result) - *result = 0; - break; - } - } - - return node; -} - -avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - int result; - - node = avl_search_closest_node(tree, data, &result); - - if(result < 0) - node = node->prev; - - return node; -} - -avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data) -{ - avl_node_t *node; - int result; - - node = avl_search_closest_node(tree, data, &result); - - if(result > 0) - node = node->next; - - return node; -} - -/* Insertion and deletion */ - -avl_node_t *avl_insert(avl_tree_t *tree, void *data) -{ - avl_node_t *closest, *new; - int result; - - if (!tree->root) - { - new = avl_alloc_node(); - new->data = data; - avl_insert_top(tree, new); - } - else - { - closest = avl_search_closest_node(tree, data, &result); - switch(result) - { - case -1: - new = avl_alloc_node(); - new->data = data; - avl_insert_before(tree, closest, new); - break; - case 1: - new = avl_alloc_node(); - new->data = data; - avl_insert_after(tree, closest, new); - break; - default: - return NULL; - } - } - -#ifdef AVL_COUNT - new->count = 1; -#endif -#ifdef AVL_DEPTH - new->depth = 1; -#endif - - return new; -} - -avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node) -{ - avl_node_t *closest; - int result; - - if (!tree->root) - avl_insert_top(tree, node); - else - { - closest = avl_search_closest_node(tree, node->data, &result); - switch(result) - { - case -1: - avl_insert_before(tree, closest, node); - break; - case 1: - avl_insert_after(tree, closest, node); - break; - case 0: - return NULL; - } - } - -#ifdef AVL_COUNT - node->count = 1; -#endif -#ifdef AVL_DEPTH - node->depth = 1; -#endif - - return node; -} - -void avl_insert_top(avl_tree_t *tree, avl_node_t *node) -{ - node->prev = node->next = node->parent = NULL; - tree->head = tree->tail = tree->root = node; -} - -void avl_insert_before(avl_tree_t *tree, avl_node_t *before, avl_node_t *node) -{ - if (!before) - return tree->tail ? avl_insert_after(tree, tree->tail, node) : avl_insert_top(tree, node); - - node->next = before; - node->parent = before; - node->prev = before->prev; - - if(before->left) - return avl_insert_after(tree, before->prev, node); - - if (before->prev) - before->prev->next = node; - else - tree->head = node; - - before->prev = node; - before->left = node; - - avl_rebalance(tree, before->parent); -} - -void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node) -{ - if (!after) - return tree->head ? avl_insert_before(tree, tree->head, node) : avl_insert_top(tree, node); - - if(after->right) - return avl_insert_before(tree, after->next, node); - - node->prev = after; - node->parent = after; - node->next = after->next; - - if (after->next) - after->next->prev = node; - else - tree->tail = node; - - after->next = node; - after->right = node; - - avl_rebalance(tree, after->parent); -} - -avl_node_t *avl_unlink(avl_tree_t *tree, void *data) -{ - avl_node_t *node; - - node = avl_search_node(tree, data); - - if(node) - avl_unlink_node(tree, node); - - return node; -} - -void avl_unlink_node(avl_tree_t *tree, avl_node_t *node) -{ - avl_node_t *parent; - avl_node_t **superparent; - avl_node_t *subst, *left, *right; - avl_node_t *balnode; - - if (node->prev) - node->prev->next = node->next; - else - tree->head = node->next; - if (node->next) - node->next->prev = node->prev; - else - tree->tail = node->prev; - - parent = node->parent; - - superparent = parent ? node == parent->left ? &parent->left : &parent->right : &tree->root; - - left = node->left; - right = node->right; - if (!left) - { - *superparent = right; - if (right) - right->parent = parent; - balnode = parent; - } else if (!right) - { - *superparent = left; - left->parent = parent; - balnode = parent; - } else - { - subst = node->prev; - if (subst == left) - { - balnode = subst; - } else - { - balnode = subst->parent; - balnode->right = subst->left; - if (balnode->right) - balnode->right->parent = balnode; - subst->left = left; - left->parent = subst; - } - subst->right = right; - subst->parent = parent; - right->parent = subst; - *superparent = subst; - } - - avl_rebalance(tree, balnode); - - node->next = node->prev = node->parent = node->left = node->right = NULL; - -#ifdef AVL_COUNT - node->count = 0; -#endif -#ifdef AVL_DEPTH - node->depth = 0; -#endif -} - -void avl_delete_node(avl_tree_t *tree, avl_node_t *node) -{ - avl_unlink_node(tree, node); - avl_free_node(tree, node); -} - -void avl_delete(avl_tree_t *tree, void *data) -{ - avl_node_t *node; - - node = avl_search_node(tree, data); - - if (node) - avl_delete_node(tree, node); -} - -/* Fast tree cleanup */ - -void avl_delete_tree(avl_tree_t *tree) -{ - avl_node_t *node, *next; - - for(node = tree->root; node; node = next) - { - next = node->next; - avl_free_node(tree, node); - } - - avl_free_tree(tree); -} - -/* Tree walking */ - -void avl_foreach(avl_tree_t *tree, avl_action_t action) -{ - avl_node_t *node, *next; - - for(node = tree->head; node; node = next) - { - next = node->next; - action(node->data); - } -} - -void avl_foreach_node(avl_tree_t *tree, avl_action_t action) -{ - avl_node_t *node, *next; - - for(node = tree->head; node; node = next) - { - next = node->next; - action(node); - } -} - -/* Indexing */ - -#ifdef AVL_COUNT -unsigned int avl_count(avl_tree_t *tree) -{ - return AVL_NODE_COUNT(tree->root); -} - -avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index) -{ - avl_node_t *node; - unsigned int c; - - node = tree->root; - - while (node) - { - c = AVL_L_COUNT(node); - - if (index < c) - { - node = node->left; - } else if (index > c) - { - node = node->right; - index -= c + 1; - } else - { - return node; - } - } - - return NULL; -} - -unsigned int avl_index(const avl_node_t *node) -{ - avl_node_t *next; - unsigned int index; - - index = AVL_L_COUNT(node); - - while ((next = node->parent)) - { - if (node == next->right) - index += AVL_L_COUNT(next) + 1; - node = next; - } - - return index; -} -#endif -#ifdef AVL_DEPTH -unsigned int avl_depth(avl_tree_t *tree) -{ - return AVL_NODE_DEPTH(tree->root); -} -#endif diff --git a/lib/avl_tree.h b/lib/avl_tree.h deleted file mode 100644 index d1ad618..0000000 --- a/lib/avl_tree.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - avl_tree.h -- header file for avl_tree.c - Copyright (C) 1998 Michael H. Buselli - 2000,2001 Ivo Timmermans , - 2000,2001 Guus Sliepen - 2000,2001 Wessel Dankers - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Original AVL tree library by Michael H. Buselli . - - Modified 2000-11-28 by Wessel Dankers to use counts - instead of depths, to add the ->next and ->prev and to generally obfuscate - the code. Mail me if you found a bug. - - Cleaned up and incorporated some of the ideas from the red-black tree - library for inclusion into tinc (http://tinc.nl.linux.org/) by - Guus Sliepen . - - $Id: avl_tree.h,v 1.1.2.4 2001/02/06 10:13:22 guus Exp $ -*/ - - -#ifndef __AVL_TREE_H__ -#define __AVL_TREE_H__ - -#ifndef AVL_DEPTH - #ifndef AVL_COUNT - #define AVL_DEPTH - #endif -#endif - -typedef struct avl_node_t { - - /* Linked list part */ - - struct avl_node_t *next; - struct avl_node_t *prev; - - /* Tree part */ - - struct avl_node_t *parent; - struct avl_node_t *left; - struct avl_node_t *right; - -#ifdef AVL_COUNT - unsigned int count; -#endif -#ifdef AVL_DEPTH - unsigned char depth; -#endif - - /* Payload */ - - void *data; - -} avl_node_t; - -typedef int (*avl_compare_t) (const void *, const void *); -typedef void (*avl_action_t) (const void *); -typedef void (*avl_action_node_t) (const avl_node_t *); - -typedef struct avl_tree_t { - - /* Linked list part */ - - avl_node_t *head; - avl_node_t *tail; - - /* Tree part */ - - avl_node_t *root; - - avl_compare_t compare; - avl_action_t delete; - -} avl_tree_t; - -/* (De)constructors */ - -extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t); -extern void avl_free_tree(avl_tree_t *); - -extern avl_node_t *avl_alloc_node(void); -extern void avl_free_node(avl_tree_t *tree, avl_node_t *); - -/* Insertion and deletion */ - -extern avl_node_t *avl_insert(avl_tree_t *, void *); -extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *); - -extern void avl_insert_top(avl_tree_t *, avl_node_t *); -extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *); -extern void avl_insert_after(avl_tree_t *, avl_node_t *, avl_node_t *); - -extern avl_node_t *avl_unlink(avl_tree_t *, void *); -extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *); -extern void avl_delete(avl_tree_t *, void *); -extern void avl_delete_node(avl_tree_t *, avl_node_t *); - -/* Fast tree cleanup */ - -extern void avl_delete_tree(avl_tree_t *); - -/* Searching */ - -extern void *avl_search(const avl_tree_t *, const void *); -extern void *avl_search_closest(const avl_tree_t *, const void *, int *); -extern void *avl_search_closest_smaller(const avl_tree_t *, const void *); -extern void *avl_search_closest_greater(const avl_tree_t *, const void *); - -extern avl_node_t *avl_search_node(const avl_tree_t *, const void *); -extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *); -extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *, const void *); -extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const void *); - -/* Tree walking */ - -extern void avl_foreach(avl_tree_t *, avl_action_t); -extern void avl_foreach_node(avl_tree_t *, avl_action_t); - -/* Indexing */ - -#ifdef AVL_COUNT -extern unsigned int avl_count(avl_tree_t *); -extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int); -extern unsigned int avl_index(const avl_node_t *); -#endif -#ifdef AVL_DEPTH -extern unsigned int avl_depth(avl_tree_t *); -#endif - -#endif /* __AVL_TREE_H__ */ diff --git a/lib/dropin.c b/lib/dropin.c deleted file mode 100644 index 66aaa31..0000000 --- a/lib/dropin.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - dropin.c -- a set of drop-in replacements for libc functions - Copyright (C) 2000,2001 Ivo Timmermans , - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: dropin.c,v 1.1.2.8 2002/02/10 21:57:51 guus Exp $ -*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#ifndef HAVE_DAEMON -/* - Replacement for the daemon() function. - - The daemon() function is for programs wishing to detach themselves - from the controlling terminal and run in the background as system - daemons. - - Unless the argument nochdir is non-zero, daemon() changes the - current working directory to the root (``/''). - - Unless the argument noclose is non-zero, daemon() will redirect - standard input, standard output and standard error to /dev/null. -*/ -int daemon(int nochdir, int noclose) -{ - pid_t pid; - int fd; - - pid = fork(); - - /* Check if forking failed */ - if(pid < 0) - { - perror("fork"); - exit(-1); - } - - /* If we are the parent, terminate */ - if(pid) - exit(0); - - /* Detach by becoming the new process group leader */ - if(setsid() < 0) - { - perror("setsid"); - return -1; - } - - /* Change working directory to the root (to avoid keeping mount - points busy) */ - if(!nochdir) - { - chdir("/"); - } - - /* Redirect stdin/out/err to /dev/null */ - if(!noclose) - { - fd = open("/dev/null", O_RDWR); - - if(fd < 0) - { - perror("opening /dev/null"); - return -1; - } - else - { - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - } - } - - return 0; -} -#endif - - - - -#ifndef HAVE_GET_CURRENT_DIR_NAME -/* - Replacement for the GNU get_current_dir_name function: - - get_current_dir_name will malloc(3) an array big enough to hold the - current directory name. If the environment variable PWD is set, and - its value is correct, then that value will be returned. -*/ -char *get_current_dir_name(void) -{ - size_t size; - char *buf; - char *r; - - /* Start with 100 bytes. If this turns out to be insufficient to - contain the working directory, double the size. */ - size = 100; - buf = xmalloc(size); - - errno = 0; /* Success */ - r = getcwd(buf, size); - /* getcwd returns NULL and sets errno to ERANGE if the bufferspace - is insufficient to contain the entire working directory. */ - while(r == NULL && errno == ERANGE) - { - free(buf); - size <<= 1; /* double the size */ - buf = xmalloc(size); - r = getcwd(buf, size); - } - - return buf; -} -#endif - -#ifndef HAVE_ASPRINTF -int asprintf(char **buf, const char *fmt, ...) -{ - int status; - va_list ap; - int len; - - len = 4096; - *buf = xmalloc(len); - - va_start(ap, fmt); - status = vsnprintf (*buf, len, fmt, ap); - va_end (ap); - - if(status >= 0) - *buf = xrealloc(*buf, status); - - if(status > len-1) - { - len = status; - va_start(ap, fmt); - status = vsnprintf (*buf, len, fmt, ap); - va_end (ap); - } - - return status; -} -#endif diff --git a/lib/dropin.h b/lib/dropin.h deleted file mode 100644 index ad66d99..0000000 --- a/lib/dropin.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - dropin.h -- header file for dropin.c - Copyright (C) 2000,2001 Ivo Timmermans , - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: dropin.h,v 1.1.2.6 2002/02/10 21:57:51 guus Exp $ -*/ - -#ifndef __DROPIN_H__ -#define __DROPIN_H__ - -#ifndef HAVE_DAEMON -extern int daemon(int, int); -#endif - -#ifndef HAVE_GET_CURRENT_DIR_NAME -extern char* get_current_dir_name(void); -#endif - -#ifndef HAVE_ASPRINTF -extern int asprintf(char **, const char *, ...); -#endif - -#endif /* __DROPIN_H__ */ diff --git a/lib/getopt.c b/lib/getopt.c deleted file mode 100644 index 300f86d..0000000 --- a/lib/getopt.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 - Free Software Foundation, Inc. - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -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. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in . - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 -#include -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -#include -#include -#endif /* GNU C library. */ - -#ifdef VMS -#include -#if HAVE_STRING_H - 0 -#include -#endif -#endif - -#if defined (WIN32) && !defined (__CYGWIN32__) -/* It's not Unix, really. See? Capital letters. */ -#include -#define getpid() GetCurrentProcessId() -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -#ifdef HAVE_LIBINTL_H -# include -# define _(msgid) gettext (msgid) -#else -# define _(msgid) (msgid) -#endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = NULL; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -#include -#define my_index strchr -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#if !defined (__STDC__) || !__STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -extern pid_t __libc_pid; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -text_set_element (__libc_subinit, store_args_and_env); - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined (__STDC__) && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); - memset (&new_str[nonoption_flags_max_len], '\0', - top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined (__STDC__) && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - { - memcpy (__getopt_nonoption_flags, orig_str, len); - memset (&__getopt_nonoption_flags[len], '\0', - nonoption_flags_max_len - len); - } - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#ifdef _LIBC -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/lib/getopt.h b/lib/getopt.h deleted file mode 100644 index 69256fd..0000000 --- a/lib/getopt.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -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. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -#if defined (__STDC__) && __STDC__ - const char *name; -#else - char *name; -#endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -#if defined (__STDC__) && __STDC__ -#ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* not __GNU_LIBRARY__ */ -extern int getopt (); -#endif /* __GNU_LIBRARY__ */ -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); -#else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/lib/list.c b/lib/list.c deleted file mode 100644 index cb2d4d2..0000000 --- a/lib/list.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - list.c -- functions to deal with double linked lists - Copyright (C) 2000,2001 Ivo Timmermans - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: list.c,v 1.1.2.10 2002/03/27 15:01:16 guus Exp $ -*/ - -#include "config.h" - -#include - -#include -#include - -#include "list.h" - -/* (De)constructors */ - -list_t *list_alloc(list_action_t delete) -{ - list_t *list; - - list = xmalloc_and_zero(sizeof(list_t)); - list->delete = delete; - - return list; -} - -void list_free(list_t *list) -{ - free(list); -} - -list_node_t *list_alloc_node(void) -{ - list_node_t *node; - - node = xmalloc_and_zero(sizeof(list_node_t)); - - return node; -} - -void list_free_node(list_t *list, list_node_t *node) -{ - if(node->data && list->delete) - list->delete(node->data); - - free(node); -} - -/* Insertion and deletion */ - -list_node_t *list_insert_head(list_t *list, void *data) -{ - list_node_t *node; - - node = list_alloc_node(); - - node->data = data; - node->prev = NULL; - node->next = list->head; - list->head = node; - - if(node->next) - node->next->prev = node; - else - list->tail = node; - - list->count++; - - return node; -} - -list_node_t *list_insert_tail(list_t *list, void *data) -{ - list_node_t *node; - - node = list_alloc_node(); - - node->data = data; - node->next = NULL; - node->prev = list->tail; - list->tail = node; - - if(node->prev) - node->prev->next = node; - else - list->head = node; - - list->count++; - - return node; -} - -void list_unlink_node(list_t *list, list_node_t *node) -{ - if(node->prev) - node->prev->next = node->next; - else - list->head = node->next; - - if(node->next) - node->next->prev = node->prev; - else - list->tail = node->prev; - - list->count--; -} - -void list_delete_node(list_t *list, list_node_t *node) -{ - list_unlink_node(list, node); - list_free_node(list, node); -} - -void list_delete_head(list_t *list) -{ - list_delete_node(list, list->head); -} - -void list_delete_tail(list_t *list) -{ - list_delete_node(list, list->tail); -} - -/* Head/tail lookup */ - -void *list_get_head(list_t *list) -{ - if(list->head) - return list->head->data; - else - return NULL; -} - -void *list_get_tail(list_t *list) -{ - if(list->tail) - return list->tail->data; - else - return NULL; -} - -/* Fast list deletion */ - -void list_delete_list(list_t *list) -{ - list_node_t *node, *next; - - for(node = list->head; node; node = next) - { - next = node->next; - list_free_node(list, node); - } - - list_free(list); -} - -/* Traversing */ - -void list_foreach_node(list_t *list, list_action_node_t action) -{ - list_node_t *node, *next; - - for(node = list->head; node; node = next) - { - next = node->next; - action(node); - } -} - -void list_foreach(list_t *list, list_action_t action) -{ - list_node_t *node, *next; - - for(node = list->head; node; node = next) - { - next = node->next; - if(node->data) - action(node->data); - } -} diff --git a/lib/list.h b/lib/list.h deleted file mode 100644 index 3e1735b..0000000 --- a/lib/list.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - list.h -- header file for list.c - Copyright (C) 2000,2001 Ivo Timmermans - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: list.h,v 1.1.2.5 2002/03/27 15:01:16 guus Exp $ -*/ - -#ifndef __TINC_LIST_H__ -#define __TINC_LIST_H__ - -typedef struct list_node_t -{ - struct list_node_t *prev; - struct list_node_t *next; - - /* Payload */ - - void *data; -} list_node_t; - -typedef void (*list_action_t) (const void *); -typedef void (*list_action_node_t) (const list_node_t *); - -typedef struct list_t -{ - list_node_t *head; - list_node_t *tail; - int count; - - /* Callbacks */ - - list_action_t delete; -} list_t; - -/* (De)constructors */ - -extern list_t *list_alloc(list_action_t); -extern void list_free(list_t *); -extern list_node_t *list_alloc_node(void); -extern void list_free_node(list_t *, list_node_t *); - -/* Insertion and deletion */ - -extern list_node_t *list_insert_head(list_t *, void *); -extern list_node_t *list_insert_tail(list_t *, void *); - -extern void list_unlink_node(list_t *, list_node_t *); -extern void list_delete_node(list_t *, list_node_t *); - -extern void list_delete_head(list_t *); -extern void list_delete_tail(list_t *); - -/* Head/tail lookup */ - -extern void *list_get_head(list_t *); -extern void *list_get_tail(list_t *); - -/* Fast list deletion */ - -extern void list_delete_list(list_t *); - -/* Traversing */ - -extern void list_foreach(list_t *, list_action_t); -extern void list_foreach_node(list_t *, list_action_node_t); - -#endif /* __TINC_LIST_H__ */ diff --git a/lib/malloc.c b/lib/malloc.c deleted file mode 100644 index b859e58..0000000 --- a/lib/malloc.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Work around bug on some systems where malloc (0) fails. - Copyright (C) 1997 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. */ - -/* written by Jim Meyering */ - -#if HAVE_CONFIG_H -# include -#endif -#undef malloc - -#include - -char *malloc (); - -/* Allocate an N-byte block of memory from the heap. - If N is zero, allocate a 1-byte block. */ - -char * -rpl_malloc (n) - size_t n; -{ - if (n == 0) - n = 1; - return malloc (n); -} diff --git a/lib/memcmp.c b/lib/memcmp.c deleted file mode 100644 index 1226947..0000000 --- a/lib/memcmp.c +++ /dev/null @@ -1,391 +0,0 @@ -/* Copyright (C) 1991, 1993, 1995, 1997, 1998 Free Software Foundation, Inc. - Contributed by Torbjorn Granlund (tege@sics.se). - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - 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. */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#undef __ptr_t -#if defined __cplusplus || (defined __STDC__ && __STDC__) -# define __ptr_t void * -#else /* Not C++ or ANSI C. */ -# undef const -# define const -# define __ptr_t char * -#endif /* C++ or ANSI C. */ - -#ifndef __P -# if defined __GNUC__ || (defined __STDC__ && __STDC__) -# define __P(args) args -# else -# define __P(args) () -# endif /* GCC. */ -#endif /* Not __P. */ - -#if defined HAVE_STRING_H || defined _LIBC -# include -#endif - -#undef memcmp - -#ifdef _LIBC - -# include - -#else /* Not in the GNU C library. */ - -# include - -/* Type to use for aligned memory operations. - This should normally be the biggest type supported by a single load - and store. Must be an unsigned type. */ -# define op_t unsigned long int -# define OPSIZ (sizeof(op_t)) - -/* Threshold value for when to enter the unrolled loops. */ -# define OP_T_THRES 16 - -/* Type to use for unaligned operations. */ -typedef unsigned char byte; - -# ifndef WORDS_BIGENDIAN -# define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) -# else -# define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) -# endif - -#endif /* In the GNU C library. */ - -#ifdef WORDS_BIGENDIAN -# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) -#else -# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) -#endif - -/* BE VERY CAREFUL IF YOU CHANGE THIS CODE! */ - -/* The strategy of this memcmp is: - - 1. Compare bytes until one of the block pointers is aligned. - - 2. Compare using memcmp_common_alignment or - memcmp_not_common_alignment, regarding the alignment of the other - block after the initial byte operations. The maximum number of - full words (of type op_t) are compared in this way. - - 3. Compare the few remaining bytes. */ - -#ifndef WORDS_BIGENDIAN -/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. - A and B are known to be different. - This is needed only on little-endian machines. */ - -static int memcmp_bytes __P((op_t, op_t)); - -# ifdef __GNUC__ -__inline -# endif -static int -memcmp_bytes (a, b) - op_t a, b; -{ - long int srcp1 = (long int) &a; - long int srcp2 = (long int) &b; - op_t a0, b0; - - do - { - a0 = ((byte *) srcp1)[0]; - b0 = ((byte *) srcp2)[0]; - srcp1 += 1; - srcp2 += 1; - } - while (a0 == b0); - return a0 - b0; -} -#endif - -static int memcmp_common_alignment __P((long, long, size_t)); - -/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' - objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for - memory operations on `op_t's. */ -#ifdef __GNUC__ -__inline -#endif -static int -memcmp_common_alignment (srcp1, srcp2, len) - long int srcp1; - long int srcp2; - size_t len; -{ - op_t a0, a1; - op_t b0, b1; - - switch (len % 4) - { - default: /* Avoid warning about uninitialized local variables. */ - case 2: - a0 = ((op_t *) srcp1)[0]; - b0 = ((op_t *) srcp2)[0]; - srcp1 -= 2 * OPSIZ; - srcp2 -= 2 * OPSIZ; - len += 2; - goto do1; - case 3: - a1 = ((op_t *) srcp1)[0]; - b1 = ((op_t *) srcp2)[0]; - srcp1 -= OPSIZ; - srcp2 -= OPSIZ; - len += 1; - goto do2; - case 0: - if (OP_T_THRES <= 3 * OPSIZ && len == 0) - return 0; - a0 = ((op_t *) srcp1)[0]; - b0 = ((op_t *) srcp2)[0]; - goto do3; - case 1: - a1 = ((op_t *) srcp1)[0]; - b1 = ((op_t *) srcp2)[0]; - srcp1 += OPSIZ; - srcp2 += OPSIZ; - len -= 1; - if (OP_T_THRES <= 3 * OPSIZ && len == 0) - goto do0; - /* Fall through. */ - } - - do - { - a0 = ((op_t *) srcp1)[0]; - b0 = ((op_t *) srcp2)[0]; - if (a1 != b1) - return CMP_LT_OR_GT (a1, b1); - - do3: - a1 = ((op_t *) srcp1)[1]; - b1 = ((op_t *) srcp2)[1]; - if (a0 != b0) - return CMP_LT_OR_GT (a0, b0); - - do2: - a0 = ((op_t *) srcp1)[2]; - b0 = ((op_t *) srcp2)[2]; - if (a1 != b1) - return CMP_LT_OR_GT (a1, b1); - - do1: - a1 = ((op_t *) srcp1)[3]; - b1 = ((op_t *) srcp2)[3]; - if (a0 != b0) - return CMP_LT_OR_GT (a0, b0); - - srcp1 += 4 * OPSIZ; - srcp2 += 4 * OPSIZ; - len -= 4; - } - while (len != 0); - - /* This is the right position for do0. Please don't move - it into the loop. */ - do0: - if (a1 != b1) - return CMP_LT_OR_GT (a1, b1); - return 0; -} - -static int memcmp_not_common_alignment __P((long, long, size_t)); - -/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN - `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory - operations on `op_t', but SRCP1 *should be unaligned*. */ -#ifdef __GNUC__ -__inline -#endif -static int -memcmp_not_common_alignment (srcp1, srcp2, len) - long int srcp1; - long int srcp2; - size_t len; -{ - op_t a0, a1, a2, a3; - op_t b0, b1, b2, b3; - op_t x; - int shl, shr; - - /* Calculate how to shift a word read at the memory operation - aligned srcp1 to make it aligned for comparison. */ - - shl = 8 * (srcp1 % OPSIZ); - shr = 8 * OPSIZ - shl; - - /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t' - it points in the middle of. */ - srcp1 &= -OPSIZ; - - switch (len % 4) - { - default: /* Avoid warning about uninitialized local variables. */ - case 2: - a1 = ((op_t *) srcp1)[0]; - a2 = ((op_t *) srcp1)[1]; - b2 = ((op_t *) srcp2)[0]; - srcp1 -= 1 * OPSIZ; - srcp2 -= 2 * OPSIZ; - len += 2; - goto do1; - case 3: - a0 = ((op_t *) srcp1)[0]; - a1 = ((op_t *) srcp1)[1]; - b1 = ((op_t *) srcp2)[0]; - srcp2 -= 1 * OPSIZ; - len += 1; - goto do2; - case 0: - if (OP_T_THRES <= 3 * OPSIZ && len == 0) - return 0; - a3 = ((op_t *) srcp1)[0]; - a0 = ((op_t *) srcp1)[1]; - b0 = ((op_t *) srcp2)[0]; - srcp1 += 1 * OPSIZ; - goto do3; - case 1: - a2 = ((op_t *) srcp1)[0]; - a3 = ((op_t *) srcp1)[1]; - b3 = ((op_t *) srcp2)[0]; - srcp1 += 2 * OPSIZ; - srcp2 += 1 * OPSIZ; - len -= 1; - if (OP_T_THRES <= 3 * OPSIZ && len == 0) - goto do0; - /* Fall through. */ - } - - do - { - a0 = ((op_t *) srcp1)[0]; - b0 = ((op_t *) srcp2)[0]; - x = MERGE(a2, shl, a3, shr); - if (x != b3) - return CMP_LT_OR_GT (x, b3); - - do3: - a1 = ((op_t *) srcp1)[1]; - b1 = ((op_t *) srcp2)[1]; - x = MERGE(a3, shl, a0, shr); - if (x != b0) - return CMP_LT_OR_GT (x, b0); - - do2: - a2 = ((op_t *) srcp1)[2]; - b2 = ((op_t *) srcp2)[2]; - x = MERGE(a0, shl, a1, shr); - if (x != b1) - return CMP_LT_OR_GT (x, b1); - - do1: - a3 = ((op_t *) srcp1)[3]; - b3 = ((op_t *) srcp2)[3]; - x = MERGE(a1, shl, a2, shr); - if (x != b2) - return CMP_LT_OR_GT (x, b2); - - srcp1 += 4 * OPSIZ; - srcp2 += 4 * OPSIZ; - len -= 4; - } - while (len != 0); - - /* This is the right position for do0. Please don't move - it into the loop. */ - do0: - x = MERGE(a2, shl, a3, shr); - if (x != b3) - return CMP_LT_OR_GT (x, b3); - return 0; -} - -int -rpl_memcmp (s1, s2, len) - const __ptr_t s1; - const __ptr_t s2; - size_t len; -{ - op_t a0; - op_t b0; - long int srcp1 = (long int) s1; - long int srcp2 = (long int) s2; - op_t res; - - if (len >= OP_T_THRES) - { - /* There are at least some bytes to compare. No need to test - for LEN == 0 in this alignment loop. */ - while (srcp2 % OPSIZ != 0) - { - a0 = ((byte *) srcp1)[0]; - b0 = ((byte *) srcp2)[0]; - srcp1 += 1; - srcp2 += 1; - res = a0 - b0; - if (res != 0) - return res; - len -= 1; - } - - /* SRCP2 is now aligned for memory operations on `op_t'. - SRCP1 alignment determines if we can do a simple, - aligned compare or need to shuffle bits. */ - - if (srcp1 % OPSIZ == 0) - res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ); - else - res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ); - if (res != 0) - return res; - - /* Number of bytes remaining in the interval [0..OPSIZ-1]. */ - srcp1 += len & -OPSIZ; - srcp2 += len & -OPSIZ; - len %= OPSIZ; - } - - /* There are just a few bytes to compare. Use byte memory operations. */ - while (len != 0) - { - a0 = ((byte *) srcp1)[0]; - b0 = ((byte *) srcp2)[0]; - srcp1 += 1; - srcp2 += 1; - res = a0 - b0; - if (res != 0) - return res; - len -= 1; - } - - return 0; -} - -#ifdef weak_alias -# undef bcmp -weak_alias (memcmp, bcmp) -#endif diff --git a/lib/pidfile.c b/lib/pidfile.c deleted file mode 100644 index a954d18..0000000 --- a/lib/pidfile.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - pidfile.c - interact with pidfiles - Copyright (c) 1995 Martin Schulze - - This file is part of the sysklogd package, a kernel and system log daemon. - - 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, USA -*/ - -/* left unaltered for tinc -- Ivo Timmermans */ -/* - * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze - * First version (v0.2) released - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* read_pid - * - * Reads the specified pidfile and returns the read pid. - * 0 is returned if either there's no pidfile, it's empty - * or no pid can be read. - */ -int read_pid (char *pidfile) -{ - FILE *f; - int pid; - - if (!(f=fopen(pidfile,"r"))) - return 0; - fscanf(f,"%d", &pid); - fclose(f); - return pid; -} - -/* check_pid - * - * Reads the pid using read_pid and looks up the pid in the process - * table (using /proc) to determine if the process already exists. If - * so 1 is returned, otherwise 0. - */ -int check_pid (char *pidfile) -{ - int pid = read_pid(pidfile); - - /* Amazing ! _I_ am already holding the pid file... */ - if ((!pid) || (pid == getpid ())) - return 0; - - /* - * The 'standard' method of doing this is to try and do a 'fake' kill - * of the process. If an ESRCH error is returned the process cannot - * be found -- GW - */ - /* But... errno is usually changed only on error.. */ - errno = 0; - if (kill(pid, 0) && errno == ESRCH) - return(0); - - return pid; -} - -/* write_pid - * - * Writes the pid to the specified file. If that fails 0 is - * returned, otherwise the pid. - */ -int write_pid (char *pidfile) -{ - FILE *f; - int fd; - int pid; - - if ( ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1) - || ((f = fdopen(fd, "r+")) == NULL) ) { - fprintf(stderr, "Can't open or create %s.\n", pidfile); - return 0; - } - -#ifdef HAVE_FLOCK - if (flock(fd, LOCK_EX|LOCK_NB) == -1) { - fscanf(f, "%d", &pid); - fclose(f); - printf("Can't lock, lock is held by pid %d.\n", pid); - return 0; - } -#endif - - pid = getpid(); - if (!fprintf(f,"%d\n", pid)) { - printf("Can't write pid , %s.\n", strerror(errno)); - close(fd); - return 0; - } - fflush(f); - -#ifdef HAVE_FLOCK - if (flock(fd, LOCK_UN) == -1) { - printf("Can't unlock pidfile %s, %s.\n", pidfile, strerror(errno)); - close(fd); - return 0; - } -#endif - close(fd); - - return pid; -} - -/* remove_pid - * - * Remove the the specified file. The result from unlink(2) - * is returned - */ -int remove_pid (char *pidfile) -{ - return unlink (pidfile); -} - diff --git a/lib/realloc.c b/lib/realloc.c deleted file mode 100644 index d0d3e4a..0000000 --- a/lib/realloc.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Work around bug on some systems where realloc (NULL, 0) fails. - Copyright (C) 1997 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. */ - -/* written by Jim Meyering */ - -#if HAVE_CONFIG_H -# include -#endif -#undef realloc - -#include - -char *malloc (); -char *realloc (); - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. If N is zero, change it to 1. If P is NULL, - use malloc. */ - -char * -rpl_realloc (p, n) - char *p; - size_t n; -{ - if (n == 0) - n = 1; - if (p == 0) - return malloc (n); - return realloc (p, n); -} diff --git a/lib/utils.c b/lib/utils.c deleted file mode 100644 index d79532b..0000000 --- a/lib/utils.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - utils.c -- gathering of some stupid small functions - Copyright (C) 1999-2001 Ivo Timmermans - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include -#include -#include - -#include "config.h" - -#include -#include -#include - -#ifdef ENABLE_TRACING -volatile int (cp_line[]) = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -volatile char (*cp_file[]) = {"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?"}; -volatile int cp_index = 0; -#endif - -char *hexadecimals = "0123456789ABCDEF"; - -int charhex2bin(char c) -{ - if(isdigit(c)) - return c - '0'; - else - return toupper(c) - 'A' + 10; -} - - -void hex2bin(char *src, char *dst, int length) -{ - int i; - for(i=0; i=0; i--) - { - dst[i*2+1] = hexadecimals[(unsigned char)src[i] & 15]; - dst[i*2] = hexadecimals[(unsigned char)src[i]>>4]; - } -} - -#ifdef ENABLE_TRACING -void cp_trace() -{ - syslog(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d...", - cp_file[(cp_index+15)%16], cp_line[(cp_index+15)%16], - cp_file[(cp_index+14)%16], cp_line[(cp_index+14)%16], - cp_file[(cp_index+13)%16], cp_line[(cp_index+13)%16], - cp_file[(cp_index+12)%16], cp_line[(cp_index+12)%16], - cp_file[(cp_index+11)%16], cp_line[(cp_index+11)%16], - cp_file[(cp_index+10)%16], cp_line[(cp_index+10)%16], - cp_file[(cp_index+9)%16], cp_line[(cp_index+9)%16], - cp_file[(cp_index+8)%16], cp_line[(cp_index+8)%16], - cp_file[(cp_index+7)%16], cp_line[(cp_index+7)%16], - cp_file[(cp_index+6)%16], cp_line[(cp_index+6)%16], - cp_file[(cp_index+5)%16], cp_line[(cp_index+5)%16], - cp_file[(cp_index+4)%16], cp_line[(cp_index+4)%16], - cp_file[(cp_index+3)%16], cp_line[(cp_index+3)%16], - cp_file[(cp_index+2)%16], cp_line[(cp_index+2)%16], - cp_file[(cp_index+1)%16], cp_line[(cp_index+1)%16], - cp_file[cp_index], cp_line[cp_index] - ); -} -#endif diff --git a/lib/utils.h b/lib/utils.h deleted file mode 100644 index 0b79bfa..0000000 --- a/lib/utils.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - utils.h -- header file for utils.c - Copyright (C) 1999-2001 Ivo Timmermans - 2000,2001 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef __TINC_UTILS_H__ -#define __TINC_UTILS_H__ - -#include - -enum { - DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */ - DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */ - DEBUG_ERROR = 2, /* Show error messages received from other hosts */ - DEBUG_STATUS = 2, /* Show status messages received from other hosts */ - DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */ - DEBUG_META = 4, /* Show contents of every request that is sent/received */ - DEBUG_TRAFFIC = 5, /* Show network traffic information */ - DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */ - DEBUG_SCARY_THINGS = 10 /* You have been warned */ -}; - -#define min(a,b) (((a)<(b))?(a):(b)) - -#ifdef ENABLE_TRACING -extern volatile int cp_line[]; -extern volatile char *cp_file[]; -extern volatile int cp_index; -extern void cp_trace(void); - - #define cp { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 16; } - #define ecp { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); } -#else - #define cp - #define ecp - #define cp_trace() -#endif - -extern void hex2bin(char *src, char *dst, int length); -extern void bin2hex(char *src, char *dst, int length); - -#endif /* __TINC_UTILS_H__ */ diff --git a/lib/xalloc.h b/lib/xalloc.h deleted file mode 100644 index caf0f37..0000000 --- a/lib/xalloc.h +++ /dev/null @@ -1,26 +0,0 @@ -#include - -#ifndef PARAMS -# if defined PROTOTYPES || (defined __STDC__ && __STDC__) -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif -#endif - -/* Exit value when the requested amount of memory is not available. - The caller may set it to some other value. */ -extern int xalloc_exit_failure; - -/* FIXME: describe */ -extern char *const xalloc_msg_memory_exhausted; - -/* FIXME: describe */ -extern void (*xalloc_fail_func) (); - -void *xmalloc PARAMS ((size_t n)); -void *xmalloc_and_zero PARAMS ((size_t n)); -void *xcalloc PARAMS ((size_t n, size_t s)); -void *xrealloc PARAMS ((void *p, size_t n)); - -char *xstrdup PARAMS ((const char *s)); diff --git a/lib/xmalloc.c b/lib/xmalloc.c deleted file mode 100644 index e1ab314..0000000 --- a/lib/xmalloc.c +++ /dev/null @@ -1,156 +0,0 @@ -/* xmalloc.c -- malloc with out of memory checking - Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 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. */ - -#if HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#if STDC_HEADERS -# include -#else -void *calloc (); -void *malloc (); -void *realloc (); -void free (); -#endif - -#if ENABLE_NLS -# include -# define _(Text) gettext (Text) -#else -# define textdomain(Domain) -# define _(Text) Text -#endif -#define N_(Text) Text - -#include "xalloc.h" - -#ifndef EXIT_FAILURE -# define EXIT_FAILURE 1 -#endif - -/* Prototypes for functions defined here. */ -#if defined (__STDC__) && __STDC__ -void *xmalloc (size_t n); -void *xcalloc (size_t n, size_t s); -void *xrealloc (void *p, size_t n); -#endif - -#ifndef HAVE_DONE_WORKING_MALLOC_CHECK -#error you must run the autoconf test for a properly working malloc -- see malloc.m4 -#endif - -#ifndef HAVE_DONE_WORKING_REALLOC_CHECK -#error you must run the autoconf test for a properly working realloc -- see realloc.m4 -#endif - -/* Exit value when the requested amount of memory is not available. - The caller may set it to some other value. */ -int xalloc_exit_failure = EXIT_FAILURE; - -/* FIXME: describe */ -char *const xalloc_msg_memory_exhausted = N_("Memory exhausted"); - -/* FIXME: describe */ -void (*xalloc_fail_func) (int) = 0; - -static void -xalloc_fail (int size) -{ - if (xalloc_fail_func) - (*xalloc_fail_func) (size); - fprintf(stderr, "%s\n", xalloc_msg_memory_exhausted); - exit(xalloc_exit_failure); -} - -/* Allocate N bytes of memory dynamically, with error checking. */ - -void * -xmalloc (n) - size_t n; -{ - void *p; - - p = malloc (n); - if (p == 0) - xalloc_fail ((int)n); - return p; -} - -/* Allocate N bytes of memory dynamically, and set it all to zero. */ - -void * -xmalloc_and_zero (n) - size_t n; -{ - void *p; - - p = malloc (n); - if (p == 0) - xalloc_fail ((int)n); - memset (p, '\0', n); - return p; -} - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. - If P is NULL, run xmalloc. */ - -void * -xrealloc (p, n) - void *p; - size_t n; -{ - p = realloc (p, n); - if (p == 0) - xalloc_fail (n); - return p; -} - -/* Duplicate a string */ - -char *xstrdup(const char *s) -{ - char *p; - - p = strdup(s); - if(!p) - xalloc_fail ((int)strlen(s)); - return p; -} - -#ifdef NOT_USED - -/* Allocate memory for N elements of S bytes, with error checking. */ - -void * -xcalloc (n, s) - size_t n, s; -{ - void *p; - - p = calloc (n, s); - if (p == 0) - xalloc_fail (); - return p; -} - -#endif /* NOT_USED */ diff --git a/m4/Makefile.am b/m4/Makefile.am deleted file mode 100644 index 216417b..0000000 --- a/m4/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -## Process this file with automake to produce Makefile.in -*-Makefile-*- - -##m4-files-begin -EXTRA_DIST = README Makefile.am.in aclocal-include.m4 malloc.m4 openssl.m4 \ -perl.m4 realloc.m4 tuntap.m4 zlib.m4 - -##m4-files-end - -Makefile.am: Makefile.am.in - rm -f $@ $@t - sed -n '1,/^##m4-files-begin/p' $< > $@t - ( echo EXTRA_DIST = README Makefile.am.in; \ - find . -type f -name '*.m4' -print |sed 's,^\./,,' |sort ) \ - |fmt | (tr '\012' @; echo) \ - |sed 's/@$$/%/;s/@/ \\@/g' |tr @% '\012\012' \ - >> $@t - sed -n '/^##m4-files-end/,$$p' $< >> $@t - chmod a-w $@t - mv $@t $@ diff --git a/m4/Makefile.am.in b/m4/Makefile.am.in deleted file mode 100644 index 9ee9c43..0000000 --- a/m4/Makefile.am.in +++ /dev/null @@ -1,16 +0,0 @@ -## Process this file with automake to produce Makefile.in -*-Makefile-*- - -##m4-files-begin -##m4-files-end - -Makefile.am: Makefile.am.in - rm -f $@ $@t - sed -n '1,/^##m4-files-begin/p' $< > $@t - ( echo EXTRA_DIST = README Makefile.am.in; \ - find . -type f -name '*.m4' -print |sed 's,^\./,,' |sort ) \ - |fmt | (tr '\012' @; echo) \ - |sed 's/@$$/%/;s/@/ \\@/g' |tr @% '\012\012' \ - >> $@t - sed -n '/^##m4-files-end/,$$p' $< >> $@t - chmod a-w $@t - mv $@t $@ diff --git a/m4/Makefile.in b/m4/Makefile.in deleted file mode 100644 index 6c80fe3..0000000 --- a/m4/Makefile.in +++ /dev/null @@ -1,232 +0,0 @@ -# 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 = : -host_alias = @host_alias@ -host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INCLUDES = @INCLUDES@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ - -EXTRA_DIST = README Makefile.am.in aclocal-include.m4 malloc.m4 openssl.m4 \ -perl.m4 realloc.m4 tuntap.m4 zlib.m4 - -subdir = m4 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -DIST_SOURCES = -DIST_COMMON = README Makefile.am Makefile.in -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu m4/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 mostlyclean-am - -distclean: distclean-am - -distclean-am: clean-am distclean-generic - -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 - -uninstall-am: uninstall-info-am - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic 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 uninstall uninstall-am uninstall-info-am - - -Makefile.am: Makefile.am.in - rm -f $@ $@t - sed -n '1,/^##m4-files-begin/p' $< > $@t - ( echo EXTRA_DIST = README Makefile.am.in; \ - find . -type f -name '*.m4' -print |sed 's,^\./,,' |sort ) \ - |fmt | (tr '\012' @; echo) \ - |sed 's/@$$/%/;s/@/ \\@/g' |tr @% '\012\012' \ - >> $@t - sed -n '/^##m4-files-end/,$$p' $< >> $@t - chmod a-w $@t - mv $@t $@ -# 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/m4/README b/m4/README deleted file mode 100644 index df032df..0000000 --- a/m4/README +++ /dev/null @@ -1,8 +0,0 @@ -These files are used by a program called aclocal (part of the GNU automake -package). aclocal uses these files to create aclocal.m4 which is in turn -used by autoconf to create the configure script at the the top level in -this distribution. - -The Makefile.am file in this directory is automatically generated -from the template file, Makefile.am.in. The generation will fail -if you don't have all the right tools. diff --git a/m4/aclocal-include.m4 b/m4/aclocal-include.m4 deleted file mode 100644 index 844e7d2..0000000 --- a/m4/aclocal-include.m4 +++ /dev/null @@ -1,14 +0,0 @@ -# aclocal-include.m4 -# -# This macro adds the name macrodir to the set of directories -# that `aclocal' searches for macros. - -# serial 1 - -dnl AM_ACLOCAL_INCLUDE(macrodir) -AC_DEFUN([AM_ACLOCAL_INCLUDE], -[ - test -n "$ACLOCAL_FLAGS" && ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" - - for k in $1 ; do ACLOCAL="$ACLOCAL -I $k" ; done -]) diff --git a/m4/attribute.m4 b/m4/attribute.m4 new file mode 100644 index 0000000..9d673e9 --- /dev/null +++ b/m4/attribute.m4 @@ -0,0 +1,25 @@ +dnl Check to find out whether function attributes are supported. +dnl If they are not, #define them to be nothing. + +AC_DEFUN([tinc_ATTRIBUTE], +[ + AC_CACHE_CHECK([for working $1 attribute], tinc_cv_attribute_$1, + [ + tempcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wall -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [void *test(void) __attribute__ (($1)); + void *test(void) { return (void *)0; } + ], + )], + [tinc_cv_attribute_$1=yes], + [tinc_cv_attribute_$1=no] + ) + CFLAGS="$tempcflags" + ]) + + if test ${tinc_cv_attribute_$1} = no; then + AC_DEFINE([$1], [], [Defined if the $1 attribute is not supported.]) + fi +]) diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 0000000..1d38b76 --- /dev/null +++ b/m4/ax_append_flag.m4 @@ -0,0 +1,69 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_APPEND_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl +AS_VAR_SET_IF(FLAGS, + [case " AS_VAR_GET(FLAGS) " in + *" $1 "*) + AC_RUN_LOG([: FLAGS already contains $1]) + ;; + *) + AC_RUN_LOG([: FLAGS="$FLAGS $1"]) + AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) + ;; + esac], + [AS_VAR_SET(FLAGS,["$1"])]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/m4/ax_cflags_warn_all.m4 b/m4/ax_cflags_warn_all.m4 new file mode 100644 index 0000000..1f07799 --- /dev/null +++ b/m4/ax_cflags_warn_all.m4 @@ -0,0 +1,122 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# +# DESCRIPTION +# +# Try to find a compiler option that enables most reasonable warnings. +# +# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result +# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default. +# +# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX, +# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and +# Intel compilers. For a given compiler, the Fortran flags are much more +# experimental than their C equivalents. +# +# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS +# - $2 add-value-if-not-found : nothing +# - $3 action-if-found : add value to shellvariable +# - $4 action-if-not-found : nothing +# +# NOTE: These macros depend on AX_APPEND_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2010 Rhys Ulerich +# +# 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 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 15 + +AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl +AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl +AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl +AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings], +VAR,[VAR="no, unknown" +ac_save_[]FLAGS="$[]FLAGS" +for ac_arg dnl +in "-warn all % -warn all" dnl Intel + "-pedantic % -Wall" dnl GCC + "-xstrconst % -v" dnl Solaris C + "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix + "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX + "-ansi -ansiE % -fullwarn" dnl IRIX + "+ESlit % +w1" dnl HP-UX C + "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10) + "-h conform % -h msglevel 2" dnl Cray C (Unicos) + # +do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) +done +FLAGS="$ac_save_[]FLAGS" +]) +AS_VAR_POPDEF([FLAGS])dnl +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +case ".$VAR" in + .ok|.ok,*) m4_ifvaln($3,$3) ;; + .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; + *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;; +esac +AS_VAR_POPDEF([VAR])dnl +])dnl AX_FLAGS_WARN_ALL +dnl implementation tactics: +dnl the for-argument contains a list of options. The first part of +dnl these does only exist to detect the compiler - usually it is +dnl a global option to enable -ansi or -extrawarnings. All other +dnl compilers will fail about it. That was needed since a lot of +dnl compilers will give false positives for some option-syntax +dnl like -Woption or -Xoption as they think of it is a pass-through +dnl to later compile stages or something. The "%" is used as a +dnl delimiter. A non-option comment can be given after "%%" marks +dnl which will be shown but not added to the respective C/CXXFLAGS. + +AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([C]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([C]) +]) + +AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([C++]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([C++]) +]) + +AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([Fortran]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([Fortran]) +]) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..c3a8d69 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 new file mode 100644 index 0000000..e2d0d36 --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 0000000..cae1111 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/m4/lzo.m4 b/m4/lzo.m4 new file mode 100644 index 0000000..36aa9b7 --- /dev/null +++ b/m4/lzo.m4 @@ -0,0 +1,47 @@ +dnl Check to find the lzo headers/libraries + +AC_DEFUN([tinc_LZO], +[ + AC_ARG_ENABLE([lzo], + AS_HELP_STRING([--disable-lzo], [disable lzo compression support])) + AS_IF([test "x$enable_lzo" != "xno"], [ + AC_DEFINE(HAVE_LZO, 1, [enable lzo compression support]) + AC_ARG_WITH(lzo, + AS_HELP_STRING([--with-lzo=DIR], [lzo base directory, or:]), + [lzo="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib"] + ) + + AC_ARG_WITH(lzo-include, + AS_HELP_STRING([--with-lzo-include=DIR], [lzo headers directory]), + [lzo_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval"] + ) + + AC_ARG_WITH(lzo-lib, + AS_HELP_STRING([--with-lzo-lib=DIR], [lzo library directory]), + [lzo_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval"] + ) + + AC_CHECK_LIB(lzo2, lzo1x_1_compress, + [LIBS="$LIBS -llzo2"], + [AC_CHECK_LIB(lzo, lzo1x_1_compress, + [LIBS="$LIBS -llzo"], + [AC_MSG_ERROR("lzo libraries not found."); break] + )] + ) + + AC_CHECK_HEADERS(lzo/lzo1x.h, + [AC_DEFINE(LZO1X_H, [], [Location of lzo1x.h])], + [AC_CHECK_HEADERS(lzo2/lzo1x.h, + [AC_DEFINE(LZO1X_H, [], [Location of lzo1x.h])], + [AC_CHECK_HEADERS(lzo1x.h, + [AC_DEFINE(LZO1X_H, [], [Location of lzo1x.h])], + [AC_MSG_ERROR("lzo header files not found."); break] + )] + )] + ) + ]) +]) diff --git a/m4/malloc.m4 b/m4/malloc.m4 deleted file mode 100644 index bd3cad4..0000000 --- a/m4/malloc.m4 +++ /dev/null @@ -1,44 +0,0 @@ -#serial 1 - -dnl From Jim Meyering. -dnl Determine whether malloc accepts 0 as its argument. -dnl If it doesn't, arrange to use the replacement function. -dnl -dnl If you use this macro in a package, you should -dnl add the following two lines to acconfig.h: -dnl /* Define to rpl_malloc if the replacement function should be used. */ -dnl #undef malloc -dnl - -AC_DEFUN(jm_FUNC_MALLOC, -[ - if test x = y; then - dnl This code is deliberately never run via ./configure. - dnl FIXME: this is a gross hack to make autoheader put an entry - dnl for this symbol in config.h.in. - AC_CHECK_FUNCS(DONE_WORKING_MALLOC_CHECK) - fi - dnl xmalloc.c requires that this symbol be defined so it doesn't - dnl mistakenly use a broken malloc -- as it might if this test were omitted. - ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK - AC_DEFINE_UNQUOTED($ac_kludge) - - AC_CACHE_CHECK([for working malloc], jm_cv_func_working_malloc, - [AC_TRY_RUN([ - char *malloc (); - int - main () - { - exit (malloc (0) ? 0 : 1); - } - ], - jm_cv_func_working_malloc=yes, - jm_cv_func_working_malloc=no, - dnl When crosscompiling, assume malloc is broken. - jm_cv_func_working_malloc=no) - ]) - if test $jm_cv_func_working_malloc = no; then - LIBOBJS="$LIBOBJS malloc.o" - AC_DEFINE_UNQUOTED(malloc, rpl_malloc) - fi -]) diff --git a/m4/openssl.m4 b/m4/openssl.m4 index e5c0939..895c31a 100644 --- a/m4/openssl.m4 +++ b/m4/openssl.m4 @@ -1,49 +1,58 @@ -dnl Check to find the OpenSSL headers/libraries +dnl Check to find the LibreSSL/OpenSSL headers/libraries -AC_DEFUN(tinc_OPENSSL, +AC_DEFUN([tinc_OPENSSL], [ - tinc_ac_save_CPPFLAGS="$CPPFLAGS" + case $host_os in + *mingw*) + ;; + *) + AC_CHECK_FUNC(dlopen, + [], + [AC_CHECK_LIB(dl, dlopen, + [LIBS="$LIBS -ldl"], + [AC_MSG_ERROR([LibreSSL/OpenSSL depends on libdl.]); break] + )] + ) + ;; + esac + + AC_ARG_WITH(openssl, + AS_HELP_STRING([--with-openssl=DIR], [LibreSSL/OpenSSL base directory, or:]), + [openssl="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib"] + ) AC_ARG_WITH(openssl-include, - [ --with-openssl-include=DIR OpenSSL headers directory (without trailing /openssl)], + AS_HELP_STRING([--with-openssl-include=DIR], [LibreSSL/OpenSSL headers directory (without trailing /openssl)]), [openssl_include="$withval" - CFLAGS="$CFLAGS -I$withval" CPPFLAGS="$CPPFLAGS -I$withval"] ) AC_ARG_WITH(openssl-lib, - [ --with-openssl-lib=DIR OpenSSL library directory], + AS_HELP_STRING([--with-openssl-lib=DIR], [LibreSSL/OpenSSL library directory]), [openssl_lib="$withval" - LIBS="$LIBS -L$withval"] + LDFLAGS="$LDFLAGS -L$withval"] ) - AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h, + AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h, [], - [AC_MSG_ERROR("OpenSSL header files not found."); break] + [AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break] ) - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - AC_CHECK_LIB(crypto, SHA1_version, - [LIBS="$LIBS -lcrypto"], - [AC_MSG_ERROR("OpenSSL libraries not found.")] + AC_CHECK_LIB(crypto, EVP_EncryptInit_ex, + [LIBS="-lcrypto $LIBS"], + [AC_MSG_ERROR([LibreSSL/OpenSSL libraries not found.])] ) - AC_CHECK_FUNCS(RAND_pseudo_bytes) - - AC_CHECK_FUNC(OpenSSL_add_all_algorithms, - [], - AC_CHECK_FUNC(SSLeay_add_all_algorithms, - [AC_DEFINE(HAVE_SSLEAY_ADD_ALL_ALGORITHMS)], - [AC_MSG_ERROR("Missing required OpenSSL functionality!")] - ) + AC_CHECK_FUNCS([RAND_bytes EVP_EncryptInit_ex EVP_CIPHER_CTX_new], , + [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break], ) - AC_CHECK_FUNC(dlopen, - [], - AC_CHECK_LIB(dl, dlopen, - [LIBS="$LIBS -ldl"], - [AC_MSG_ERROR("OpenSSL depends on libdl.")] - ) + AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_aes_256_cfb], , + [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break], + [#include ] ) + + AC_CHECK_FUNCS([BN_GENCB_new RSA_set0_key], , , [#include ]) ]) diff --git a/m4/perl.m4 b/m4/perl.m4 deleted file mode 100644 index 0cc681c..0000000 --- a/m4/perl.m4 +++ /dev/null @@ -1,39 +0,0 @@ -#serial 1 - -dnl From Jim Meyering. -dnl Find a new-enough version of Perl. -dnl - -AC_DEFUN(jm_PERL, -[ - dnl FIXME: don't hard-code 5.003 - dnl FIXME: should we cache the result? - AC_MSG_CHECKING([for perl5.003 or newer]) - if test "${PERL+set}" = set; then - # `PERL' is set in the user's environment. - candidate_perl_names="$PERL" - perl_specified=yes - else - candidate_perl_names='perl perl5' - perl_specified=no - fi - - found=no - AC_SUBST(PERL) - PERL="$missing_dir/missing perl" - for perl in $candidate_perl_names; do - # Run test in a subshell; some versions of sh will print an error if - # an executable is not found, even if stderr is redirected. - if ( $perl -e 'require 5.003' ) > /dev/null 2>&1; then - PERL=$perl - found=yes - break - fi - done - - AC_MSG_RESULT($found) - test $found = no && AC_MSG_WARN([ -*** You don't seem to have perl5.003 or newer installed. -*** Because of that, you may be unable to regenerate certain files -*** if you modify the sources from which they are derived.] ) -]) diff --git a/m4/realloc.m4 b/m4/realloc.m4 deleted file mode 100644 index aba1984..0000000 --- a/m4/realloc.m4 +++ /dev/null @@ -1,44 +0,0 @@ -#serial 1 - -dnl From Jim Meyering. -dnl Determine whether realloc works when both arguments are 0. -dnl If it doesn't, arrange to use the replacement function. -dnl -dnl If you use this macro in a package, you should -dnl add the following two lines to acconfig.h: -dnl /* Define to rpl_realloc if the replacement function should be used. */ -dnl #undef realloc -dnl - -AC_DEFUN(jm_FUNC_REALLOC, -[ - if test x = y; then - dnl This code is deliberately never run via ./configure. - dnl FIXME: this is a gross hack to make autoheader put an entry - dnl for this symbol in config.h.in. - AC_CHECK_FUNCS(DONE_WORKING_REALLOC_CHECK) - fi - dnl xmalloc.c requires that this symbol be defined so it doesn't - dnl mistakenly use a broken realloc -- as it might if this test were omitted. - ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK - AC_DEFINE_UNQUOTED($ac_kludge) - - AC_CACHE_CHECK([for working realloc], jm_cv_func_working_realloc, - [AC_TRY_RUN([ - char *realloc (); - int - main () - { - exit (realloc (0, 0) ? 0 : 1); - } - ], - jm_cv_func_working_realloc=yes, - jm_cv_func_working_realloc=no, - dnl When crosscompiling, assume realloc is broken. - jm_cv_func_working_realloc=no) - ]) - if test $jm_cv_func_working_realloc = no; then - LIBOBJS="$LIBOBJS realloc.o" - AC_DEFINE_UNQUOTED(realloc, rpl_realloc) - fi -]) diff --git a/m4/tuntap.m4 b/m4/tuntap.m4 deleted file mode 100644 index 0bee1ce..0000000 --- a/m4/tuntap.m4 +++ /dev/null @@ -1,39 +0,0 @@ -dnl Check to find out whether the running kernel has support for TUN/TAP - -AC_DEFUN(tinc_TUNTAP, -[ -AC_ARG_WITH(kernel, - [ --with-kernel=dir give the directory with kernel sources] - [ (default: /usr/src/linux)], - kerneldir="$withval", - kerneldir="/usr/src/linux" -) - -AC_CACHE_CHECK([for linux/if_tun.h], tinc_cv_linux_if_tun_h, -[ - AC_TRY_COMPILE([#include "$kerneldir/include/linux/if_tun.h"], - [int a = IFF_TAP;], - if_tun_h="\"$kerneldir/include/linux/if_tun.h\"", - [AC_TRY_COMPILE([#include ], - [int a = IFF_TAP;], - if_tun_h="default", - if_tun_h="no" - )] - ) - - if test $if_tun_h = no; then - tinc_cv_linux_if_tun_h=none - else - tinc_cv_linux_if_tun_h="$if_tun_h" - fi -]) - -if test $tinc_cv_linux_if_tun_h != none; then - AC_DEFINE(HAVE_TUNTAP) - if test $tinc_cv_linux_if_tun_h != default; then - AC_DEFINE_UNQUOTED(LINUX_IF_TUN_H, $tinc_cv_linux_if_tun_h) - fi -fi -AC_SUBST(LINUX_IF_TUN_H) -AC_SUBST(HAVE_TUNTAP) -]) diff --git a/m4/zlib.m4 b/m4/zlib.m4 index d5fbc67..64245a5 100644 --- a/m4/zlib.m4 +++ b/m4/zlib.m4 @@ -1,31 +1,38 @@ dnl Check to find the zlib headers/libraries -AC_DEFUN(tinc_ZLIB, +AC_DEFUN([tinc_ZLIB], [ - tinc_ac_save_CPPFLAGS="$CPPFLAGS" + AC_ARG_ENABLE([zlib], + AS_HELP_STRING([--disable-zlib], [disable zlib compression support])) + AS_IF([test "x$enable_zlib" != "xno"], [ + AC_DEFINE(HAVE_ZLIB, 1, [have zlib compression support]) + AC_ARG_WITH(zlib, + AS_HELP_STRING([--with-zlib=DIR], [zlib base directory, or:]), + [zlib="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib"] + ) - AC_ARG_WITH(zlib-include, - [ --with-zlib-include=DIR zlib headers directory], - [zlib_include="$withval" - CFLAGS="$CFLAGS -I$withval" - CPPFLAGS="$CPPFLAGS -I$withval"] - ) + AC_ARG_WITH(zlib-include, + AS_HELP_STRING([--with-zlib-include=DIR], [zlib headers directory]), + [zlib_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval"] + ) - AC_ARG_WITH(zlib-lib, - [ --with-zlib-lib=DIR zlib library directory], - [zlib_lib="$withval" - LIBS="$LIBS -L$withval"] - ) + AC_ARG_WITH(zlib-lib, + AS_HELP_STRING([--with-zlib-lib=DIR], [zlib library directory]), + [zlib_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval"] + ) - AC_CHECK_HEADERS(zlib.h, - [], - [AC_MSG_ERROR("zlib header files not found."); break] - ) + AC_CHECK_HEADERS(zlib.h, + [], + [AC_MSG_ERROR("zlib header files not found."); break] + ) - CPPFLAGS="$tinc_ac_save_CPPFLAGS" - - AC_CHECK_LIB(z, compress2, - [LIBS="$LIBS -lz"], - [AC_MSG_ERROR("zlib libraries not found.")] - ) + AC_CHECK_LIB(z, compress2, + [LIBS="$LIBS -lz"], + [AC_MSG_ERROR("zlib libraries not found.")] + ) + ]) ]) diff --git a/missing b/missing index 0a7fb5a..8d0eaad 100755 --- a/missing +++ b/missing @@ -1,7 +1,10 @@ #! /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 , 1996. +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 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 @@ -14,9 +17,7 @@ # 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. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -24,260 +25,191 @@ # 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" + echo 1>&2 "Try '$0 --help' for more information" exit 1 fi -run=: +case $1 in -# 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 + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; -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 + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; -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. +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. 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]" + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.3 - GNU automake" + echo "missing $scriptversion (GNU Automake)" + exit $? ;; -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" + 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 +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/mkinstalldirs b/mkinstalldirs deleted file mode 100755 index 4f58503..0000000 --- a/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje 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/po/ChangeLog b/po/ChangeLog deleted file mode 100644 index c31f13f..0000000 --- a/po/ChangeLog +++ /dev/null @@ -1,28 +0,0 @@ -2002-04-09 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-09 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-08 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-08 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-08 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-08 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-08 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - diff --git a/po/Makefile.in.in b/po/Makefile.in.in deleted file mode 100644 index 28726a2..0000000 --- a/po/Makefile.in.in +++ /dev/null @@ -1,196 +0,0 @@ -# Makefile for program source directory in GNU NLS utilities package. -# Copyright (C) 1995-1997, 2000, 2001 by Ulrich Drepper -# -# This file file be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public License -# but which still want to provide support for the GNU gettext functionality. -# Please note that the actual code is *not* freely available. - -PACKAGE = @PACKAGE@ -VERSION = @VERSION@ - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -SHELL = /bin/sh -@SET_MAKE@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -datadir = @datadir@ -localedir = $(datadir)/locale -gettextsrcdir = $(datadir)/gettext/po - -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` - -CC = @CC@ -GMSGFMT = @GMSGFMT@ -MSGFMT = @MSGFMT@ -XGETTEXT = @XGETTEXT@ -MSGMERGE = msgmerge - -DEFS = @DEFS@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ - -INCLUDES = -I.. -I$(top_srcdir)/intl - -COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) - -POFILES = @POFILES@ -GMOFILES = @GMOFILES@ -DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \ -$(POFILES) $(GMOFILES) - -POTFILES = \ - -CATALOGS = @CATALOGS@ - -.SUFFIXES: -.SUFFIXES: .c .o .po .pox .gmo .mo - -.c.o: - $(COMPILE) $< - -.po.pox: - $(MAKE) $(PACKAGE).pot - $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox - -.po.mo: - $(MSGFMT) -o $@ $< - -.po.gmo: - file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ - && rm -f $$file && $(GMSGFMT) --statistics -o $$file $< - - -all: all-@USE_NLS@ - -all-yes: $(CATALOGS) -all-no: - -# Note: Target 'all' must not depend on target '$(srcdir)/$(PACKAGE).pot', -# otherwise packages like GCC can not be built if only parts of the source -# have been downloaded. - -$(srcdir)/$(PACKAGE).pot: $(POTFILES) $(srcdir)/POTFILES.in - $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ - --add-comments --keyword=_ --keyword=N_ \ - --files-from=$(srcdir)/POTFILES.in \ - && test ! -f $(PACKAGE).po \ - || ( rm -f $(srcdir)/$(PACKAGE).pot \ - && mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot ) - - -install: install-exec install-data -install-exec: -install-data: install-data-@USE_NLS@ - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ - $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ - else \ - : ; \ - fi -install-data-no: all -install-data-yes: all - $(mkinstalldirs) $(DESTDIR)$(datadir) - @catalogs='$(CATALOGS)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - dir=$(localedir)/$$lang/LC_MESSAGES; \ - $(mkinstalldirs) $(DESTDIR)$$dir; \ - if test -r $$cat; then \ - $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \ - echo "installing $$cat as $(DESTDIR)$$dir/$(PACKAGE).mo"; \ - else \ - $(INSTALL_DATA) $(srcdir)/$$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \ - echo "installing $(srcdir)/$$cat as" \ - "$(DESTDIR)$$dir/$(PACKAGE).mo"; \ - fi; \ - done - -# Define this as empty until I found a useful application. -installcheck: - -uninstall: - catalogs='$(CATALOGS)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \ - done - if test "$(PACKAGE)" = "gettext"; then \ - rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ - else \ - : ; \ - fi - -check: all - -dvi info tags TAGS ID: - -mostlyclean: - rm -f core core.* *.pox $(PACKAGE).po *.new.po - rm -fr *.o - -clean: mostlyclean - -distclean: clean - rm -f Makefile Makefile.in POTFILES *.mo - -maintainer-clean: distclean - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - rm -f $(GMOFILES) - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) -dist distdir: - $(MAKE) update-po - @$(MAKE) dist2 -# This is a separate target because 'update-po' must be executed before. -dist2: $(DISTFILES) - dists="$(DISTFILES)"; \ - for file in $$dists; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - cp -p $$dir/$$file $(distdir); \ - done - -update-po: Makefile - $(MAKE) $(PACKAGE).pot - if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \ - cd $(srcdir); \ - catalogs='$(GMOFILES)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - echo "$$lang:"; \ - if $(MSGMERGE) $$lang.po $(PACKAGE).pot -o $$lang.new.po; then \ - mv -f $$lang.new.po $$lang.po; \ - else \ - echo "msgmerge for $$cat failed!"; \ - rm -f $$lang.new.po; \ - fi; \ - done - $(MAKE) update-gmo - -update-gmo: Makefile $(GMOFILES) - @: - -Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ - $(SHELL) ./config.status - -# Tell versions [3.59,3.63) of GNU make not to export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in deleted file mode 100644 index 4e52a3a..0000000 --- a/po/POTFILES.in +++ /dev/null @@ -1,33 +0,0 @@ -# List of files which contain translatable strings. -# Copyright (C) 1999,2000 Ivo Timmermans - -# Package source files - -lib/pidfile.c -lib/utils.c -src/conf.c -src/connection.c -src/meta.c -src/net.c -src/net_packet.c -src/net_setup.c -src/net_socket.c -src/netutl.c -src/protocol.c -src/protocol_auth.c -src/protocol_edge.c -src/protocol_key.c -src/protocol_misc.c -src/protocol_subnet.c -src/subnet.c -src/tincd.c -src/process.c -src/route.c -src/node.c -src/edge.c -src/graph.c -src/linux/device.c -src/freebsd/device.c -src/solaris/device.c -src/netbsd/device.c -src/openbsd/device.c diff --git a/po/nl.gmo b/po/nl.gmo deleted file mode 100644 index cf84ba6..0000000 Binary files a/po/nl.gmo and /dev/null differ diff --git a/po/nl.po b/po/nl.po deleted file mode 100644 index 4288fee..0000000 --- a/po/nl.po +++ /dev/null @@ -1,1288 +0,0 @@ -# Dutch messages for tinc -# Copyright (C) 1999-2001 Ivo Timmermans, Guus Sliepen. -# Ivo Timmermans , 1999-2002. -# Guus Sliepen , 2000-2002. -msgid "" -msgstr "" -"Project-Id-Version: tinc 1.0-cvs\n" -"POT-Creation-Date: 2002-04-09 13:59+0200\n" -"PO-Revision-Date: 2002-03-27 16:59+0100\n" -"Last-Translator: Guus Sliepen \n" -"Language-Team: Dutch \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: src/conf.c:173 -#, c-format -msgid "\"yes\" or \"no\" expected for configuration variable %s in %s line %d" -msgstr "" -"\"ja\" of \"nee\" verwacht voor configuratievariabele %s in %s regel %d" - -#: src/conf.c:188 -#, c-format -msgid "Integer expected for configuration variable %s in %s line %d" -msgstr "Geheel getal verwacht voor configuratievariabele %s in %s regel %d" - -#: src/conf.c:218 -#, c-format -msgid "" -"Hostname or IP address expected for configuration variable %s in %s line %d" -msgstr "" -"Hostnaam of IP adres verwacht voor configuratievariabele %s in %s regel %d" - -#: src/conf.c:235 -#, c-format -msgid "Port number expected for configuration variable %s in %s line %d" -msgstr "Poortnummer verwacht voor configuratievariabele %s in %s regel %d" - -#: src/conf.c:251 -#, c-format -msgid "Subnet expected for configuration variable %s in %s line %d" -msgstr "Subnet verwacht voor configuratievariabele %s in %s regel %d" - -#: src/conf.c:261 -#, c-format -msgid "" -"Network address and prefix length do not match for configuration variable %s " -"in %s line %d" -msgstr "" -"Netwerk adres en prefix lengte komen niet overeen bij configuratievariabele %" -"s in %s regel %d" - -#: src/conf.c:369 -#, c-format -msgid "Cannot open config file %s: %s" -msgstr "Kan configuratie bestand %s niet openen: %s" - -#: src/conf.c:405 -#, c-format -msgid "No value for variable `%s' on line %d while reading config file %s" -msgstr "" -"Geen waarde voor variabele `%s' op regel %d tijdens het lezen van " -"configuratie bestand %s" - -#: src/conf.c:438 -#, c-format -msgid "Failed to read `%s': %s" -msgstr "Lezen van `%s' mislukte: %s" - -#: src/conf.c:465 -#, c-format -msgid "`%s' is not an absolute path" -msgstr "`%s' is geen absoluut pad" - -#: src/conf.c:481 src/conf.c:513 -#, c-format -msgid "Couldn't stat `%s': %s" -msgstr "Kon `%s' niet statten: %s" - -#: src/conf.c:487 src/conf.c:522 -#, c-format -msgid "`%s' is owned by UID %d instead of %d" -msgstr "`%s' is eigendom van UID %d in plaats van %d" - -#: src/conf.c:494 src/conf.c:529 -#, c-format -msgid "Warning: `%s' is a symlink" -msgstr "Waarschuwing: `%s' is een symbolische link" - -#: src/conf.c:499 src/conf.c:534 -#, c-format -msgid "Unable to read symbolic link `%s': %s" -msgstr "Kan symbolische link `%s' niet lezen: %s" - -#. Accessible by others -#: src/conf.c:545 -#, c-format -msgid "`%s' has unsecure permissions" -msgstr "`%s' heeft onveilige permissies" - -#. Ask for a file and/or directory name. -#: src/conf.c:570 -#, c-format -msgid "Please enter a file to save %s to [%s]: " -msgstr "Geef een bestand om de %s naar de schrijven [%s]: " - -#: src/conf.c:576 -#, c-format -msgid "Error while reading stdin: %s\n" -msgstr "Fout tijdens lezen van standaardinvoer: %s\n" - -#: src/conf.c:602 -#, c-format -msgid "Error opening file `%s': %s\n" -msgstr "Fout bij het openen van het bestand `%s': %s\n" - -#: src/conf.c:612 -#, c-format -msgid "" -"The file `%s' (or any of the leading directories) has unsafe permissions.\n" -"I will not create or overwrite this file.\n" -msgstr "" -"Het bestand `%s' (of een van de voorgaande mappen) heeft onvoldoende " -"bescherming.\n" -"Ik maak of overschrijf dit bestand niet.\n" - -#: src/connection.c:114 -msgid "Connections:" -msgstr "Verbindingen:" - -#: src/connection.c:119 -#, c-format -msgid " %s at %s options %lx socket %d status %04x" -msgstr " %s op %s opties %lx socket %d status %04x" - -#: src/connection.c:123 -msgid "End of connections." -msgstr "Einde van verbindingen." - -#: src/meta.c:49 -#, c-format -msgid "Sending %d bytes of metadata to %s (%s)" -msgstr "Verzenden van %d bytes metadata naar %s (%s)" - -#: src/meta.c:63 -#, c-format -msgid "Sending meta data to %s (%s) failed: %s" -msgstr "Fout tijdens verzenden metadata naar %s (%s): %s" - -#: src/meta.c:94 -#, c-format -msgid "This is a bug: %s:%d: %d:%s %s (%s)" -msgstr "Dit is een programmeerfout: %s:%d: %d:%s %s (%s)" - -#: src/meta.c:100 -#, c-format -msgid "Metadata socket error for %s (%s): %s" -msgstr "Fout op metadata socket voor %s (%s): %s" - -#: src/meta.c:121 -#, c-format -msgid "Connection closed by %s (%s)" -msgstr "Verbinding beëindigd door %s (%s)" - -#: src/meta.c:128 -#, c-format -msgid "Metadata socket read error for %s (%s): %s" -msgstr "Fout op metadata socket voor %s (%s) tijdens lezen: %s" - -#: src/meta.c:202 -#, c-format -msgid "Metadata read buffer overflow for %s (%s)" -msgstr "Metadata leesbuffer overloop voor %s (%s)" - -#: src/net.c:88 -msgid "Purging unreachable nodes" -msgstr "Verwijderen onbereikbare nodes" - -#: src/net.c:98 -#, c-format -msgid "Purging node %s (%s)" -msgstr "Verwijdering node %s (%s)" - -#: src/net.c:188 -#, c-format -msgid "Closing connection with %s (%s)" -msgstr "Beëindigen verbinding met %s (%s)" - -#: src/net.c:253 -#, c-format -msgid "%s (%s) didn't respond to PING" -msgstr "%s (%s) antwoordde niet op ping" - -#: src/net.c:266 -#, c-format -msgid "Timeout from %s (%s) during authentication" -msgstr "Timeout van %s (%s) tijdens authenticatie" - -#: src/net.c:311 src/net_socket.c:253 -#, c-format -msgid "Error while connecting to %s (%s): %s" -msgstr "Fout tijdens schrijven naar %s (%s): %s" - -#: src/net.c:363 -#, c-format -msgid "Error while waiting for input: %s" -msgstr "Fout tijdens wachten op invoer: %s" - -#: src/net.c:397 -msgid "Regenerating symmetric key" -msgstr "Hergenereren symmetrische sleutel" - -#: src/net.c:414 -msgid "Flushing event queue" -msgstr "Legen taakrij" - -#: src/net.c:431 -msgid "Rereading configuration file and restarting in 5 seconds..." -msgstr "Herlezen configuratiebestand en herstarten na 5 seconden..." - -#: src/net.c:438 -msgid "Unable to reread configuration file, exitting." -msgstr "Kan configuratiebestand niet herlezen, beëindigen." - -#: src/net_packet.c:107 -#, c-format -msgid "Got unauthenticated packet from %s (%s)" -msgstr "Kreeg niet-geauthenticeerd pakket van %s (%s)" - -#: src/net_packet.c:134 -#, c-format -msgid "Got late or replayed packet from %s (%s), seqno %d" -msgstr "Kreeg laat of gedupliceerd pakket van %s (%s), seqno %d" - -#: src/net_packet.c:151 -#, c-format -msgid "Error while uncompressing packet from %s (%s)" -msgstr "Fout tijdens decomprimeren pakket van %s (%s)" - -#: src/net_packet.c:178 -#, c-format -msgid "Received packet of %d bytes from %s (%s)" -msgstr "Ontvangst pakket van %d bytes van %s (%s)" - -#: src/net_packet.c:204 -#, c-format -msgid "No valid key known yet for %s (%s), queueing packet" -msgstr "" -"Nog geen geldige sleutel bekend voor %s (%s), pakket wordt in wachtrij gezet" - -#: src/net_packet.c:237 -#, c-format -msgid "Error while compressing packet to %s (%s)" -msgstr "Fout tijdens comprimeren pakket naar %s (%s)" - -#: src/net_packet.c:288 -#, c-format -msgid "Setting outgoing packet priority to %d" -msgstr "Instellen prioriteit uitgaand pakket op %d" - -#. SO_PRIORITY doesn't seem to work -#: src/net_packet.c:290 src/net_setup.c:450 src/net_socket.c:98 -#: src/net_socket.c:144 src/net_socket.c:171 src/process.c:273 -#: src/process.c:310 -#, c-format -msgid "System call `%s' failed: %s" -msgstr "Systeemaanroep `%s' mislukte: %s" - -#: src/net_packet.c:296 -#, c-format -msgid "Error sending packet to %s (%s): %s" -msgstr "Fout tijdens verzenden pakket naar %s (%s): %s" - -#: src/net_packet.c:313 -#, c-format -msgid "Sending packet of %d bytes to %s (%s)" -msgstr "Verzending pakket van %d bytes naar %s (%s)" - -#: src/net_packet.c:320 -msgid "Packet is looping back to us!" -msgstr "Pakket komt terug naar ons!" - -#: src/net_packet.c:329 -#, c-format -msgid "Node %s (%s) is not reachable" -msgstr "Node %s (%s) is niet bereikbaar" - -#: src/net_packet.c:337 -#, c-format -msgid "Sending packet to %s via %s (%s)" -msgstr "Verzending pakket naar %s via %s (%s)" - -#: src/net_packet.c:357 -#, c-format -msgid "Broadcasting packet of %d bytes from %s (%s)" -msgstr "Verspreiding pakket van %d bytes van %s (%s)" - -#: src/net_packet.c:374 -#, c-format -msgid "Flushing queue for %s (%s)" -msgstr "Legen van wachtrij voor %s (%s)" - -#: src/net_packet.c:396 -#, c-format -msgid "This is a bug: %s:%d: %d:%s" -msgstr "Dit is een programmeerfout: %s:%d: %d:%s" - -#: src/net_packet.c:403 -#, c-format -msgid "Incoming data socket error: %s" -msgstr "Fout op socket voor inkomend verkeer: %s" - -#: src/net_packet.c:409 -#, c-format -msgid "Receiving packet failed: %s" -msgstr "Ontvangst pakket mislukt: %s" - -#: src/net_packet.c:420 -#, c-format -msgid "Received UDP packet from unknown source %s" -msgstr "Ontvangst UDP pakket van onbekende oorsprong %s" - -#: src/net_setup.c:102 -#, c-format -msgid "Error reading RSA public key file `%s': %s" -msgstr "Fout tijdens lezen RSA publieke sleutel bestand `%s': %s" - -#: src/net_setup.c:112 -#, c-format -msgid "Reading RSA public key file `%s' failed: %s" -msgstr "Lezen RSA publieke sleutel bestand `%s' mislukt: %s" - -#: src/net_setup.c:140 -#, c-format -msgid "No public key for %s specified!" -msgstr "Geen publieke sleutel bekend voor %s gespecificeerd!" - -#: src/net_setup.c:166 -#, c-format -msgid "Error reading RSA private key file `%s': %s" -msgstr "Fout tijdens lezen RSA privé sleutel bestand `%s': %s" - -#: src/net_setup.c:176 -#, c-format -msgid "Reading RSA private key file `%s' failed: %s" -msgstr "Fout tijdens lezen RSA privé sleutel bestand `%s': %s" - -#: src/net_setup.c:202 src/net_setup.c:203 -msgid "MYSELF" -msgstr "MIJZELF" - -#: src/net_setup.c:210 -msgid "Name for tinc daemon required!" -msgstr "Naam voor tinc daemon verplicht!" - -#: src/net_setup.c:216 -msgid "Invalid name for myself!" -msgstr "Ongeldige naam voor mijzelf!" - -#: src/net_setup.c:230 -msgid "Cannot open host configuration file for myself!" -msgstr "Kan host configuratie bestand voor mijzelf niet openen!" - -#: src/net_setup.c:287 -msgid "Invalid routing mode!" -msgstr "Ongeldige routing modus!" - -#: src/net_setup.c:298 -msgid "PriorityInheritance not supported on this platform" -msgstr "PriorityInheritance wordt niet ondersteund op dit platform" - -#: src/net_setup.c:308 -msgid "Bogus maximum timeout!" -msgstr "Onzinnige maximum timeout!" - -#: src/net_setup.c:325 -msgid "Invalid address family!" -msgstr "Ongeldige adresfamilie!" - -#: src/net_setup.c:347 -msgid "Unrecognized cipher type!" -msgstr "Onbekend cipher type!" - -#: src/net_setup.c:382 -msgid "Unrecognized digest type!" -msgstr "Onbekend digest type!" - -#: src/net_setup.c:398 -msgid "MAC length exceeds size of digest!" -msgstr "MAC lengte is groter dan dat van digest!" - -#: src/net_setup.c:403 -msgid "Bogus MAC length!" -msgstr "Onzinnige MAC lengte!" - -#: src/net_setup.c:419 -msgid "Bogus compression level!" -msgstr "Onzinnig compressieniveau!" - -#: src/net_setup.c:465 -#, c-format -msgid "Listening on %s" -msgstr "Luisterend op %s" - -#: src/net_setup.c:476 -msgid "Ready" -msgstr "Gereed" - -#: src/net_setup.c:479 -msgid "Unable to create any listening socket!" -msgstr "Kon geen enkele luistersocket aanmaken!" - -#: src/net_socket.c:90 -#, c-format -msgid "Creating metasocket failed: %s" -msgstr "Aanmaak van metasocket mislukt: %s" - -#: src/net_socket.c:124 src/net_socket.c:186 -#, c-format -msgid "Can't bind to interface %s: %s" -msgstr "Kan niet aan interface %s binden: %s" - -#: src/net_socket.c:128 -msgid "BindToDevice not supported on this platform" -msgstr "BindToDevice wordt niet ondersteund op dit platform" - -#: src/net_socket.c:136 -#, c-format -msgid "Can't bind to %s/tcp: %s" -msgstr "Kan niet aan %s/tcp binden: %s" - -#: src/net_socket.c:163 -#, c-format -msgid "Creating UDP socket failed: %s" -msgstr "Aanmaak UDP socket mislukte: %s" - -#: src/net_socket.c:196 -#, c-format -msgid "Can't bind to %s/udp: %s" -msgstr "Kan niet aan %s/udp binden: %s" - -#: src/net_socket.c:219 -#, c-format -msgid "Trying to re-establish outgoing connection in %d seconds" -msgstr "Poging tot herstellen van uitgaande verbinding over %d seconden" - -#: src/net_socket.c:228 src/net_socket.c:322 -#, c-format -msgid "Trying to connect to %s (%s)" -msgstr "Poging tot verbinden met %s (%s)" - -#: src/net_socket.c:234 src/net_socket.c:329 -#, c-format -msgid "Creating socket for %s failed: %s" -msgstr "Aanmaken socket voor %s mislukt: %s" - -#: src/net_socket.c:258 src/net_socket.c:268 -#, c-format -msgid "Connected to %s (%s)" -msgstr "Verbonden met %s (%s)" - -#: src/net_socket.c:287 -#, c-format -msgid "Could not set up a meta connection to %s" -msgstr "Kon geen metaverbinding aangaan met %s" - -#: src/net_socket.c:350 -#, c-format -msgid "fcntl for %s: %s" -msgstr "fcntl voor %s: %s" - -#: src/net_socket.c:368 -#, c-format -msgid "%s: %s" -msgstr "%s: %s" - -#: src/net_socket.c:389 -#, c-format -msgid "Already connected to %s" -msgstr "Reeds verbonden met %s" - -#: src/net_socket.c:408 -#, c-format -msgid "No address specified for %s" -msgstr "Geen adres gespecificeerd voor %s" - -#: src/net_socket.c:435 -#, c-format -msgid "Accepting a new connection failed: %s" -msgstr "Aanname van nieuwe verbinding is mislukt: %s" - -#: src/net_socket.c:453 -#, c-format -msgid "Connection from %s" -msgstr "Verbinding van %s" - -#: src/net_socket.c:475 -#, c-format -msgid "Invalid name for outgoing connection in %s line %d" -msgstr "Ongeldige naam voor uitgaande verbinding in %s regel %d" - -#: src/netutl.c:65 src/netutl.c:88 -#, c-format -msgid "Error looking up %s port %s: %s\n" -msgstr "Fout bij het opzoeken van %s poort %s: %s\n" - -#: src/netutl.c:109 -#, c-format -msgid "Error while translating addresses: %s" -msgstr "Fout tijdens vertalen adressen: %s" - -#: src/netutl.c:134 -#, c-format -msgid "Error while looking up hostname: %s" -msgstr "Fout bij het opzoeken van hostnaam: %s" - -#: src/netutl.c:137 -#, c-format -msgid "%s port %s" -msgstr "%s poort %s" - -#: src/netutl.c:166 -#, c-format -msgid "sockaddrcmp() was called with unknown address family %d, exitting!" -msgstr "" -"sockaddrcmp() werd aangeroepen met onbekende adresfamilie %d, beëindigen!" - -#: src/protocol.c:77 -#, c-format -msgid "Output buffer overflow while sending request to %s (%s)" -msgstr "Uitvoer buffer overvol tijdens zenden verzoek naar %s (%s)" - -#: src/protocol.c:85 -#, c-format -msgid "Sending %s to %s (%s): %s" -msgstr "Verzending %s naar %s (%s): %s" - -#: src/protocol.c:87 -#, c-format -msgid "Sending %s to %s (%s)" -msgstr "Verzending %s naar %s (%s)" - -#: src/protocol.c:104 -#, c-format -msgid "Unknown request from %s (%s): %s" -msgstr "Onbekend verzoek van %s (%s): %s" - -#: src/protocol.c:107 -#, c-format -msgid "Unknown request from %s (%s)" -msgstr "Onbekend verzoek van %s (%s)" - -#: src/protocol.c:117 -#, c-format -msgid "Got %s from %s (%s): %s" -msgstr "Kreeg %s van %s (%s): %s" - -#: src/protocol.c:120 -#, c-format -msgid "Got %s from %s (%s)" -msgstr "Kreeg %s van %s (%s)" - -#: src/protocol.c:127 -#, c-format -msgid "Unauthorized request from %s (%s)" -msgstr "Niet toegestaan verzoek van %s (%s)" - -#: src/protocol.c:134 -#, c-format -msgid "Error while processing %s from %s (%s)" -msgstr "Fout tijdens afhandelen %s van %s (%s)" - -#: src/protocol.c:141 -#, c-format -msgid "Bogus data received from %s (%s)" -msgstr "Onzinnige data ontvangen van %s (%s)" - -#: src/protocol.c:187 -msgid "Already seen request" -msgstr "Verzoek reeds gezien" - -#: src/protocol.c:218 -#, c-format -msgid "Aging past requests: deleted %d, left %d\n" -msgstr "Veroudering vorige verzoeken: %d gewist, %d overgebleven\n" - -#: src/protocol_auth.c:69 src/protocol_auth.c:224 src/protocol_auth.c:357 -#: src/protocol_auth.c:417 src/protocol_auth.c:529 src/protocol_edge.c:90 -#: src/protocol_edge.c:219 src/protocol_key.c:80 src/protocol_key.c:128 -#: src/protocol_key.c:196 src/protocol_misc.c:61 src/protocol_misc.c:91 -#: src/protocol_misc.c:177 src/protocol_subnet.c:71 src/protocol_subnet.c:163 -#, c-format -msgid "Got bad %s from %s (%s)" -msgstr "Kreeg verkeerde %s van %s (%s)" - -#: src/protocol_auth.c:77 src/protocol_edge.c:98 src/protocol_edge.c:104 -#: src/protocol_edge.c:228 src/protocol_edge.c:234 src/protocol_subnet.c:79 -#: src/protocol_subnet.c:87 src/protocol_subnet.c:171 -#: src/protocol_subnet.c:189 -#, c-format -msgid "Got bad %s from %s (%s): %s" -msgstr "Kreeg verkeerde %s van %s (%s): %s" - -#: src/protocol_auth.c:87 -#, c-format -msgid "Peer %s is %s instead of %s" -msgstr "Ander %s is %s in plaats van %s" - -#: src/protocol_auth.c:98 -#, c-format -msgid "Peer %s (%s) uses incompatible version %d" -msgstr "Ander %s (%s) gebruikt incompatibele versie %d" - -#: src/protocol_auth.c:117 -#, c-format -msgid "Peer %s had unknown identity (%s)" -msgstr "Ander %s heeft onbekende identiteit (%s)" - -#: src/protocol_auth.c:175 -#, c-format -msgid "Generated random meta key (unencrypted): %s" -msgstr "Willekeurige meta sleutel aangemaakt (niet versleuteld): %s" - -#: src/protocol_auth.c:187 src/protocol_auth.c:254 -#, c-format -msgid "Error during encryption of meta key for %s (%s)" -msgstr "Fout tijdens versleutelen van meta key voor %s (%s)" - -#: src/protocol_auth.c:234 src/protocol_auth.c:367 src/protocol_auth.c:425 -#: src/protocol_auth.c:443 -#, c-format -msgid "Possible intruder %s (%s): %s" -msgstr "Mogelijke indringer %s (%s): %s" - -#: src/protocol_auth.c:262 -#, c-format -msgid "Received random meta key (unencrypted): %s" -msgstr "Ontving willekeurige meta key (niet versleuteld): %s" - -#: src/protocol_auth.c:274 -#, c-format -msgid "%s (%s) uses unknown cipher!" -msgstr "%s (%s) gebruikt onbekende cipher!" - -#: src/protocol_auth.c:296 src/protocol_key.c:267 -#, c-format -msgid "Node %s (%s) uses unknown digest!" -msgstr "Node %s (%s) gebruikt onbekende digest!" - -#: src/protocol_auth.c:302 -#, c-format -msgid "%s (%s) uses bogus MAC length!" -msgstr "%s (%s) gebruikt onzinnige MAC lengte!" - -#: src/protocol_auth.c:425 -msgid "wrong challenge reply length" -msgstr "verkeerde lengte antwoord op uitdaging" - -#: src/protocol_auth.c:443 -msgid "wrong challenge reply" -msgstr "verkeerd antwoord op uitdaging" - -#: src/protocol_auth.c:448 -#, c-format -msgid "Expected challenge reply: %s" -msgstr "Verwachtte antwoord op uitdaging: %s" - -#: src/protocol_auth.c:549 -#, c-format -msgid "Established a second connection with %s (%s), closing old connection" -msgstr "Tweede verbinding met %s (%s) gemaakt, oude verbinding wordt gesloten" - -#: src/protocol_auth.c:583 -#, c-format -msgid "Connection with %s (%s) activated" -msgstr "Verbinding met %s (%s) geactiveerd" - -#: src/protocol_edge.c:98 src/protocol_edge.c:104 src/protocol_edge.c:228 -#: src/protocol_edge.c:234 src/protocol_subnet.c:79 src/protocol_subnet.c:171 -msgid "invalid name" -msgstr "ongeldige naam" - -#: src/protocol_edge.c:150 -#, c-format -msgid "Got %s from %s (%s) for ourself which does not match existing entry" -msgstr "" -"Kreeg %s van %s (%s) voor onszelf welke niet overeenkomt met reeds bekende" - -#: src/protocol_edge.c:157 -#, c-format -msgid "Got %s from %s (%s) which does not match existing entry" -msgstr "Kreeg %s van %s (%s) welke niet overeenkomt met reeds bekende" - -#: src/protocol_edge.c:167 -#, c-format -msgid "Got %s from %s (%s) for ourself which does not exist" -msgstr "Kreeg %s van %s (%s) voor onszelf welke niet bestaat" - -#: src/protocol_edge.c:248 src/protocol_edge.c:257 src/protocol_edge.c:268 -#, c-format -msgid "Got %s from %s (%s) which does not appear in the edge tree" -msgstr "Kreeg %s van %s (%s) welke niet voorkomt in de edge tree" - -#: src/protocol_edge.c:275 src/protocol_subnet.c:118 src/protocol_subnet.c:217 -#, c-format -msgid "Got %s from %s (%s) for ourself" -msgstr "Kreeg %s van %s (%s) voor onszelf" - -#: src/protocol_key.c:92 -#, c-format -msgid "Got %s from %s (%s) origin %s which does not exist" -msgstr "Kreeg %s van %s (%s) herkomst %s welke niet bestaat" - -#: src/protocol_key.c:137 src/protocol_key.c:205 -#, c-format -msgid "" -"Got %s from %s (%s) origin %s which does not exist in our connection list" -msgstr "" -"Kreeg %s van %s (%s) herkomst %s welke niet voorkomt in de verbindingslijst" - -#: src/protocol_key.c:146 src/protocol_key.c:214 -#, c-format -msgid "" -"Got %s from %s (%s) destination %s which does not exist in our connection " -"list" -msgstr "" -"Kreeg %s van %s (%s) doel %s welke niet voorkomt in de verbindingslijst" - -#: src/protocol_key.c:246 -#, c-format -msgid "Node %s (%s) uses unknown cipher!" -msgstr "Node %s (%s) gebruikt onbekende cipher!" - -#: src/protocol_key.c:251 -#, c-format -msgid "Node %s (%s) uses wrong keylength!" -msgstr "Node %s (%s) gebruikt verkeerde lengte sleutel!" - -#: src/protocol_key.c:272 -#, c-format -msgid "Node %s (%s) uses bogus MAC length!" -msgstr "Node %s (%s) gebruikt onzinnige MAC lengte!" - -#: src/protocol_misc.c:68 -#, c-format -msgid "Status message from %s (%s): %s: %s" -msgstr "Statusmelding van %s (%s): %s: %s" - -#: src/protocol_misc.c:98 -#, c-format -msgid "Error message from %s (%s): %s: %s" -msgstr "Foutmelding van %s (%s): %s: %s" - -#: src/protocol_subnet.c:87 src/protocol_subnet.c:189 -msgid "invalid subnet string" -msgstr "ongeldige subnet string" - -#: src/protocol_subnet.c:180 -#, c-format -msgid "Got %s from %s (%s) for %s which is not in our node tree" -msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in de node boom" - -#: src/protocol_subnet.c:207 -#, c-format -msgid "Got %s from %s (%s) for %s which does not appear in his subnet tree" -msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in zijn subnet boom" - -#: src/subnet.c:99 -#, c-format -msgid "subnet_compare() was called with unknown subnet type %d, exitting!" -msgstr "" -"subnet_compare() werd aangeroepen met onbekend subnet type %d, beëindigen!" - -#: src/subnet.c:274 -#, c-format -msgid "net2str() was called with unknown subnet type %d, exitting!" -msgstr "net2str() werd aangeroepen met onbekend subnet type %d, beëindigen!" - -#: src/subnet.c:384 -msgid "Subnet list:" -msgstr "Subnet lijst:" - -#: src/subnet.c:389 -#, c-format -msgid " %s owner %s" -msgstr " %s eigenaar %s" - -#: src/subnet.c:392 -msgid "End of subnet list." -msgstr "Einde van subnet lijst." - -#: src/tincd.c:100 -#, c-format -msgid "Try `%s --help' for more information.\n" -msgstr "Probeer `%s --help' voor meer informatie.\n" - -#: src/tincd.c:103 -#, c-format -msgid "" -"Usage: %s [option]...\n" -"\n" -msgstr "" -"Gebruik: %s [optie]...\n" -"\n" - -#: src/tincd.c:104 -msgid "" -" -c, --config=DIR Read configuration options from DIR.\n" -" -D, --no-detach Don't fork and detach.\n" -" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" -" -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" -" -n, --net=NETNAME Connect to net NETNAME.\n" -msgstr "" -" -c, --config=MAP Lees configuratie uit MAP.\n" -" -D, --no-detach Start geen nieuw proces.\n" -" -d, --debug[=NIVEAU] Verhoog debugniveau of stel het in op NIVEAU.\n" -" -k, --kill[=SIGNAAL] Poging tot zenden signaal naar lopende tincd en " -"beëindig.\n" -" -n, --net=NETNAAM Verbind met net NETNAAM.\n" - -#: src/tincd.c:109 -msgid "" -" -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" -" --help Display this help and exit.\n" -" --version Output version information and exit.\n" -"\n" -msgstr "" -" -K, --generate-keys[=BITS] Genereer publiek/privé RSA sleutelpaar.\n" -" --help Geef deze hulp en beëindig.\n" -" --version Geef versie informatie en beëindig.\n" -"\n" - -#: src/tincd.c:112 -msgid "Report bugs to tinc@nl.linux.org.\n" -msgstr "" -"Meld fouten in het programma aan tinc@nl.linux.org;\n" -"Meld fouten in de vertaling aan vertaling@nl.linux.org.\n" - -#: src/tincd.c:166 -#, c-format -msgid "" -"Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, " -"USR1, USR2, WINCH, INT or ALRM.\n" -msgstr "" -"Ongeldig argument `%s'; SIGNAAL moet een getal zijn of één van HUP, TERM, " -"KILL, USR1, USR2, WINCH, INT of ALRM.\n" - -#: src/tincd.c:184 -#, c-format -msgid "" -"Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n" -msgstr "" -"Ongeldig argument `%s'; BITS moet een nummer zijn gelijk aan of groter dan " -"512.\n" - -#: src/tincd.c:245 -#, c-format -msgid "Generating %d bits keys:\n" -msgstr "Bezig met genereren van een %d bits sleutel:\n" - -#: src/tincd.c:250 -msgid "Error during key generation!\n" -msgstr "Fout tijdens genereren sleutel!\n" - -#: src/tincd.c:254 -msgid "Done.\n" -msgstr "Klaar.\n" - -#: src/tincd.c:263 -msgid "public RSA key" -msgstr "openbare RSA sleutel" - -#: src/tincd.c:267 src/tincd.c:278 -msgid "" -"Appending key to existing contents.\n" -"Make sure only one key is stored in the file.\n" -msgstr "" -"Sleutel wordt toegevoegd aan bestaande inhoud.\n" -"Let er op dat er slechts één sleutel in het bestand is.\n" - -#: src/tincd.c:274 -msgid "private RSA key" -msgstr "geheime RSA sleutel" - -#: src/tincd.c:299 -msgid "Both netname and configuration directory given, using the latter..." -msgstr "" -"Zowel netnaam als configuratiemap zijn gegeven, laatste wordt gebruikt..." - -#: src/tincd.c:328 -#, c-format -msgid "%s version %s (built %s %s, protocol %d)\n" -msgstr "%s versie %s (gemaakt %s %s, protocol %d)\n" - -#: src/tincd.c:329 -msgid "" -"Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n" -"See the AUTHORS file for a complete list.\n" -"\n" -"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" -"and you are welcome to redistribute it under certain conditions;\n" -"see the file COPYING for details.\n" -msgstr "" -"Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen en anderen.\n" -"Zie het bestand AUTHORS voor een volledige lijst.\n" -"\n" -"tinc wordt gedistribueerd ZONDER ENIGE GARANTIE. Dit is vrije " -"programmatuur,\n" -"en je bent welkom om het te distribueren onder bepaalde voorwaarden;\n" -"zie het bestand COPYING voor details.\n" - -#: src/tincd.c:386 -msgid "Unrecoverable error" -msgstr "Onherstelbare fout" - -#: src/tincd.c:391 -#, c-format -msgid "Restarting in %d seconds!" -msgstr "Herstart in %d seconden!" - -#: src/process.c:373 src/tincd.c:396 -msgid "Not restarting." -msgstr "Geen herstart." - -#: src/process.c:69 -#, c-format -msgid "Memory exhausted (couldn't allocate %d bytes), exitting." -msgstr "Geheugen uitgeput (kon geen %d bytes reserveren), beëindigen." - -#: src/process.c:100 -msgid "Terminating" -msgstr "Beëindigen" - -#: src/process.c:116 -#, c-format -msgid "A tincd is already running for net `%s' with pid %d.\n" -msgstr "Een tincd draait al voor net `%s' met pid %d.\n" - -#: src/process.c:119 -#, c-format -msgid "A tincd is already running with pid %d.\n" -msgstr "Een tincd draait al met pid %d.\n" - -#: src/process.c:140 -#, c-format -msgid "No other tincd is running for net `%s'.\n" -msgstr "Geen andere tincd draait voor net `%s'.\n" - -#: src/process.c:142 -msgid "No other tincd is running.\n" -msgstr "Geen andere tincd draait.\n" - -#: src/process.c:151 -#, c-format -msgid "The tincd for net `%s' is no longer running. " -msgstr "De tincd voor net `%s' draait niet meer. " - -#: src/process.c:153 -msgid "The tincd is no longer running. " -msgstr "De tincd draait niet meer. " - -#: src/process.c:155 -msgid "Removing stale lock file.\n" -msgstr "Verwijdering oud vergrendelingsbestand.\n" - -#: src/process.c:183 -#, c-format -msgid "Couldn't detach from terminal: %s" -msgstr "Kon niet ontkoppelen van terminal: %s" - -#: src/process.c:196 -#, c-format -msgid "tincd %s (%s %s) starting, debug level %d" -msgstr "tincd %s (%s %s) start, debug niveau %d" - -#: src/process.c:199 -#, c-format -msgid "tincd %s starting" -msgstr "tincd %s wordt gestart" - -#: src/process.c:280 -#, c-format -msgid "Executing script %s" -msgstr "Uitvoeren script %s" - -#: src/process.c:290 -#, c-format -msgid "Process %d (%s) exited with non-zero status %d" -msgstr "Proces %d (%s) beëindigde met status %d" - -#: src/process.c:298 -#, c-format -msgid "Process %d (%s) was killed by signal %d (%s)" -msgstr "Proces %d (%s) was gestopt door signaal %d (%s)" - -#: src/process.c:304 -#, c-format -msgid "Process %d (%s) terminated abnormally" -msgstr "Proces %d (%s) abnormaal beëindigd" - -#: src/process.c:329 -msgid "Got TERM signal" -msgstr "Kreeg TERM signaal" - -#: src/process.c:338 -msgid "Got QUIT signal" -msgstr "Kreeg QUIT signaal" - -#: src/process.c:345 -#, c-format -msgid "Got another fatal signal %d (%s): not restarting." -msgstr "Kreeg nog een fataal signaal %s (%s): geen herstart." - -#: src/process.c:354 -#, c-format -msgid "Got fatal signal %d (%s)" -msgstr "Kreeg fataal signaal %d (%s)" - -#: src/process.c:359 -msgid "Trying to re-execute in 5 seconds..." -msgstr "Poging tot herstarten over 5 seconden..." - -#: src/process.c:382 -msgid "Got HUP signal" -msgstr "Kreeg HUP signaal" - -#: src/process.c:391 -#, c-format -msgid "Reverting to old debug level (%d)" -msgstr "Herstellen van oud debug niveau (%d)" - -#: src/process.c:398 -#, c-format -msgid "" -"Temporarily setting debug level to 5. Kill me with SIGINT again to go back " -"to level %d." -msgstr "" -"Tijdelijk instellen debug niveau op 5. Zend nog een SIGINT signaal om niveau " -"%d te herstellen." - -#: src/process.c:409 -msgid "Got ALRM signal" -msgstr "Kreeg ALRM signaal" - -#: src/process.c:438 -#, c-format -msgid "Got unexpected signal %d (%s)" -msgstr "Kreeg onverwacht signaal %d (%s)" - -#: src/process.c:447 -#, c-format -msgid "Ignored signal %d (%s)" -msgstr "Signaal %d (%s) genegeerd" - -#: src/process.c:504 -#, c-format -msgid "Installing signal handler for signal %d (%s) failed: %s\n" -msgstr "Installeren van signaal afhandelaar voor signaal %d (%s) faalde: %s\n" - -#: src/route.c:73 -#, c-format -msgid "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx" -msgstr "Nieuw MAC adres %hx:%hx:%hx:%hx:%hx:%hx geleerd" - -#: src/route.c:107 -#, c-format -msgid "MAC address %hx:%hx:%hx:%hx:%hx:%hx expired" -msgstr "MAC adres %hx:%hx:%hx:%hx:%hx:%hx verlopen" - -#: src/route.c:152 -#, c-format -msgid "Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d" -msgstr "Kan pakket niet routeren: onbekend IPv4 doeladres %d.%d.%d.%d" - -#: src/route.c:172 -#, c-format -msgid "" -"Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%" -"hx:%hx:%hx" -msgstr "" -"Kan pakket niet routeren: onbekend IPv6 doeladres %hx:%hx:%hx:%hx:%hx:%hx:%" -"hx:%hx" - -#: src/route.c:233 -msgid "" -"Cannot route packet: received unknown type neighbor solicitation request" -msgstr "" -"Kan pakket niet routeren: ontvangst van onbekend type neighbor solicitation " -"verzoek" - -#: src/route.c:254 -msgid "Cannot route packet: checksum error for neighbor solicitation request" -msgstr "" -"Kan pakket niet routeren: checksum fout voor neighbor solicitation verzoek" - -#: src/route.c:266 -#, c-format -msgid "" -"Cannot route packet: neighbor solicitation request for unknown address %hx:%" -"hx:%hx:%hx:%hx:%hx:%hx:%hx" -msgstr "" -"Kan pakket niet routeren: neighbor solicitation verzoek voor onbekend adres %" -"hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx" - -#: src/route.c:341 -msgid "Cannot route packet: received unknown type ARP request" -msgstr "Kan pakket niet routeren: ontvangst van onbekend type ARP verzoek" - -#: src/route.c:354 -#, c-format -msgid "Cannot route packet: ARP request for unknown address %d.%d.%d.%d" -msgstr "Kan pakket niet routeren: ARP verzoek voor onbekend adres %d.%d.%d.%d" - -#: src/route.c:411 -#, c-format -msgid "Cannot route packet: unknown type %hx" -msgstr "Kan pakket niet routeren: onbekend type %hx" - -#: src/node.c:161 -msgid "Nodes:" -msgstr "Nodes:" - -#: src/node.c:166 -#, c-format -msgid "" -" %s at %s cipher %d digest %d maclength %d compression %d options %lx status " -"%04x nexthop %s via %s" -msgstr "" -" %s op %s cipher %d digest %d maclengte %d compressie %d opties %lx status %" -"04x nexthop %s via %s" - -#: src/node.c:171 -msgid "End of nodes." -msgstr "Einde van nodes." - -#: src/edge.c:194 -msgid "Edges:" -msgstr "Edges:" - -#: src/edge.c:201 -#, c-format -msgid " %s at %s - %s at %s options %lx weight %d" -msgstr " %s op %s - %s op %s opties %lx gewicht %d" - -#: src/edge.c:209 -msgid "End of edges." -msgstr "Einde van edges." - -#: src/graph.c:261 -#, c-format -msgid "Node %s (%s) became reachable" -msgstr "Node %s (%s) werd bereikbaar" - -#: src/graph.c:273 -#, c-format -msgid "Node %s (%s) became unreachable" -msgstr "Node %s (%s) is niet meer bereikbaar" - -#: src/freebsd/device.c:70 src/linux/device.c:89 src/netbsd/device.c:74 -#: src/openbsd/device.c:74 src/solaris/device.c:75 -#, c-format -msgid "Could not open %s: %s" -msgstr "Kon `%s' niet openen: %s" - -#: src/linux/device.c:114 src/linux/device.c:124 -msgid "Linux tun/tap device" -msgstr "Linux tun/tap apparaat" - -#: src/linux/device.c:122 -#, c-format -msgid "Old ioctl() request was needed for %s" -msgstr "Oud ioctl() verzoek was nodig voor %s" - -#: src/linux/device.c:131 -msgid "Linux ethertap device" -msgstr "Linux ethertap apparaat" - -#: src/freebsd/device.c:87 src/linux/device.c:136 src/netbsd/device.c:90 -#: src/openbsd/device.c:90 src/solaris/device.c:132 -#, c-format -msgid "%s is a %s" -msgstr "%s is een %s" - -#: src/freebsd/device.c:108 src/linux/device.c:159 src/linux/device.c:169 -#: src/netbsd/device.c:111 src/openbsd/device.c:111 src/solaris/device.c:149 -#, c-format -msgid "Error while reading from %s %s: %s" -msgstr "Fout tijdens lezen van %s %s: %s" - -#: src/freebsd/device.c:117 src/linux/device.c:180 src/netbsd/device.c:126 -#: src/openbsd/device.c:140 src/solaris/device.c:164 -#, c-format -msgid "Read packet of %d bytes from %s" -msgstr "Pakket van %d bytes gelezen van %s" - -#: src/freebsd/device.c:128 src/linux/device.c:191 src/netbsd/device.c:139 -#: src/openbsd/device.c:154 src/solaris/device.c:175 -#, c-format -msgid "Writing packet of %d bytes to %s" -msgstr "Pakket van %d bytes geschreven naar %s" - -#: src/linux/device.c:198 src/linux/device.c:207 src/netbsd/device.c:149 -#: src/openbsd/device.c:180 src/solaris/device.c:180 -#, c-format -msgid "Can't write to %s %s: %s" -msgstr "Kan niet schrijven naar %s %s: %s" - -#: src/freebsd/device.c:144 src/linux/device.c:220 src/netbsd/device.c:160 -#: src/openbsd/device.c:191 src/solaris/device.c:192 -#, c-format -msgid "Statistics for %s %s:" -msgstr "Statistieken voor %s %s:" - -#: src/freebsd/device.c:145 src/linux/device.c:221 src/netbsd/device.c:161 -#: src/openbsd/device.c:192 src/solaris/device.c:193 -#, c-format -msgid " total bytes in: %10d" -msgstr " totaal aantal bytes in: %10d" - -#: src/freebsd/device.c:146 src/linux/device.c:222 src/netbsd/device.c:162 -#: src/openbsd/device.c:193 src/solaris/device.c:194 -#, c-format -msgid " total bytes out: %10d" -msgstr " totaal aantal bytes uit: %10d" - -#: src/freebsd/device.c:85 -msgid "FreeBSD tap device" -msgstr "FreeBSD tap apparaat" - -#: src/freebsd/device.c:133 -#, c-format -msgid "Error while writing to %s %s: %s" -msgstr "Fout tijdens schrijven naar %s %s: %s" - -#: src/solaris/device.c:86 -#, c-format -msgid "Could not open /dev/ip: %s" -msgstr "Kon /dev/ip niet openen: %s" - -#: src/solaris/device.c:92 -#, c-format -msgid "Can't assign new interface: %s" -msgstr "Kan geen nieuwe interface toekennen: %s" - -#: src/solaris/device.c:97 -#, c-format -msgid "Could not open %s twice: %s" -msgstr "Kon `%s' niet twee keer openen: %s" - -#: src/solaris/device.c:102 -#, c-format -msgid "Can't push IP module: %s" -msgstr "Kan IP module niet invoegen: %s" - -#: src/solaris/device.c:108 -#, c-format -msgid "Can't set PPA %d: %s" -msgstr "Kon PPA %d niet instellen: %s" - -#: src/solaris/device.c:113 -#, c-format -msgid "Can't link TUN device to IP: %s" -msgstr "Kan TUN apparaat niet koppelen aan IP: %s" - -#: src/solaris/device.c:120 -msgid "Solaris tun device" -msgstr "Solaris tun apparaat" - -#: src/netbsd/device.c:88 -msgid "NetBSD tun device" -msgstr "NetBSD tun apparaat" - -#: src/openbsd/device.c:88 -msgid "OpenBSD tun device" -msgstr "OpenBSD tun apparaat" - -#: src/openbsd/device.c:130 -#, c-format -msgid "Unknown address family %d while reading packet from %s %s" -msgstr "Onbekende adresfamilie tijdens lezen pakket van %s %s" - -#: src/openbsd/device.c:169 -#, c-format -msgid "Unknown address family %d while writing packet to %s %s" -msgstr "Onbekende adresfamilie tijdens schrijven pakket naar %s %s" - -#~ msgid "Invalid public/private keypair!" -#~ msgstr "Ongeldig publiek/privé sleutelpaar!" diff --git a/po/tinc.pot b/po/tinc.pot deleted file mode 100644 index 9eb3a62..0000000 --- a/po/tinc.pot +++ /dev/null @@ -1,1232 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR Free Software Foundation, Inc. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2002-04-09 13:59+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: src/conf.c:173 -#, c-format -msgid "\"yes\" or \"no\" expected for configuration variable %s in %s line %d" -msgstr "" - -#: src/conf.c:188 -#, c-format -msgid "Integer expected for configuration variable %s in %s line %d" -msgstr "" - -#: src/conf.c:218 -#, c-format -msgid "" -"Hostname or IP address expected for configuration variable %s in %s line %d" -msgstr "" - -#: src/conf.c:235 -#, c-format -msgid "Port number expected for configuration variable %s in %s line %d" -msgstr "" - -#: src/conf.c:251 -#, c-format -msgid "Subnet expected for configuration variable %s in %s line %d" -msgstr "" - -#: src/conf.c:261 -#, c-format -msgid "" -"Network address and prefix length do not match for configuration variable %s " -"in %s line %d" -msgstr "" - -#: src/conf.c:369 -#, c-format -msgid "Cannot open config file %s: %s" -msgstr "" - -#: src/conf.c:405 -#, c-format -msgid "No value for variable `%s' on line %d while reading config file %s" -msgstr "" - -#: src/conf.c:438 -#, c-format -msgid "Failed to read `%s': %s" -msgstr "" - -#: src/conf.c:465 -#, c-format -msgid "`%s' is not an absolute path" -msgstr "" - -#: src/conf.c:481 src/conf.c:513 -#, c-format -msgid "Couldn't stat `%s': %s" -msgstr "" - -#: src/conf.c:487 src/conf.c:522 -#, c-format -msgid "`%s' is owned by UID %d instead of %d" -msgstr "" - -#: src/conf.c:494 src/conf.c:529 -#, c-format -msgid "Warning: `%s' is a symlink" -msgstr "" - -#: src/conf.c:499 src/conf.c:534 -#, c-format -msgid "Unable to read symbolic link `%s': %s" -msgstr "" - -#. Accessible by others -#: src/conf.c:545 -#, c-format -msgid "`%s' has unsecure permissions" -msgstr "" - -#. Ask for a file and/or directory name. -#: src/conf.c:570 -#, c-format -msgid "Please enter a file to save %s to [%s]: " -msgstr "" - -#: src/conf.c:576 -#, c-format -msgid "Error while reading stdin: %s\n" -msgstr "" - -#: src/conf.c:602 -#, c-format -msgid "Error opening file `%s': %s\n" -msgstr "" - -#: src/conf.c:612 -#, c-format -msgid "" -"The file `%s' (or any of the leading directories) has unsafe permissions.\n" -"I will not create or overwrite this file.\n" -msgstr "" - -#: src/connection.c:114 -msgid "Connections:" -msgstr "" - -#: src/connection.c:119 -#, c-format -msgid " %s at %s options %lx socket %d status %04x" -msgstr "" - -#: src/connection.c:123 -msgid "End of connections." -msgstr "" - -#: src/meta.c:49 -#, c-format -msgid "Sending %d bytes of metadata to %s (%s)" -msgstr "" - -#: src/meta.c:63 -#, c-format -msgid "Sending meta data to %s (%s) failed: %s" -msgstr "" - -#: src/meta.c:94 -#, c-format -msgid "This is a bug: %s:%d: %d:%s %s (%s)" -msgstr "" - -#: src/meta.c:100 -#, c-format -msgid "Metadata socket error for %s (%s): %s" -msgstr "" - -#: src/meta.c:121 -#, c-format -msgid "Connection closed by %s (%s)" -msgstr "" - -#: src/meta.c:128 -#, c-format -msgid "Metadata socket read error for %s (%s): %s" -msgstr "" - -#: src/meta.c:202 -#, c-format -msgid "Metadata read buffer overflow for %s (%s)" -msgstr "" - -#: src/net.c:88 -msgid "Purging unreachable nodes" -msgstr "" - -#: src/net.c:98 -#, c-format -msgid "Purging node %s (%s)" -msgstr "" - -#: src/net.c:188 -#, c-format -msgid "Closing connection with %s (%s)" -msgstr "" - -#: src/net.c:253 -#, c-format -msgid "%s (%s) didn't respond to PING" -msgstr "" - -#: src/net.c:266 -#, c-format -msgid "Timeout from %s (%s) during authentication" -msgstr "" - -#: src/net.c:311 src/net_socket.c:253 -#, c-format -msgid "Error while connecting to %s (%s): %s" -msgstr "" - -#: src/net.c:363 -#, c-format -msgid "Error while waiting for input: %s" -msgstr "" - -#: src/net.c:397 -msgid "Regenerating symmetric key" -msgstr "" - -#: src/net.c:414 -msgid "Flushing event queue" -msgstr "" - -#: src/net.c:431 -msgid "Rereading configuration file and restarting in 5 seconds..." -msgstr "" - -#: src/net.c:438 -msgid "Unable to reread configuration file, exitting." -msgstr "" - -#: src/net_packet.c:107 -#, c-format -msgid "Got unauthenticated packet from %s (%s)" -msgstr "" - -#: src/net_packet.c:134 -#, c-format -msgid "Got late or replayed packet from %s (%s), seqno %d" -msgstr "" - -#: src/net_packet.c:151 -#, c-format -msgid "Error while uncompressing packet from %s (%s)" -msgstr "" - -#: src/net_packet.c:178 -#, c-format -msgid "Received packet of %d bytes from %s (%s)" -msgstr "" - -#: src/net_packet.c:204 -#, c-format -msgid "No valid key known yet for %s (%s), queueing packet" -msgstr "" - -#: src/net_packet.c:237 -#, c-format -msgid "Error while compressing packet to %s (%s)" -msgstr "" - -#: src/net_packet.c:288 -#, c-format -msgid "Setting outgoing packet priority to %d" -msgstr "" - -#. SO_PRIORITY doesn't seem to work -#: src/net_packet.c:290 src/net_setup.c:450 src/net_socket.c:98 -#: src/net_socket.c:144 src/net_socket.c:171 src/process.c:273 -#: src/process.c:310 -#, c-format -msgid "System call `%s' failed: %s" -msgstr "" - -#: src/net_packet.c:296 -#, c-format -msgid "Error sending packet to %s (%s): %s" -msgstr "" - -#: src/net_packet.c:313 -#, c-format -msgid "Sending packet of %d bytes to %s (%s)" -msgstr "" - -#: src/net_packet.c:320 -msgid "Packet is looping back to us!" -msgstr "" - -#: src/net_packet.c:329 -#, c-format -msgid "Node %s (%s) is not reachable" -msgstr "" - -#: src/net_packet.c:337 -#, c-format -msgid "Sending packet to %s via %s (%s)" -msgstr "" - -#: src/net_packet.c:357 -#, c-format -msgid "Broadcasting packet of %d bytes from %s (%s)" -msgstr "" - -#: src/net_packet.c:374 -#, c-format -msgid "Flushing queue for %s (%s)" -msgstr "" - -#: src/net_packet.c:396 -#, c-format -msgid "This is a bug: %s:%d: %d:%s" -msgstr "" - -#: src/net_packet.c:403 -#, c-format -msgid "Incoming data socket error: %s" -msgstr "" - -#: src/net_packet.c:409 -#, c-format -msgid "Receiving packet failed: %s" -msgstr "" - -#: src/net_packet.c:420 -#, c-format -msgid "Received UDP packet from unknown source %s" -msgstr "" - -#: src/net_setup.c:102 -#, c-format -msgid "Error reading RSA public key file `%s': %s" -msgstr "" - -#: src/net_setup.c:112 -#, c-format -msgid "Reading RSA public key file `%s' failed: %s" -msgstr "" - -#: src/net_setup.c:140 -#, c-format -msgid "No public key for %s specified!" -msgstr "" - -#: src/net_setup.c:166 -#, c-format -msgid "Error reading RSA private key file `%s': %s" -msgstr "" - -#: src/net_setup.c:176 -#, c-format -msgid "Reading RSA private key file `%s' failed: %s" -msgstr "" - -#: src/net_setup.c:202 src/net_setup.c:203 -msgid "MYSELF" -msgstr "" - -#: src/net_setup.c:210 -msgid "Name for tinc daemon required!" -msgstr "" - -#: src/net_setup.c:216 -msgid "Invalid name for myself!" -msgstr "" - -#: src/net_setup.c:230 -msgid "Cannot open host configuration file for myself!" -msgstr "" - -#: src/net_setup.c:287 -msgid "Invalid routing mode!" -msgstr "" - -#: src/net_setup.c:298 -msgid "PriorityInheritance not supported on this platform" -msgstr "" - -#: src/net_setup.c:308 -msgid "Bogus maximum timeout!" -msgstr "" - -#: src/net_setup.c:325 -msgid "Invalid address family!" -msgstr "" - -#: src/net_setup.c:347 -msgid "Unrecognized cipher type!" -msgstr "" - -#: src/net_setup.c:382 -msgid "Unrecognized digest type!" -msgstr "" - -#: src/net_setup.c:398 -msgid "MAC length exceeds size of digest!" -msgstr "" - -#: src/net_setup.c:403 -msgid "Bogus MAC length!" -msgstr "" - -#: src/net_setup.c:419 -msgid "Bogus compression level!" -msgstr "" - -#: src/net_setup.c:465 -#, c-format -msgid "Listening on %s" -msgstr "" - -#: src/net_setup.c:476 -msgid "Ready" -msgstr "" - -#: src/net_setup.c:479 -msgid "Unable to create any listening socket!" -msgstr "" - -#: src/net_socket.c:90 -#, c-format -msgid "Creating metasocket failed: %s" -msgstr "" - -#: src/net_socket.c:124 src/net_socket.c:186 -#, c-format -msgid "Can't bind to interface %s: %s" -msgstr "" - -#: src/net_socket.c:128 -msgid "BindToDevice not supported on this platform" -msgstr "" - -#: src/net_socket.c:136 -#, c-format -msgid "Can't bind to %s/tcp: %s" -msgstr "" - -#: src/net_socket.c:163 -#, c-format -msgid "Creating UDP socket failed: %s" -msgstr "" - -#: src/net_socket.c:196 -#, c-format -msgid "Can't bind to %s/udp: %s" -msgstr "" - -#: src/net_socket.c:219 -#, c-format -msgid "Trying to re-establish outgoing connection in %d seconds" -msgstr "" - -#: src/net_socket.c:228 src/net_socket.c:322 -#, c-format -msgid "Trying to connect to %s (%s)" -msgstr "" - -#: src/net_socket.c:234 src/net_socket.c:329 -#, c-format -msgid "Creating socket for %s failed: %s" -msgstr "" - -#: src/net_socket.c:258 src/net_socket.c:268 -#, c-format -msgid "Connected to %s (%s)" -msgstr "" - -#: src/net_socket.c:287 -#, c-format -msgid "Could not set up a meta connection to %s" -msgstr "" - -#: src/net_socket.c:350 -#, c-format -msgid "fcntl for %s: %s" -msgstr "" - -#: src/net_socket.c:368 -#, c-format -msgid "%s: %s" -msgstr "" - -#: src/net_socket.c:389 -#, c-format -msgid "Already connected to %s" -msgstr "" - -#: src/net_socket.c:408 -#, c-format -msgid "No address specified for %s" -msgstr "" - -#: src/net_socket.c:435 -#, c-format -msgid "Accepting a new connection failed: %s" -msgstr "" - -#: src/net_socket.c:453 -#, c-format -msgid "Connection from %s" -msgstr "" - -#: src/net_socket.c:475 -#, c-format -msgid "Invalid name for outgoing connection in %s line %d" -msgstr "" - -#: src/netutl.c:65 src/netutl.c:88 -#, c-format -msgid "Error looking up %s port %s: %s\n" -msgstr "" - -#: src/netutl.c:109 -#, c-format -msgid "Error while translating addresses: %s" -msgstr "" - -#: src/netutl.c:134 -#, c-format -msgid "Error while looking up hostname: %s" -msgstr "" - -#: src/netutl.c:137 -#, c-format -msgid "%s port %s" -msgstr "" - -#: src/netutl.c:166 -#, c-format -msgid "sockaddrcmp() was called with unknown address family %d, exitting!" -msgstr "" - -#: src/protocol.c:77 -#, c-format -msgid "Output buffer overflow while sending request to %s (%s)" -msgstr "" - -#: src/protocol.c:85 -#, c-format -msgid "Sending %s to %s (%s): %s" -msgstr "" - -#: src/protocol.c:87 -#, c-format -msgid "Sending %s to %s (%s)" -msgstr "" - -#: src/protocol.c:104 -#, c-format -msgid "Unknown request from %s (%s): %s" -msgstr "" - -#: src/protocol.c:107 -#, c-format -msgid "Unknown request from %s (%s)" -msgstr "" - -#: src/protocol.c:117 -#, c-format -msgid "Got %s from %s (%s): %s" -msgstr "" - -#: src/protocol.c:120 -#, c-format -msgid "Got %s from %s (%s)" -msgstr "" - -#: src/protocol.c:127 -#, c-format -msgid "Unauthorized request from %s (%s)" -msgstr "" - -#: src/protocol.c:134 -#, c-format -msgid "Error while processing %s from %s (%s)" -msgstr "" - -#: src/protocol.c:141 -#, c-format -msgid "Bogus data received from %s (%s)" -msgstr "" - -#: src/protocol.c:187 -msgid "Already seen request" -msgstr "" - -#: src/protocol.c:218 -#, c-format -msgid "Aging past requests: deleted %d, left %d\n" -msgstr "" - -#: src/protocol_auth.c:69 src/protocol_auth.c:224 src/protocol_auth.c:357 -#: src/protocol_auth.c:417 src/protocol_auth.c:529 src/protocol_edge.c:90 -#: src/protocol_edge.c:219 src/protocol_key.c:80 src/protocol_key.c:128 -#: src/protocol_key.c:196 src/protocol_misc.c:61 src/protocol_misc.c:91 -#: src/protocol_misc.c:177 src/protocol_subnet.c:71 src/protocol_subnet.c:163 -#, c-format -msgid "Got bad %s from %s (%s)" -msgstr "" - -#: src/protocol_auth.c:77 src/protocol_edge.c:98 src/protocol_edge.c:104 -#: src/protocol_edge.c:228 src/protocol_edge.c:234 src/protocol_subnet.c:79 -#: src/protocol_subnet.c:87 src/protocol_subnet.c:171 -#: src/protocol_subnet.c:189 -#, c-format -msgid "Got bad %s from %s (%s): %s" -msgstr "" - -#: src/protocol_auth.c:87 -#, c-format -msgid "Peer %s is %s instead of %s" -msgstr "" - -#: src/protocol_auth.c:98 -#, c-format -msgid "Peer %s (%s) uses incompatible version %d" -msgstr "" - -#: src/protocol_auth.c:117 -#, c-format -msgid "Peer %s had unknown identity (%s)" -msgstr "" - -#: src/protocol_auth.c:175 -#, c-format -msgid "Generated random meta key (unencrypted): %s" -msgstr "" - -#: src/protocol_auth.c:187 src/protocol_auth.c:254 -#, c-format -msgid "Error during encryption of meta key for %s (%s)" -msgstr "" - -#: src/protocol_auth.c:234 src/protocol_auth.c:367 src/protocol_auth.c:425 -#: src/protocol_auth.c:443 -#, c-format -msgid "Possible intruder %s (%s): %s" -msgstr "" - -#: src/protocol_auth.c:262 -#, c-format -msgid "Received random meta key (unencrypted): %s" -msgstr "" - -#: src/protocol_auth.c:274 -#, c-format -msgid "%s (%s) uses unknown cipher!" -msgstr "" - -#: src/protocol_auth.c:296 src/protocol_key.c:267 -#, c-format -msgid "Node %s (%s) uses unknown digest!" -msgstr "" - -#: src/protocol_auth.c:302 -#, c-format -msgid "%s (%s) uses bogus MAC length!" -msgstr "" - -#: src/protocol_auth.c:425 -msgid "wrong challenge reply length" -msgstr "" - -#: src/protocol_auth.c:443 -msgid "wrong challenge reply" -msgstr "" - -#: src/protocol_auth.c:448 -#, c-format -msgid "Expected challenge reply: %s" -msgstr "" - -#: src/protocol_auth.c:549 -#, c-format -msgid "Established a second connection with %s (%s), closing old connection" -msgstr "" - -#: src/protocol_auth.c:583 -#, c-format -msgid "Connection with %s (%s) activated" -msgstr "" - -#: src/protocol_edge.c:98 src/protocol_edge.c:104 src/protocol_edge.c:228 -#: src/protocol_edge.c:234 src/protocol_subnet.c:79 src/protocol_subnet.c:171 -msgid "invalid name" -msgstr "" - -#: src/protocol_edge.c:150 -#, c-format -msgid "Got %s from %s (%s) for ourself which does not match existing entry" -msgstr "" - -#: src/protocol_edge.c:157 -#, c-format -msgid "Got %s from %s (%s) which does not match existing entry" -msgstr "" - -#: src/protocol_edge.c:167 -#, c-format -msgid "Got %s from %s (%s) for ourself which does not exist" -msgstr "" - -#: src/protocol_edge.c:248 src/protocol_edge.c:257 src/protocol_edge.c:268 -#, c-format -msgid "Got %s from %s (%s) which does not appear in the edge tree" -msgstr "" - -#: src/protocol_edge.c:275 src/protocol_subnet.c:118 src/protocol_subnet.c:217 -#, c-format -msgid "Got %s from %s (%s) for ourself" -msgstr "" - -#: src/protocol_key.c:92 -#, c-format -msgid "Got %s from %s (%s) origin %s which does not exist" -msgstr "" - -#: src/protocol_key.c:137 src/protocol_key.c:205 -#, c-format -msgid "" -"Got %s from %s (%s) origin %s which does not exist in our connection list" -msgstr "" - -#: src/protocol_key.c:146 src/protocol_key.c:214 -#, c-format -msgid "" -"Got %s from %s (%s) destination %s which does not exist in our connection " -"list" -msgstr "" - -#: src/protocol_key.c:246 -#, c-format -msgid "Node %s (%s) uses unknown cipher!" -msgstr "" - -#: src/protocol_key.c:251 -#, c-format -msgid "Node %s (%s) uses wrong keylength!" -msgstr "" - -#: src/protocol_key.c:272 -#, c-format -msgid "Node %s (%s) uses bogus MAC length!" -msgstr "" - -#: src/protocol_misc.c:68 -#, c-format -msgid "Status message from %s (%s): %s: %s" -msgstr "" - -#: src/protocol_misc.c:98 -#, c-format -msgid "Error message from %s (%s): %s: %s" -msgstr "" - -#: src/protocol_subnet.c:87 src/protocol_subnet.c:189 -msgid "invalid subnet string" -msgstr "" - -#: src/protocol_subnet.c:180 -#, c-format -msgid "Got %s from %s (%s) for %s which is not in our node tree" -msgstr "" - -#: src/protocol_subnet.c:207 -#, c-format -msgid "Got %s from %s (%s) for %s which does not appear in his subnet tree" -msgstr "" - -#: src/subnet.c:99 -#, c-format -msgid "subnet_compare() was called with unknown subnet type %d, exitting!" -msgstr "" - -#: src/subnet.c:274 -#, c-format -msgid "net2str() was called with unknown subnet type %d, exitting!" -msgstr "" - -#: src/subnet.c:384 -msgid "Subnet list:" -msgstr "" - -#: src/subnet.c:389 -#, c-format -msgid " %s owner %s" -msgstr "" - -#: src/subnet.c:392 -msgid "End of subnet list." -msgstr "" - -#: src/tincd.c:100 -#, c-format -msgid "Try `%s --help' for more information.\n" -msgstr "" - -#: src/tincd.c:103 -#, c-format -msgid "" -"Usage: %s [option]...\n" -"\n" -msgstr "" - -#: src/tincd.c:104 -msgid "" -" -c, --config=DIR Read configuration options from DIR.\n" -" -D, --no-detach Don't fork and detach.\n" -" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" -" -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" -" -n, --net=NETNAME Connect to net NETNAME.\n" -msgstr "" - -#: src/tincd.c:109 -msgid "" -" -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" -" --help Display this help and exit.\n" -" --version Output version information and exit.\n" -"\n" -msgstr "" - -#: src/tincd.c:112 -msgid "Report bugs to tinc@nl.linux.org.\n" -msgstr "" - -#: src/tincd.c:166 -#, c-format -msgid "" -"Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, " -"USR1, USR2, WINCH, INT or ALRM.\n" -msgstr "" - -#: src/tincd.c:184 -#, c-format -msgid "" -"Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n" -msgstr "" - -#: src/tincd.c:245 -#, c-format -msgid "Generating %d bits keys:\n" -msgstr "" - -#: src/tincd.c:250 -msgid "Error during key generation!\n" -msgstr "" - -#: src/tincd.c:254 -msgid "Done.\n" -msgstr "" - -#: src/tincd.c:263 -msgid "public RSA key" -msgstr "" - -#: src/tincd.c:267 src/tincd.c:278 -msgid "" -"Appending key to existing contents.\n" -"Make sure only one key is stored in the file.\n" -msgstr "" - -#: src/tincd.c:274 -msgid "private RSA key" -msgstr "" - -#: src/tincd.c:299 -msgid "Both netname and configuration directory given, using the latter..." -msgstr "" - -#: src/tincd.c:328 -#, c-format -msgid "%s version %s (built %s %s, protocol %d)\n" -msgstr "" - -#: src/tincd.c:329 -msgid "" -"Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n" -"See the AUTHORS file for a complete list.\n" -"\n" -"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" -"and you are welcome to redistribute it under certain conditions;\n" -"see the file COPYING for details.\n" -msgstr "" - -#: src/tincd.c:386 -msgid "Unrecoverable error" -msgstr "" - -#: src/tincd.c:391 -#, c-format -msgid "Restarting in %d seconds!" -msgstr "" - -#: src/process.c:373 src/tincd.c:396 -msgid "Not restarting." -msgstr "" - -#: src/process.c:69 -#, c-format -msgid "Memory exhausted (couldn't allocate %d bytes), exitting." -msgstr "" - -#: src/process.c:100 -msgid "Terminating" -msgstr "" - -#: src/process.c:116 -#, c-format -msgid "A tincd is already running for net `%s' with pid %d.\n" -msgstr "" - -#: src/process.c:119 -#, c-format -msgid "A tincd is already running with pid %d.\n" -msgstr "" - -#: src/process.c:140 -#, c-format -msgid "No other tincd is running for net `%s'.\n" -msgstr "" - -#: src/process.c:142 -msgid "No other tincd is running.\n" -msgstr "" - -#: src/process.c:151 -#, c-format -msgid "The tincd for net `%s' is no longer running. " -msgstr "" - -#: src/process.c:153 -msgid "The tincd is no longer running. " -msgstr "" - -#: src/process.c:155 -msgid "Removing stale lock file.\n" -msgstr "" - -#: src/process.c:183 -#, c-format -msgid "Couldn't detach from terminal: %s" -msgstr "" - -#: src/process.c:196 -#, c-format -msgid "tincd %s (%s %s) starting, debug level %d" -msgstr "" - -#: src/process.c:199 -#, c-format -msgid "tincd %s starting" -msgstr "" - -#: src/process.c:280 -#, c-format -msgid "Executing script %s" -msgstr "" - -#: src/process.c:290 -#, c-format -msgid "Process %d (%s) exited with non-zero status %d" -msgstr "" - -#: src/process.c:298 -#, c-format -msgid "Process %d (%s) was killed by signal %d (%s)" -msgstr "" - -#: src/process.c:304 -#, c-format -msgid "Process %d (%s) terminated abnormally" -msgstr "" - -#: src/process.c:329 -msgid "Got TERM signal" -msgstr "" - -#: src/process.c:338 -msgid "Got QUIT signal" -msgstr "" - -#: src/process.c:345 -#, c-format -msgid "Got another fatal signal %d (%s): not restarting." -msgstr "" - -#: src/process.c:354 -#, c-format -msgid "Got fatal signal %d (%s)" -msgstr "" - -#: src/process.c:359 -msgid "Trying to re-execute in 5 seconds..." -msgstr "" - -#: src/process.c:382 -msgid "Got HUP signal" -msgstr "" - -#: src/process.c:391 -#, c-format -msgid "Reverting to old debug level (%d)" -msgstr "" - -#: src/process.c:398 -#, c-format -msgid "" -"Temporarily setting debug level to 5. Kill me with SIGINT again to go back " -"to level %d." -msgstr "" - -#: src/process.c:409 -msgid "Got ALRM signal" -msgstr "" - -#: src/process.c:438 -#, c-format -msgid "Got unexpected signal %d (%s)" -msgstr "" - -#: src/process.c:447 -#, c-format -msgid "Ignored signal %d (%s)" -msgstr "" - -#: src/process.c:504 -#, c-format -msgid "Installing signal handler for signal %d (%s) failed: %s\n" -msgstr "" - -#: src/route.c:73 -#, c-format -msgid "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx" -msgstr "" - -#: src/route.c:107 -#, c-format -msgid "MAC address %hx:%hx:%hx:%hx:%hx:%hx expired" -msgstr "" - -#: src/route.c:152 -#, c-format -msgid "Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d" -msgstr "" - -#: src/route.c:172 -#, c-format -msgid "" -"Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%" -"hx:%hx:%hx" -msgstr "" - -#: src/route.c:233 -msgid "" -"Cannot route packet: received unknown type neighbor solicitation request" -msgstr "" - -#: src/route.c:254 -msgid "Cannot route packet: checksum error for neighbor solicitation request" -msgstr "" - -#: src/route.c:266 -#, c-format -msgid "" -"Cannot route packet: neighbor solicitation request for unknown address %hx:%" -"hx:%hx:%hx:%hx:%hx:%hx:%hx" -msgstr "" - -#: src/route.c:341 -msgid "Cannot route packet: received unknown type ARP request" -msgstr "" - -#: src/route.c:354 -#, c-format -msgid "Cannot route packet: ARP request for unknown address %d.%d.%d.%d" -msgstr "" - -#: src/route.c:411 -#, c-format -msgid "Cannot route packet: unknown type %hx" -msgstr "" - -#: src/node.c:161 -msgid "Nodes:" -msgstr "" - -#: src/node.c:166 -#, c-format -msgid "" -" %s at %s cipher %d digest %d maclength %d compression %d options %lx status " -"%04x nexthop %s via %s" -msgstr "" - -#: src/node.c:171 -msgid "End of nodes." -msgstr "" - -#: src/edge.c:194 -msgid "Edges:" -msgstr "" - -#: src/edge.c:201 -#, c-format -msgid " %s at %s - %s at %s options %lx weight %d" -msgstr "" - -#: src/edge.c:209 -msgid "End of edges." -msgstr "" - -#: src/graph.c:261 -#, c-format -msgid "Node %s (%s) became reachable" -msgstr "" - -#: src/graph.c:273 -#, c-format -msgid "Node %s (%s) became unreachable" -msgstr "" - -#: src/freebsd/device.c:70 src/linux/device.c:89 src/netbsd/device.c:74 -#: src/openbsd/device.c:74 src/solaris/device.c:75 -#, c-format -msgid "Could not open %s: %s" -msgstr "" - -#: src/linux/device.c:114 src/linux/device.c:124 -msgid "Linux tun/tap device" -msgstr "" - -#: src/linux/device.c:122 -#, c-format -msgid "Old ioctl() request was needed for %s" -msgstr "" - -#: src/linux/device.c:131 -msgid "Linux ethertap device" -msgstr "" - -#: src/freebsd/device.c:87 src/linux/device.c:136 src/netbsd/device.c:90 -#: src/openbsd/device.c:90 src/solaris/device.c:132 -#, c-format -msgid "%s is a %s" -msgstr "" - -#: src/freebsd/device.c:108 src/linux/device.c:159 src/linux/device.c:169 -#: src/netbsd/device.c:111 src/openbsd/device.c:111 src/solaris/device.c:149 -#, c-format -msgid "Error while reading from %s %s: %s" -msgstr "" - -#: src/freebsd/device.c:117 src/linux/device.c:180 src/netbsd/device.c:126 -#: src/openbsd/device.c:140 src/solaris/device.c:164 -#, c-format -msgid "Read packet of %d bytes from %s" -msgstr "" - -#: src/freebsd/device.c:128 src/linux/device.c:191 src/netbsd/device.c:139 -#: src/openbsd/device.c:154 src/solaris/device.c:175 -#, c-format -msgid "Writing packet of %d bytes to %s" -msgstr "" - -#: src/linux/device.c:198 src/linux/device.c:207 src/netbsd/device.c:149 -#: src/openbsd/device.c:180 src/solaris/device.c:180 -#, c-format -msgid "Can't write to %s %s: %s" -msgstr "" - -#: src/freebsd/device.c:144 src/linux/device.c:220 src/netbsd/device.c:160 -#: src/openbsd/device.c:191 src/solaris/device.c:192 -#, c-format -msgid "Statistics for %s %s:" -msgstr "" - -#: src/freebsd/device.c:145 src/linux/device.c:221 src/netbsd/device.c:161 -#: src/openbsd/device.c:192 src/solaris/device.c:193 -#, c-format -msgid " total bytes in: %10d" -msgstr "" - -#: src/freebsd/device.c:146 src/linux/device.c:222 src/netbsd/device.c:162 -#: src/openbsd/device.c:193 src/solaris/device.c:194 -#, c-format -msgid " total bytes out: %10d" -msgstr "" - -#: src/freebsd/device.c:85 -msgid "FreeBSD tap device" -msgstr "" - -#: src/freebsd/device.c:133 -#, c-format -msgid "Error while writing to %s %s: %s" -msgstr "" - -#: src/solaris/device.c:86 -#, c-format -msgid "Could not open /dev/ip: %s" -msgstr "" - -#: src/solaris/device.c:92 -#, c-format -msgid "Can't assign new interface: %s" -msgstr "" - -#: src/solaris/device.c:97 -#, c-format -msgid "Could not open %s twice: %s" -msgstr "" - -#: src/solaris/device.c:102 -#, c-format -msgid "Can't push IP module: %s" -msgstr "" - -#: src/solaris/device.c:108 -#, c-format -msgid "Can't set PPA %d: %s" -msgstr "" - -#: src/solaris/device.c:113 -#, c-format -msgid "Can't link TUN device to IP: %s" -msgstr "" - -#: src/solaris/device.c:120 -msgid "Solaris tun device" -msgstr "" - -#: src/netbsd/device.c:88 -msgid "NetBSD tun device" -msgstr "" - -#: src/openbsd/device.c:88 -msgid "OpenBSD tun device" -msgstr "" - -#: src/openbsd/device.c:130 -#, c-format -msgid "Unknown address family %d while reading packet from %s %s" -msgstr "" - -#: src/openbsd/device.c:169 -#, c-format -msgid "Unknown address family %d while writing packet to %s %s" -msgstr "" diff --git a/src/Makefile.am b/src/Makefile.am index 32aee66..7b3dd97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,31 +1,89 @@ ## Produce this file with automake to get Makefile.in -# $Id: Makefile.am,v 1.4.4.21 2002/03/27 15:47:06 guus Exp $ sbin_PROGRAMS = tincd -EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c +tincd_SOURCES = \ + have.h \ + system.h \ + avl_tree.c avl_tree.h \ + conf.c conf.h \ + connection.c connection.h \ + device.h \ + dropin.c dropin.h \ + dummy_device.c \ + edge.c edge.h \ + ethernet.h \ + event.c event.h \ + fake-getaddrinfo.c fake-getaddrinfo.h \ + fake-getnameinfo.c fake-getnameinfo.h \ + graph.c graph.h \ + ipv4.h \ + ipv6.h \ + list.c list.h \ + logger.c logger.h \ + meta.c meta.h \ + multicast_device.c \ + net.c net.h \ + net_packet.c \ + net_setup.c \ + net_socket.c \ + netutl.c netutl.h \ + node.c node.h \ + pidfile.c pidfile.h \ + process.c process.h \ + protocol.c protocol.h \ + protocol_auth.c \ + protocol_edge.c \ + protocol_misc.c \ + protocol_key.c \ + protocol_subnet.c \ + proxy.c proxy.h \ + raw_socket_device.c \ + route.c route.h \ + subnet.c subnet.h \ + tincd.c \ + utils.c utils.h \ + xalloc.h -tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c net_packet.c net_setup.c \ - net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \ - protocol_key.c protocol_subnet.c route.c subnet.c tincd.c +if !GETOPT +tincd_SOURCES += \ + getopt.c getopt.h \ + getopt1.c +endif -INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl +if LINUX +tincd_SOURCES += linux/device.c +endif -noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h meta.h net.h netutl.h node.h process.h \ - protocol.h route.h subnet.h +if BSD +tincd_SOURCES += bsd/device.c +if TUNEMU +tincd_SOURCES += bsd/tunemu.c bsd/tunemu.h +endif +endif -LIBS = @LIBS@ @INTLLIBS@ +if SOLARIS +tincd_SOURCES += solaris/device.c +endif -tincd_LDADD = \ - $(top_builddir)/lib/libvpn.a +if MINGW +tincd_SOURCES += mingw/device.c mingw/common.h +endif -localedir = $(datadir)/locale +if CYGWIN +tincd_SOURCES += cygwin/device.c +endif -CFLAGS = @CFLAGS@ -DPKGLIBDIR=$(pkglibdir) -DCONFDIR=\"$(sysconfdir)\" \ - -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" +if UML +tincd_SOURCES += uml_device.c +endif -dist-hook: - rm -f `find . -type l` +if VDE +tincd_SOURCES += vde_device.c +endif -lint: $(tincd_SOURCES) - lclint -nullassign -nullret +trytorecover +posixlib -skipansiheaders -skipposixheaders +gnuextensions -I/usr/include -I/usr/lib/gcc-lib/i386-linux/2.95.2/include -I. -I/home/zarq/p/tinc/cvs/cabal/src -I.. -I.. -I/home/zarq/p/tinc/cvs/cabal/lib -I/home/zarq/p/tinc/cvs/cabal/intl -D_POSIX_SOURCE -D__ELF__ -Dunix -D__i386__ -Dlinux -DHAVE_CONFIG_H -DPKGLIBDIR=/usr/local/lib/tinc -DCONFDIR=\"/usr/local/etc\" -DLOCALEDIR=\"/usr/local/share/locale\" $^ +if TUNEMU +LIBS += -lpcap +endif + +AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/ diff --git a/src/Makefile.in b/src/Makefile.in index 8e07167..5d52921 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,8 @@ -# Makefile.in generated automatically by automake 1.5 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. -# 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. @@ -13,313 +14,655 @@ @SET_MAKE@ -# $Id: Makefile.am,v 1.4.4.21 2002/03/27 15:47:06 guus Exp $ - -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 +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ +build_triplet = @build@ host_triplet = @host@ -AMTAR = @AMTAR@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CPP = @CPP@ -DATADIRNAME = @DATADIRNAME@ -DEPDIR = @DEPDIR@ -EXEEXT = @EXEEXT@ -GENCAT = @GENCAT@ -GLIBC21 = @GLIBC21@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -HAVE_TUNTAP = @HAVE_TUNTAP@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -LIBICONV = @LIBICONV@ -LINUX_IF_TUN_H = @LINUX_IF_TUN_H@ -LN_S = @LN_S@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PERL = @PERL@ -POFILES = @POFILES@ -POSUB = @POSUB@ -RANLIB = @RANLIB@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -am__include = @am__include@ -am__quote = @am__quote@ -install_sh = @install_sh@ - -INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl - -sbin_PROGRAMS = tincd - -EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c - -tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c net_packet.c net_setup.c \ - net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \ - protocol_key.c protocol_subnet.c route.c subnet.c tincd.c - - -noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h meta.h net.h netutl.h node.h process.h \ - protocol.h route.h subnet.h - - -LIBS = @LIBS@ @INTLLIBS@ - -tincd_LDADD = \ - $(top_builddir)/lib/libvpn.a - - -localedir = $(datadir)/locale - -CFLAGS = @CFLAGS@ -DPKGLIBDIR=$(pkglibdir) -DCONFDIR=\"$(sysconfdir)\" \ - -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" +sbin_PROGRAMS = tincd$(EXEEXT) +@GETOPT_FALSE@am__append_1 = \ +@GETOPT_FALSE@ getopt.c getopt.h \ +@GETOPT_FALSE@ getopt1.c +@LINUX_TRUE@am__append_2 = linux/device.c +@BSD_TRUE@am__append_3 = bsd/device.c +@BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h +@SOLARIS_TRUE@am__append_5 = solaris/device.c +@MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h +@CYGWIN_TRUE@am__append_7 = cygwin/device.c +@UML_TRUE@am__append_8 = uml_device.c +@VDE_TRUE@am__append_9 = vde_device.c +@TUNEMU_TRUE@am__append_10 = -lpcap subdir = src -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = -sbin_PROGRAMS = tincd$(EXEEXT) +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) - -am_tincd_OBJECTS = conf.$(OBJEXT) connection.$(OBJEXT) device.$(OBJEXT) \ - edge.$(OBJEXT) event.$(OBJEXT) graph.$(OBJEXT) meta.$(OBJEXT) \ +am__tincd_SOURCES_DIST = have.h system.h avl_tree.c avl_tree.h conf.c \ + conf.h connection.c connection.h device.h dropin.c dropin.h \ + dummy_device.c edge.c edge.h ethernet.h event.c event.h \ + fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \ + fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \ + logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \ + net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \ + node.h pidfile.c pidfile.h process.c process.h protocol.c \ + protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ + protocol_key.c protocol_subnet.c proxy.c proxy.h \ + raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \ + utils.c utils.h xalloc.h getopt.c getopt.h getopt1.c \ + linux/device.c bsd/device.c bsd/tunemu.c bsd/tunemu.h \ + solaris/device.c mingw/device.c mingw/common.h cygwin/device.c \ + uml_device.c vde_device.c +@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT) +am__dirstamp = $(am__leading_dot)dirstamp +@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT) +@BSD_TRUE@am__objects_3 = bsd/device.$(OBJEXT) +@BSD_TRUE@@TUNEMU_TRUE@am__objects_4 = bsd/tunemu.$(OBJEXT) +@SOLARIS_TRUE@am__objects_5 = solaris/device.$(OBJEXT) +@MINGW_TRUE@am__objects_6 = mingw/device.$(OBJEXT) +@CYGWIN_TRUE@am__objects_7 = cygwin/device.$(OBJEXT) +@UML_TRUE@am__objects_8 = uml_device.$(OBJEXT) +@VDE_TRUE@am__objects_9 = vde_device.$(OBJEXT) +am_tincd_OBJECTS = avl_tree.$(OBJEXT) conf.$(OBJEXT) \ + connection.$(OBJEXT) dropin.$(OBJEXT) dummy_device.$(OBJEXT) \ + edge.$(OBJEXT) event.$(OBJEXT) fake-getaddrinfo.$(OBJEXT) \ + fake-getnameinfo.$(OBJEXT) graph.$(OBJEXT) list.$(OBJEXT) \ + logger.$(OBJEXT) meta.$(OBJEXT) multicast_device.$(OBJEXT) \ net.$(OBJEXT) net_packet.$(OBJEXT) net_setup.$(OBJEXT) \ net_socket.$(OBJEXT) netutl.$(OBJEXT) node.$(OBJEXT) \ - process.$(OBJEXT) protocol.$(OBJEXT) protocol_auth.$(OBJEXT) \ - protocol_edge.$(OBJEXT) protocol_misc.$(OBJEXT) \ - protocol_key.$(OBJEXT) protocol_subnet.$(OBJEXT) \ - route.$(OBJEXT) subnet.$(OBJEXT) tincd.$(OBJEXT) + pidfile.$(OBJEXT) process.$(OBJEXT) protocol.$(OBJEXT) \ + protocol_auth.$(OBJEXT) protocol_edge.$(OBJEXT) \ + protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \ + protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \ + raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \ + tincd.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) \ + $(am__objects_5) $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) $(am__objects_9) tincd_OBJECTS = $(am_tincd_OBJECTS) -tincd_DEPENDENCIES = $(top_builddir)/lib/libvpn.a -tincd_LDFLAGS = - -DEFS = @DEFS@ -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ +tincd_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp -@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/conf.Po $(DEPDIR)/connection.Po \ -@AMDEP_TRUE@ $(DEPDIR)/device.Po $(DEPDIR)/edge.Po \ -@AMDEP_TRUE@ $(DEPDIR)/event.Po $(DEPDIR)/graph.Po \ -@AMDEP_TRUE@ $(DEPDIR)/meta.Po $(DEPDIR)/net.Po \ -@AMDEP_TRUE@ $(DEPDIR)/net_packet.Po $(DEPDIR)/net_setup.Po \ -@AMDEP_TRUE@ $(DEPDIR)/net_socket.Po $(DEPDIR)/netutl.Po \ -@AMDEP_TRUE@ $(DEPDIR)/node.Po $(DEPDIR)/process.Po \ -@AMDEP_TRUE@ $(DEPDIR)/protocol.Po $(DEPDIR)/protocol_auth.Po \ -@AMDEP_TRUE@ $(DEPDIR)/protocol_edge.Po \ -@AMDEP_TRUE@ $(DEPDIR)/protocol_key.Po \ -@AMDEP_TRUE@ $(DEPDIR)/protocol_misc.Po \ -@AMDEP_TRUE@ $(DEPDIR)/protocol_subnet.Po $(DEPDIR)/route.Po \ -@AMDEP_TRUE@ $(DEPDIR)/subnet.Po $(DEPDIR)/tincd.Po +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/avl_tree.Po ./$(DEPDIR)/conf.Po \ + ./$(DEPDIR)/connection.Po ./$(DEPDIR)/dropin.Po \ + ./$(DEPDIR)/dummy_device.Po ./$(DEPDIR)/edge.Po \ + ./$(DEPDIR)/event.Po ./$(DEPDIR)/fake-getaddrinfo.Po \ + ./$(DEPDIR)/fake-getnameinfo.Po ./$(DEPDIR)/getopt.Po \ + ./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/graph.Po \ + ./$(DEPDIR)/list.Po ./$(DEPDIR)/logger.Po ./$(DEPDIR)/meta.Po \ + ./$(DEPDIR)/multicast_device.Po ./$(DEPDIR)/net.Po \ + ./$(DEPDIR)/net_packet.Po ./$(DEPDIR)/net_setup.Po \ + ./$(DEPDIR)/net_socket.Po ./$(DEPDIR)/netutl.Po \ + ./$(DEPDIR)/node.Po ./$(DEPDIR)/pidfile.Po \ + ./$(DEPDIR)/process.Po ./$(DEPDIR)/protocol.Po \ + ./$(DEPDIR)/protocol_auth.Po ./$(DEPDIR)/protocol_edge.Po \ + ./$(DEPDIR)/protocol_key.Po ./$(DEPDIR)/protocol_misc.Po \ + ./$(DEPDIR)/protocol_subnet.Po ./$(DEPDIR)/proxy.Po \ + ./$(DEPDIR)/raw_socket_device.Po ./$(DEPDIR)/route.Po \ + ./$(DEPDIR)/subnet.Po ./$(DEPDIR)/tincd.Po \ + ./$(DEPDIR)/uml_device.Po ./$(DEPDIR)/utils.Po \ + ./$(DEPDIR)/vde_device.Po bsd/$(DEPDIR)/device.Po \ + bsd/$(DEPDIR)/tunemu.Po cygwin/$(DEPDIR)/device.Po \ + linux/$(DEPDIR)/device.Po mingw/$(DEPDIR)/device.Po \ + solaris/$(DEPDIR)/device.Po +am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -DIST_SOURCES = $(tincd_SOURCES) -HEADERS = $(noinst_HEADERS) - -DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = SOURCES = $(tincd_SOURCES) - +DIST_SOURCES = $(am__tincd_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ $(am__append_10) +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +tincd_SOURCES = have.h system.h avl_tree.c avl_tree.h conf.c conf.h \ + connection.c connection.h device.h dropin.c dropin.h \ + dummy_device.c edge.c edge.h ethernet.h event.c event.h \ + fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \ + fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \ + logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \ + net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \ + node.h pidfile.c pidfile.h process.c process.h protocol.c \ + protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ + protocol_key.c protocol_subnet.c proxy.c proxy.h \ + raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \ + utils.c utils.h xalloc.h $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) $(am__append_8) \ + $(am__append_9) +AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/ all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && \ - CONFIG_HEADERS= CONFIG_LINKS= \ - CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(sbindir) - @list='$(sbin_PROGRAMS)'; for p in $$list; do \ - p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - if test -f $$p \ - ; then \ - f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/$$f"; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/$$f; \ - else :; fi; \ - done + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) - @list='$(sbin_PROGRAMS)'; for p in $$list; do \ - f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ - rm -f $(DESTDIR)$(sbindir)/$$f; \ - done + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) -tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) + +installcheck-sbinPROGRAMS: $(sbin_PROGRAMS) + bad=0; pid=$$$$; list="$(sbin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if "$(DESTDIR)$(sbindir)/$$f" $$opt >c$${pid}_.out \ + 2>c$${pid}_.err &2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad +linux/$(am__dirstamp): + @$(MKDIR_P) linux + @: > linux/$(am__dirstamp) +linux/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) linux/$(DEPDIR) + @: > linux/$(DEPDIR)/$(am__dirstamp) +linux/device.$(OBJEXT): linux/$(am__dirstamp) \ + linux/$(DEPDIR)/$(am__dirstamp) +bsd/$(am__dirstamp): + @$(MKDIR_P) bsd + @: > bsd/$(am__dirstamp) +bsd/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) bsd/$(DEPDIR) + @: > bsd/$(DEPDIR)/$(am__dirstamp) +bsd/device.$(OBJEXT): bsd/$(am__dirstamp) \ + bsd/$(DEPDIR)/$(am__dirstamp) +bsd/tunemu.$(OBJEXT): bsd/$(am__dirstamp) \ + bsd/$(DEPDIR)/$(am__dirstamp) +solaris/$(am__dirstamp): + @$(MKDIR_P) solaris + @: > solaris/$(am__dirstamp) +solaris/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) solaris/$(DEPDIR) + @: > solaris/$(DEPDIR)/$(am__dirstamp) +solaris/device.$(OBJEXT): solaris/$(am__dirstamp) \ + solaris/$(DEPDIR)/$(am__dirstamp) +mingw/$(am__dirstamp): + @$(MKDIR_P) mingw + @: > mingw/$(am__dirstamp) +mingw/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) mingw/$(DEPDIR) + @: > mingw/$(DEPDIR)/$(am__dirstamp) +mingw/device.$(OBJEXT): mingw/$(am__dirstamp) \ + mingw/$(DEPDIR)/$(am__dirstamp) +cygwin/$(am__dirstamp): + @$(MKDIR_P) cygwin + @: > cygwin/$(am__dirstamp) +cygwin/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cygwin/$(DEPDIR) + @: > cygwin/$(DEPDIR)/$(am__dirstamp) +cygwin/device.$(OBJEXT): cygwin/$(am__dirstamp) \ + cygwin/$(DEPDIR)/$(am__dirstamp) + +tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) $(EXTRA_tincd_DEPENDENCIES) @rm -f tincd$(EXEEXT) - $(LINK) $(tincd_LDFLAGS) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS) mostlyclean-compile: - -rm -f *.$(OBJEXT) core *.core + -rm -f *.$(OBJEXT) + -rm -f bsd/*.$(OBJEXT) + -rm -f cygwin/*.$(OBJEXT) + -rm -f linux/*.$(OBJEXT) + -rm -f mingw/*.$(OBJEXT) + -rm -f solaris/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/conf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/edge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/event.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/graph.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/meta.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/net.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/net_packet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/net_setup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/net_socket.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/netutl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/node.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/process.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol_auth.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol_edge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol_key.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol_misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/protocol_subnet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/route.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/subnet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/tincd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl_tree.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pidfile.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@ # am--include-marker -distclean-depend: - -rm -rf $(DEPDIR) +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .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)/'`$< +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .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 $<` -CCDEPMODE = @CCDEPMODE@ -uninstall-info-am: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -tags: TAGS +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-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=; \ +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ 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) + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique GTAGS: - here=`CDPATH=: && cd $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am -top_distdir = .. -distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) - -distdir: $(DISTFILES) - $(mkinstalldirs) $(distdir)/freebsd $(distdir)/linux $(distdir)/openbsd $(distdir)/solaris - @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; \ +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ - cp -pR $$d/$$file $(distdir) \ - || exit 1; \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="${top_distdir}" distdir="$(distdir)" \ - dist-hook check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) $(HEADERS) - +all-am: Makefile $(PROGRAMS) installdirs: - $(mkinstalldirs) $(DESTDIR)$(sbindir) - + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-am install-exec: install-exec-am install-data: install-data-am @@ -330,15 +673,32 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f bsd/$(DEPDIR)/$(am__dirstamp) + -rm -f bsd/$(am__dirstamp) + -rm -f cygwin/$(DEPDIR)/$(am__dirstamp) + -rm -f cygwin/$(am__dirstamp) + -rm -f linux/$(DEPDIR)/$(am__dirstamp) + -rm -f linux/$(am__dirstamp) + -rm -f mingw/$(DEPDIR)/$(am__dirstamp) + -rm -f mingw/$(am__dirstamp) + -rm -f solaris/$(DEPDIR)/$(am__dirstamp) + -rm -f solaris/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -348,55 +708,175 @@ clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am - -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags + -rm -f ./$(DEPDIR)/avl_tree.Po + -rm -f ./$(DEPDIR)/conf.Po + -rm -f ./$(DEPDIR)/connection.Po + -rm -f ./$(DEPDIR)/dropin.Po + -rm -f ./$(DEPDIR)/dummy_device.Po + -rm -f ./$(DEPDIR)/edge.Po + -rm -f ./$(DEPDIR)/event.Po + -rm -f ./$(DEPDIR)/fake-getaddrinfo.Po + -rm -f ./$(DEPDIR)/fake-getnameinfo.Po + -rm -f ./$(DEPDIR)/getopt.Po + -rm -f ./$(DEPDIR)/getopt1.Po + -rm -f ./$(DEPDIR)/graph.Po + -rm -f ./$(DEPDIR)/list.Po + -rm -f ./$(DEPDIR)/logger.Po + -rm -f ./$(DEPDIR)/meta.Po + -rm -f ./$(DEPDIR)/multicast_device.Po + -rm -f ./$(DEPDIR)/net.Po + -rm -f ./$(DEPDIR)/net_packet.Po + -rm -f ./$(DEPDIR)/net_setup.Po + -rm -f ./$(DEPDIR)/net_socket.Po + -rm -f ./$(DEPDIR)/netutl.Po + -rm -f ./$(DEPDIR)/node.Po + -rm -f ./$(DEPDIR)/pidfile.Po + -rm -f ./$(DEPDIR)/process.Po + -rm -f ./$(DEPDIR)/protocol.Po + -rm -f ./$(DEPDIR)/protocol_auth.Po + -rm -f ./$(DEPDIR)/protocol_edge.Po + -rm -f ./$(DEPDIR)/protocol_key.Po + -rm -f ./$(DEPDIR)/protocol_misc.Po + -rm -f ./$(DEPDIR)/protocol_subnet.Po + -rm -f ./$(DEPDIR)/proxy.Po + -rm -f ./$(DEPDIR)/raw_socket_device.Po + -rm -f ./$(DEPDIR)/route.Po + -rm -f ./$(DEPDIR)/subnet.Po + -rm -f ./$(DEPDIR)/tincd.Po + -rm -f ./$(DEPDIR)/uml_device.Po + -rm -f ./$(DEPDIR)/utils.Po + -rm -f ./$(DEPDIR)/vde_device.Po + -rm -f bsd/$(DEPDIR)/device.Po + -rm -f bsd/$(DEPDIR)/tunemu.Po + -rm -f cygwin/$(DEPDIR)/device.Po + -rm -f linux/$(DEPDIR)/device.Po + -rm -f mingw/$(DEPDIR)/device.Po + -rm -f solaris/$(DEPDIR)/device.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am dvi-am: +html: html-am + +html-am: + info: info-am info-am: install-data-am: +install-dvi: install-dvi-am + +install-dvi-am: + install-exec-am: install-sbinPROGRAMS +install-html: install-html-am + +install-html-am: + install-info: install-info-am +install-info-am: + install-man: -installcheck-am: +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: installcheck-sbinPROGRAMS maintainer-clean: maintainer-clean-am - + -rm -f ./$(DEPDIR)/avl_tree.Po + -rm -f ./$(DEPDIR)/conf.Po + -rm -f ./$(DEPDIR)/connection.Po + -rm -f ./$(DEPDIR)/dropin.Po + -rm -f ./$(DEPDIR)/dummy_device.Po + -rm -f ./$(DEPDIR)/edge.Po + -rm -f ./$(DEPDIR)/event.Po + -rm -f ./$(DEPDIR)/fake-getaddrinfo.Po + -rm -f ./$(DEPDIR)/fake-getnameinfo.Po + -rm -f ./$(DEPDIR)/getopt.Po + -rm -f ./$(DEPDIR)/getopt1.Po + -rm -f ./$(DEPDIR)/graph.Po + -rm -f ./$(DEPDIR)/list.Po + -rm -f ./$(DEPDIR)/logger.Po + -rm -f ./$(DEPDIR)/meta.Po + -rm -f ./$(DEPDIR)/multicast_device.Po + -rm -f ./$(DEPDIR)/net.Po + -rm -f ./$(DEPDIR)/net_packet.Po + -rm -f ./$(DEPDIR)/net_setup.Po + -rm -f ./$(DEPDIR)/net_socket.Po + -rm -f ./$(DEPDIR)/netutl.Po + -rm -f ./$(DEPDIR)/node.Po + -rm -f ./$(DEPDIR)/pidfile.Po + -rm -f ./$(DEPDIR)/process.Po + -rm -f ./$(DEPDIR)/protocol.Po + -rm -f ./$(DEPDIR)/protocol_auth.Po + -rm -f ./$(DEPDIR)/protocol_edge.Po + -rm -f ./$(DEPDIR)/protocol_key.Po + -rm -f ./$(DEPDIR)/protocol_misc.Po + -rm -f ./$(DEPDIR)/protocol_subnet.Po + -rm -f ./$(DEPDIR)/proxy.Po + -rm -f ./$(DEPDIR)/raw_socket_device.Po + -rm -f ./$(DEPDIR)/route.Po + -rm -f ./$(DEPDIR)/subnet.Po + -rm -f ./$(DEPDIR)/tincd.Po + -rm -f ./$(DEPDIR)/uml_device.Po + -rm -f ./$(DEPDIR)/utils.Po + -rm -f ./$(DEPDIR)/vde_device.Po + -rm -f bsd/$(DEPDIR)/device.Po + -rm -f bsd/$(DEPDIR)/tunemu.Po + -rm -f cygwin/$(DEPDIR)/device.Po + -rm -f linux/$(DEPDIR)/device.Po + -rm -f mingw/$(DEPDIR)/device.Po + -rm -f solaris/$(DEPDIR)/device.Po + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic -uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS +pdf: pdf-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-sbinPROGRAMS distclean distclean-compile distclean-depend \ - distclean-generic distclean-tags 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-sbinPROGRAMS install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am uninstall-sbinPROGRAMS +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installcheck-sbinPROGRAMS installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS + +.PRECIOUS: Makefile -dist-hook: - rm -f `find . -type l` - -lint: $(tincd_SOURCES) - lclint -nullassign -nullret +trytorecover +posixlib -skipansiheaders -skipposixheaders +gnuextensions -I/usr/include -I/usr/lib/gcc-lib/i386-linux/2.95.2/include -I. -I/home/zarq/p/tinc/cvs/cabal/src -I.. -I.. -I/home/zarq/p/tinc/cvs/cabal/lib -I/home/zarq/p/tinc/cvs/cabal/intl -D_POSIX_SOURCE -D__ELF__ -Dunix -D__i386__ -Dlinux -DHAVE_CONFIG_H -DPKGLIBDIR=/usr/local/lib/tinc -DCONFDIR=\"/usr/local/etc\" -DLOCALEDIR=\"/usr/local/share/locale\" $^ # 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/src/avl_tree.c b/src/avl_tree.c new file mode 100644 index 0000000..96d3d43 --- /dev/null +++ b/src/avl_tree.c @@ -0,0 +1,757 @@ +/* + avl_tree.c -- avl_ tree and linked list convenience + Copyright (C) 1998 Michael H. Buselli + 2000-2005 Ivo Timmermans, + 2000-2015 Guus Sliepen + 2000-2005 Wessel Dankers + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Original AVL tree library by Michael H. Buselli . + + Modified 2000-11-28 by Wessel Dankers to use counts + instead of depths, to add the ->next and ->prev and to generally obfuscate + the code. Mail me if you found a bug. + + Cleaned up and incorporated some of the ideas from the red-black tree + library for inclusion into tinc (https://www.tinc-vpn.org/) by + Guus Sliepen . +*/ + +#include "system.h" + +#include "avl_tree.h" +#include "xalloc.h" + +#ifdef AVL_COUNT +#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0) +#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left)) +#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right)) +#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1) +#endif + +#ifdef AVL_DEPTH +#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0) +#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left)) +#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right)) +#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1) +#endif + +#ifndef AVL_DEPTH +static int lg(unsigned int u) __attribute__((__const__)); + +static int lg(unsigned int u) { + int r = 1; + + if(!u) { + return 0; + } + + if(u & 0xffff0000) { + u >>= 16; + r += 16; + } + + if(u & 0x0000ff00) { + u >>= 8; + r += 8; + } + + if(u & 0x000000f0) { + u >>= 4; + r += 4; + } + + if(u & 0x0000000c) { + u >>= 2; + r += 2; + } + + if(u & 0x00000002) { + r++; + } + + return r; +} +#endif + +/* Internal helper functions */ + +static int avl_check_balance(const avl_node_t *node) { +#ifdef AVL_DEPTH + int d; + + d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node); + + return d < -1 ? -1 : d > 1 ? 1 : 0; +#else + /* int d; + * d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node)); + * d = d<-1?-1:d>1?1:0; + */ + int pl, r; + + pl = lg(AVL_L_COUNT(node)); + r = AVL_R_COUNT(node); + + if(r >> pl + 1) { + return 1; + } + + if(pl < 2 || r >> pl - 2) { + return 0; + } + + return -1; +#endif +} + +static void avl_rebalance(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *child; + avl_node_t *gchild; + avl_node_t *parent; + avl_node_t **superparent; + + while(node) { + parent = node->parent; + + superparent = + parent ? node == + parent->left ? &parent->left : &parent->right : &tree->root; + + switch(avl_check_balance(node)) { + case -1: + child = node->left; +#ifdef AVL_DEPTH + + if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) { +#else + + if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) { +#endif + node->left = child->right; + + if(node->left) { + node->left->parent = node; + } + + child->right = node; + node->parent = child; + *superparent = child; + child->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); +#endif + } else { + gchild = child->right; + node->left = gchild->right; + + if(node->left) { + node->left->parent = node; + } + + child->right = gchild->left; + + if(child->right) { + child->right->parent = child; + } + + gchild->right = node; + + gchild->right->parent = gchild; + gchild->left = child; + + gchild->left->parent = gchild; + + *superparent = gchild; + gchild->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); + gchild->count = AVL_CALC_COUNT(gchild); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); + gchild->depth = AVL_CALC_DEPTH(gchild); +#endif + } + + break; + + case 1: + child = node->right; +#ifdef AVL_DEPTH + + if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) { +#else + + if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) { +#endif + node->right = child->left; + + if(node->right) { + node->right->parent = node; + } + + child->left = node; + node->parent = child; + *superparent = child; + child->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); +#endif + } else { + gchild = child->left; + node->right = gchild->left; + + if(node->right) { + node->right->parent = node; + } + + child->left = gchild->right; + + if(child->left) { + child->left->parent = child; + } + + gchild->left = node; + + gchild->left->parent = gchild; + gchild->right = child; + + gchild->right->parent = gchild; + + *superparent = gchild; + gchild->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); + gchild->count = AVL_CALC_COUNT(gchild); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); + gchild->depth = AVL_CALC_DEPTH(gchild); +#endif + } + + break; + + default: +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); +#endif + } + + node = parent; + } +} + +/* (De)constructors */ + +avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete) { + avl_tree_t *tree; + + tree = xmalloc_and_zero(sizeof(avl_tree_t)); + tree->compare = compare; + tree->delete = delete; + + return tree; +} + +void avl_free_tree(avl_tree_t *tree) { + free(tree); +} + +avl_node_t *avl_alloc_node(void) { + return xmalloc_and_zero(sizeof(avl_node_t)); +} + +void avl_free_node(avl_tree_t *tree, avl_node_t *node) { + if(node->data && tree->delete) { + tree->delete(node->data); + } + + free(node); +} + +/* Searching */ + +void *avl_search(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + return node ? node->data : NULL; +} + +void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result) { + avl_node_t *node; + + node = avl_search_closest_node(tree, data, result); + + return node ? node->data : NULL; +} + +void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_closest_smaller_node(tree, data); + + return node ? node->data : NULL; +} + +void *avl_search_closest_greater(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_closest_greater_node(tree, data); + + return node ? node->data : NULL; +} + +avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + return result ? NULL : node; +} + +avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, + int *result) { + avl_node_t *node; + int c; + + node = tree->root; + + if(!node) { + if(result) { + *result = 0; + } + + return NULL; + } + + for(;;) { + c = tree->compare(data, node->data); + + if(c < 0) { + if(node->left) { + node = node->left; + } else { + if(result) { + *result = -1; + } + + break; + } + } else if(c > 0) { + if(node->right) { + node = node->right; + } else { + if(result) { + *result = 1; + } + + break; + } + } else { + if(result) { + *result = 0; + } + + break; + } + } + + return node; +} + +avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, + const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + if(result < 0) { + node = node->prev; + } + + return node; +} + +avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, + const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + if(result > 0) { + node = node->next; + } + + return node; +} + +/* Insertion and deletion */ + +avl_node_t *avl_insert(avl_tree_t *tree, void *data) { + avl_node_t *closest, *new; + int result; + + if(!tree->root) { + new = avl_alloc_node(); + new->data = data; + avl_insert_top(tree, new); + } else { + closest = avl_search_closest_node(tree, data, &result); + + switch(result) { + case -1: + new = avl_alloc_node(); + new->data = data; + avl_insert_before(tree, closest, new); + break; + + case 1: + new = avl_alloc_node(); + new->data = data; + avl_insert_after(tree, closest, new); + break; + + default: + return NULL; + } + } + +#ifdef AVL_COUNT + new->count = 1; +#endif +#ifdef AVL_DEPTH + new->depth = 1; +#endif + + return new; +} + +avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *closest; + int result; + + if(!tree->root) { + avl_insert_top(tree, node); + } else { + closest = avl_search_closest_node(tree, node->data, &result); + + switch(result) { + case -1: + avl_insert_before(tree, closest, node); + break; + + case 1: + avl_insert_after(tree, closest, node); + break; + + case 0: + return NULL; + } + } + +#ifdef AVL_COUNT + node->count = 1; +#endif +#ifdef AVL_DEPTH + node->depth = 1; +#endif + + return node; +} + +void avl_insert_top(avl_tree_t *tree, avl_node_t *node) { + node->prev = node->next = node->parent = NULL; + tree->head = tree->tail = tree->root = node; +} + +void avl_insert_before(avl_tree_t *tree, avl_node_t *before, + avl_node_t *node) { + if(!before) { + if(tree->tail) { + avl_insert_after(tree, tree->tail, node); + } else { + avl_insert_top(tree, node); + } + + return; + } + + node->next = before; + node->parent = before; + node->prev = before->prev; + + if(before->left) { + avl_insert_after(tree, before->prev, node); + return; + } + + if(before->prev) { + before->prev->next = node; + } else { + tree->head = node; + } + + before->prev = node; + before->left = node; + + avl_rebalance(tree, before); +} + +void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node) { + if(!after) { + if(tree->head) { + avl_insert_before(tree, tree->head, node); + } else { + avl_insert_top(tree, node); + } + + return; + } + + if(after->right) { + avl_insert_before(tree, after->next, node); + return; + } + + node->prev = after; + node->parent = after; + node->next = after->next; + + if(after->next) { + after->next->prev = node; + } else { + tree->tail = node; + } + + after->next = node; + after->right = node; + + avl_rebalance(tree, after); +} + +avl_node_t *avl_unlink(avl_tree_t *tree, void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + if(node) { + avl_unlink_node(tree, node); + } + + return node; +} + +void avl_unlink_node(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *parent; + avl_node_t **superparent; + avl_node_t *subst, *left, *right; + avl_node_t *balnode; + + if(node->prev) { + node->prev->next = node->next; + } else { + tree->head = node->next; + } + + if(node->next) { + node->next->prev = node->prev; + } else { + tree->tail = node->prev; + } + + parent = node->parent; + + superparent = + parent ? node == + parent->left ? &parent->left : &parent->right : &tree->root; + + left = node->left; + right = node->right; + + if(!left) { + *superparent = right; + + if(right) { + right->parent = parent; + } + + balnode = parent; + } else if(!right) { + *superparent = left; + left->parent = parent; + balnode = parent; + } else { + subst = node->prev; + + if(!subst) { // This only happens if node is not actually in a tree at all. + abort(); + } + + if(subst == left) { + balnode = subst; + } else { + balnode = subst->parent; + balnode->right = subst->left; + + if(balnode->right) { + balnode->right->parent = balnode; + } + + subst->left = left; + left->parent = subst; + } + + subst->right = right; + subst->parent = parent; + right->parent = subst; + *superparent = subst; + } + + avl_rebalance(tree, balnode); + + node->next = node->prev = node->parent = node->left = node->right = NULL; + +#ifdef AVL_COUNT + node->count = 0; +#endif +#ifdef AVL_DEPTH + node->depth = 0; +#endif +} + +void avl_delete_node(avl_tree_t *tree, avl_node_t *node) { + avl_unlink_node(tree, node); + avl_free_node(tree, node); +} + +void avl_delete(avl_tree_t *tree, void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + if(node) { + avl_delete_node(tree, node); + } +} + +/* Fast tree cleanup */ + +void avl_delete_tree(avl_tree_t *tree) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + avl_free_node(tree, node); + } + + avl_free_tree(tree); +} + +/* Tree walking */ + +void avl_foreach(const avl_tree_t *tree, avl_action_t action) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + action(node->data); + } +} + +void avl_foreach_node(const avl_tree_t *tree, avl_action_t action) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + action(node); + } +} + +/* Indexing */ + +#ifdef AVL_COUNT +unsigned int avl_count(const avl_tree_t *tree) { + return AVL_NODE_COUNT(tree->root); +} + +avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index) { + avl_node_t *node; + unsigned int c; + + node = tree->root; + + while(node) { + c = AVL_L_COUNT(node); + + if(index < c) { + node = node->left; + } else if(index > c) { + node = node->right; + index -= c + 1; + } else { + return node; + } + } + + return NULL; +} + +unsigned int avl_index(const avl_node_t *node) { + avl_node_t *next; + unsigned int index; + + index = AVL_L_COUNT(node); + + while((next = node->parent)) { + if(node == next->right) { + index += AVL_L_COUNT(next) + 1; + } + + node = next; + } + + return index; +} +#endif +#ifdef AVL_DEPTH +unsigned int avl_depth(const avl_tree_t *tree) { + return AVL_NODE_DEPTH(tree->root); +} +#endif diff --git a/src/avl_tree.h b/src/avl_tree.h new file mode 100644 index 0000000..e8cefcf --- /dev/null +++ b/src/avl_tree.h @@ -0,0 +1,142 @@ +#ifndef TINC_AVL_TREE_H +#define TINC_AVL_TREE_H + +/* + avl_tree.h -- header file for avl_tree.c + Copyright (C) 1998 Michael H. Buselli + 2000-2005 Ivo Timmermans, + 2000-2006 Guus Sliepen + 2000-2005 Wessel Dankers + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Original AVL tree library by Michael H. Buselli . + + Modified 2000-11-28 by Wessel Dankers to use counts + instead of depths, to add the ->next and ->prev and to generally obfuscate + the code. Mail me if you found a bug. + + Cleaned up and incorporated some of the ideas from the red-black tree + library for inclusion into tinc (https://www.tinc-vpn.org/) by + Guus Sliepen . +*/ + +#ifndef AVL_DEPTH +#ifndef AVL_COUNT +#define AVL_DEPTH +#endif +#endif + +typedef struct avl_node_t { + + /* Linked list part */ + + struct avl_node_t *next; + struct avl_node_t *prev; + + /* Tree part */ + + struct avl_node_t *parent; + struct avl_node_t *left; + struct avl_node_t *right; + +#ifdef AVL_COUNT + unsigned int count; +#endif +#ifdef AVL_DEPTH + unsigned char depth; +#endif + + /* Payload */ + + void *data; + +} avl_node_t; + +typedef int (*avl_compare_t)(const void *data1, const void *data2); +typedef void (*avl_action_t)(const void *data); +typedef void (*avl_action_node_t)(const avl_node_t *node); + +typedef struct avl_tree_t { + + /* Linked list part */ + + avl_node_t *head; + avl_node_t *tail; + + /* Tree part */ + + avl_node_t *root; + + avl_compare_t compare; + avl_action_t delete; + +} avl_tree_t; + +/* (De)constructors */ + +extern avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete); +extern void avl_free_tree(avl_tree_t *tree); + +extern avl_node_t *avl_alloc_node(void); +extern void avl_free_node(avl_tree_t *tree, avl_node_t *node); + +/* Insertion and deletion */ + +extern avl_node_t *avl_insert(avl_tree_t *tree, void *data); +extern avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node); + +extern void avl_insert_top(avl_tree_t *tree, avl_node_t *node); +extern void avl_insert_before(avl_tree_t *tree, avl_node_t *before, avl_node_t *node); +extern void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node); + +extern avl_node_t *avl_unlink(avl_tree_t *tree, void *data); +extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *node); +extern void avl_delete(avl_tree_t *tree, void *data); +extern void avl_delete_node(avl_tree_t *tree, avl_node_t *node); + +/* Fast tree cleanup */ + +extern void avl_delete_tree(avl_tree_t *tree); + +/* Searching */ + +extern void *avl_search(const avl_tree_t *tree, const void *data); +extern void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result); +extern void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data); +extern void *avl_search_closest_greater(const avl_tree_t *tree, const void *data); + +extern avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data); +extern avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, int *result); +extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, const void *data); +extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data); + +/* Tree walking */ + +extern void avl_foreach(const avl_tree_t *tree, avl_action_t action); +extern void avl_foreach_node(const avl_tree_t *tree, avl_action_t action); + +/* Indexing */ + +#ifdef AVL_COUNT +extern unsigned int avl_count(const avl_tree_t *tree); +extern avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index); +extern unsigned int avl_index(const avl_node_t *node); +#endif +#ifdef AVL_DEPTH +extern unsigned int avl_depth(const avl_tree_t *tree); +#endif + +#endif diff --git a/src/bsd/device.c b/src/bsd/device.c new file mode 100644 index 0000000..23d6d69 --- /dev/null +++ b/src/bsd/device.c @@ -0,0 +1,530 @@ +/* + device.c -- Interaction BSD tun/tap device + Copyright (C) 2001-2005 Ivo Timmermans, + 2001-2016 Guus Sliepen + 2009 Grzegorz Dymarek + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "../system.h" + +#include "../conf.h" +#include "../device.h" +#include "../logger.h" +#include "../net.h" +#include "../route.h" +#include "../utils.h" +#include "../xalloc.h" + +#ifdef ENABLE_TUNEMU +#include "tunemu.h" +#endif + +#ifdef HAVE_NET_IF_UTUN_H +#include +#include +#include +#endif + +#define DEFAULT_TUN_DEVICE "/dev/tun0" +#define DEFAULT_TAP_DEVICE "/dev/tap0" + +typedef enum device_type { + DEVICE_TYPE_TUN, + DEVICE_TYPE_TUNIFHEAD, + DEVICE_TYPE_TAP, +#ifdef ENABLE_TUNEMU + DEVICE_TYPE_TUNEMU, +#endif + DEVICE_TYPE_UTUN, +} device_type_t; + +int device_fd = -1; +char *device = NULL; +char *iface = NULL; +static const char *device_info = "OS X utun device"; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; +#if defined(ENABLE_TUNEMU) +static device_type_t device_type = DEVICE_TYPE_TUNEMU; +#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY) +static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD; +#else +static device_type_t device_type = DEVICE_TYPE_TUN; +#endif + +#ifdef HAVE_NET_IF_UTUN_H +static bool setup_utun(void) { + device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + + if(device_fd == -1) { + logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno)); + return false; + } + + struct ctl_info info = {}; + + strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name)); + + if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) { + logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno)); + return false; + } + + int unit = -1; + char *p = strstr(device, "utun"), *e = NULL; + + if(p) { + unit = strtol(p + 4, &e, 10); + + if(!e) { + unit = -1; + } + } + + struct sockaddr_ctl sc = { + .sc_id = info.ctl_id, + .sc_len = sizeof(sc), + .sc_family = AF_SYSTEM, + .ss_sysaddr = AF_SYS_CONTROL, + .sc_unit = unit + 1, + }; + + if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { + logger(LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno)); + return false; + } + + char name[64] = ""; + socklen_t len = sizeof(name); + + if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) { + iface = xstrdup(device); + } else { + iface = xstrdup(name); + } + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} +#endif + +static bool setup_device(void) { + // Find out which device file to open + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + if(routing_mode == RMODE_ROUTER) { + device = xstrdup(DEFAULT_TUN_DEVICE); + } else { + device = xstrdup(DEFAULT_TAP_DEVICE); + } + } + + // Find out if it's supposed to be a tun or a tap device + + char *type; + + if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { + if(!strcasecmp(type, "tun")) + /* use default */; + +#ifdef ENABLE_TUNEMU + else if(!strcasecmp(type, "tunemu")) { + device_type = DEVICE_TYPE_TUNEMU; + } + +#endif +#ifdef HAVE_NET_IF_UTUN_H + else if(!strcasecmp(type, "utun")) { + device_type = DEVICE_TYPE_UTUN; + } + +#endif + else if(!strcasecmp(type, "tunnohead")) { + device_type = DEVICE_TYPE_TUN; + } else if(!strcasecmp(type, "tunifhead")) { + device_type = DEVICE_TYPE_TUNIFHEAD; + } else if(!strcasecmp(type, "tap")) { + device_type = DEVICE_TYPE_TAP; + } else { + logger(LOG_ERR, "Unknown device type %s!", type); + return false; + } + } else { +#ifdef HAVE_NET_IF_UTUN_H + + if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) { + device_type = DEVICE_TYPE_UTUN; + } else +#endif + if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) { + device_type = DEVICE_TYPE_TAP; + } + } + + if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) { + logger(LOG_ERR, "Only tap devices support switch mode!"); + return false; + } + + // Open the device + + switch(device_type) { +#ifdef ENABLE_TUNEMU + + case DEVICE_TYPE_TUNEMU: { + char dynamic_name[256] = ""; + device_fd = tunemu_open(dynamic_name); + } + break; +#endif +#ifdef HAVE_NET_IF_UTUN_H + + case DEVICE_TYPE_UTUN: + return setup_utun(); +#endif + + default: + device_fd = open(device, O_RDWR | O_NONBLOCK); + } + + if(device_fd < 0) { + logger(LOG_ERR, "Could not open %s: %s", device, strerror(errno)); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + // Guess what the corresponding interface is called + + char *realname = NULL; + +#if defined(HAVE_FDEVNAME) + realname = fdevname(device_fd); +#elif defined(HAVE_DEVNAME) + struct stat buf; + + if(!fstat(device_fd, &buf)) { + realname = devname(buf.st_rdev, S_IFCHR); + } + +#endif + + if(!realname) { + realname = device; + } + + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) { + iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname); + } else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) { + logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); + } + + // Configure the device as best as we can + + switch(device_type) { + default: + device_type = DEVICE_TYPE_TUN; + + case DEVICE_TYPE_TUN: +#ifdef TUNSIFHEAD + { + const int zero = 0; + + if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) { + logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno)); + return false; + } + } + +#endif +#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST) + { + const int mode = IFF_BROADCAST | IFF_MULTICAST; + ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode)); + } +#endif + + device_info = "Generic BSD tun device"; + break; + + case DEVICE_TYPE_TUNIFHEAD: +#ifdef TUNSIFHEAD + { + const int one = 1; + + if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) { + logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno)); + return false; + } + } + +#endif +#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST) + { + const int mode = IFF_BROADCAST | IFF_MULTICAST; + ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode)); + } +#endif + + device_info = "Generic BSD tun device"; + break; + + case DEVICE_TYPE_TAP: + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + device_info = "Generic BSD tap device"; +#ifdef TAPGIFNAME + { + struct ifreq ifr; + + if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) { + if(iface) { + free(iface); + } + + iface = xstrdup(ifr.ifr_name); + } + } + +#endif + break; +#ifdef ENABLE_TUNEMU + + case DEVICE_TYPE_TUNEMU: + device_info = "BSD tunemu device"; + break; +#endif + } + +#ifdef SIOCGIFADDR + + if(overwrite_mac) { + ioctl(device_fd, SIOCGIFADDR, mymac.x); + } + +#endif + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} + +static void close_device(void) { + switch(device_type) { +#ifdef ENABLE_TUNEMU + + case DEVICE_TYPE_TUNEMU: + tunemu_close(device_fd); + break; +#endif + + default: + close(device_fd); + } + + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + switch(device_type) { + case DEVICE_TYPE_TUN: +#ifdef ENABLE_TUNEMU + case DEVICE_TYPE_TUNEMU: + if(device_type == DEVICE_TYPE_TUNEMU) { + lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14); + } else +#endif + lenin = read(device_fd, packet->data + 14, MTU - 14); + + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + switch(packet->data[14] >> 4) { + case 4: + packet->data[12] = 0x08; + packet->data[13] = 0x00; + break; + + case 6: + packet->data[12] = 0x86; + packet->data[13] = 0xDD; + break; + + default: + ifdebug(TRAFFIC) logger(LOG_ERR, + "Unknown IP version %d while reading packet from %s %s", + packet->data[14] >> 4, device_info, device); + return false; + } + + memset(packet->data, 0, 12); + packet->len = lenin + 14; + break; + + case DEVICE_TYPE_UTUN: + case DEVICE_TYPE_TUNIFHEAD: { + if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + switch(packet->data[14] >> 4) { + case 4: + packet->data[12] = 0x08; + packet->data[13] = 0x00; + break; + + case 6: + packet->data[12] = 0x86; + packet->data[13] = 0xDD; + break; + + default: + ifdebug(TRAFFIC) logger(LOG_ERR, + "Unknown IP version %d while reading packet from %s %s", + packet->data[14] >> 4, device_info, device); + return false; + } + + memset(packet->data, 0, 12); + packet->len = lenin + 10; + break; + } + + case DEVICE_TYPE_TAP: + if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + packet->len = lenin; + break; + + default: + return false; + } + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", + packet->len, device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + switch(device_type) { + case DEVICE_TYPE_TUN: + if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_UTUN: + case DEVICE_TYPE_TUNIFHEAD: { + int af = (packet->data[12] << 8) + packet->data[13]; + uint32_t type; + + switch(af) { + case 0x0800: + type = htonl(AF_INET); + break; + + case 0x86DD: + type = htonl(AF_INET6); + break; + + default: + ifdebug(TRAFFIC) logger(LOG_ERR, + "Unknown address family %x while writing packet to %s %s", + af, device_info, device); + return false; + } + + memcpy(packet->data + 10, &type, sizeof(type)); + + if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; + } + + case DEVICE_TYPE_TAP: + if(write(device_fd, packet->data, packet->len) < 0) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + break; + +#ifdef ENABLE_TUNEMU + + case DEVICE_TYPE_TUNEMU: + if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + break; +#endif + + default: + return false; + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t os_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/bsd/tunemu.c b/src/bsd/tunemu.c new file mode 100644 index 0000000..7ff6f72 --- /dev/null +++ b/src/bsd/tunemu.c @@ -0,0 +1,377 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "tunemu.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPPPROTO_CTL 1 + +#define PPP_IP 0x21 +#define PPP_IPV6 0x57 + +#define SC_LOOP_TRAFFIC 0x00000200 + +#define PPPIOCNEWUNIT _IOWR('t', 62, int) +#define PPPIOCSFLAGS _IOW('t', 89, int) +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) +#define PPPIOCATTCHAN _IOW('t', 56, int) +#define PPPIOCGCHAN _IOR('t', 55, int) +#define PPPIOCCONNECT _IOW('t', 58, int) +#define PPPIOCGUNIT _IOR('t', 86, int) + +struct sockaddr_ppp { + u_int8_t ppp_len; + u_int8_t ppp_family; + u_int16_t ppp_proto; + u_int32_t ppp_cookie; +}; + +enum NPmode { + NPMODE_PASS, + NPMODE_DROP, + NPMODE_ERROR, + NPMODE_QUEUE +}; + +struct npioctl { + int protocol; + enum NPmode mode; +}; + +#define PPP_KEXT_PATH "/System/Library/Extensions/PPP.kext" + +#define ERROR_BUFFER_SIZE 1024 + +char tunemu_error[ERROR_BUFFER_SIZE]; + +static int pcap_use_count = 0; +static pcap_t *pcap = NULL; + +static int data_buffer_length = 0; +static char *data_buffer = NULL; + +static void tun_error(char *format, ...) { + va_list vl; + va_start(vl, format); + vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl); + va_end(vl); +} + +static void tun_noerror() { + *tunemu_error = 0; +} + +static void closeall() { + int fd = getdtablesize(); + + while(fd--) { + close(fd); + } + + open("/dev/null", O_RDWR, 0); + dup(0); + dup(0); +} + +static int ppp_load_kext() { + int pid = fork(); + + if(pid < 0) { + tun_error("fork for ppp kext: %s", strerror(errno)); + return -1; + } + + if(pid == 0) { + closeall(); + execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL); + exit(1); + } + + int status; + + while(waitpid(pid, &status, 0) < 0) { + if(errno == EINTR) { + continue; + } + + tun_error("waitpid for ppp kext: %s", strerror(errno)); + return -1; + } + + if(WEXITSTATUS(status) != 0) { + tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH); + return -1; + } + + tun_noerror(); + return 0; +} + +static int ppp_new_instance() { + // create ppp socket + int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + + if(ppp_sockfd < 0) { + if(ppp_load_kext() < 0) { + return -1; + } + + ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + + if(ppp_sockfd < 0) { + tun_error("creating ppp socket: %s", strerror(errno)); + return -1; + } + } + + // connect to ppp procotol + struct sockaddr_ppp pppaddr; + pppaddr.ppp_len = sizeof(struct sockaddr_ppp); + pppaddr.ppp_family = AF_PPP; + pppaddr.ppp_proto = PPPPROTO_CTL; + pppaddr.ppp_cookie = 0; + + if(connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) { + tun_error("connecting ppp socket: %s", strerror(errno)); + close(ppp_sockfd); + return -1; + } + + tun_noerror(); + return ppp_sockfd; +} + +static int ppp_new_unit(int *unit_number) { + int fd = ppp_new_instance(); + + if(fd < 0) { + return -1; + } + + // create ppp unit + if(ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0) { + tun_error("creating ppp unit: %s", strerror(errno)); + close(fd); + return -1; + } + + tun_noerror(); + return fd; +} + +static int ppp_setup_unit(int unit_fd) { + // send traffic to program + int flags = SC_LOOP_TRAFFIC; + + if(ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0) { + tun_error("setting ppp loopback mode: %s", strerror(errno)); + return -1; + } + + // allow packets + struct npioctl npi; + npi.protocol = PPP_IP; + npi.mode = NPMODE_PASS; + + if(ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0) { + tun_error("starting ppp unit: %s", strerror(errno)); + return -1; + } + + tun_noerror(); + return 0; +} + +static int open_pcap() { + if(pcap != NULL) { + pcap_use_count++; + return 0; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf); + pcap_use_count = 1; + + if(pcap == NULL) { + tun_error("opening pcap: %s", errbuf); + return -1; + } + + tun_noerror(); + return 0; +} + +static void close_pcap() { + if(pcap == NULL) { + return; + } + + pcap_use_count--; + + if(pcap_use_count == 0) { + pcap_close(pcap); + pcap = NULL; + } +} + +static void allocate_data_buffer(int size) { + if(data_buffer_length < size) { + free(data_buffer); + data_buffer_length = size; + data_buffer = malloc(data_buffer_length); + } +} + +static void make_device_name(tunemu_device device, int unit_number) { + snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number); +} + +static int check_device_name(tunemu_device device) { + if(strlen(device) < 4) { + return -1; + } + + int unit_number = atoi(device + 3); + + if(unit_number < 0 || unit_number > 999) { + return -1; + } + + tunemu_device compare; + make_device_name(compare, unit_number); + + if(strcmp(device, compare) != 0) { + return -1; + } + + return 0; +} + +int tunemu_open(tunemu_device device) { + int ppp_unit_number = -1; + + if(device[0] != 0) { + if(check_device_name(device) < 0) { + tun_error("invalid device name \"%s\"", device); + return -1; + } + + ppp_unit_number = atoi(device + 3); + } + + int ppp_unit_fd = ppp_new_unit(&ppp_unit_number); + + if(ppp_unit_fd < 0) { + return -1; + } + + if(ppp_setup_unit(ppp_unit_fd) < 0) { + close(ppp_unit_fd); + return -1; + } + + if(open_pcap() < 0) { + close(ppp_unit_fd); + return -1; + } + + make_device_name(device, ppp_unit_number); + + return ppp_unit_fd; +} + +int tunemu_close(int ppp_sockfd) { + int ret = close(ppp_sockfd); + + if(ret == 0) { + close_pcap(); + } + + return ret; +} + +int tunemu_read(int ppp_sockfd, char *buffer, int length) { + allocate_data_buffer(length + 2); + + length = read(ppp_sockfd, data_buffer, length + 2); + + if(length < 0) { + tun_error("reading packet: %s", strerror(errno)); + return length; + } + + tun_noerror(); + + length -= 2; + + if(length < 0) { + return 0; + } + + memcpy(buffer, data_buffer + 2, length); + + return length; +} + +int tunemu_write(int ppp_sockfd, char *buffer, int length) { + allocate_data_buffer(length + 4); + + data_buffer[0] = 0x02; + data_buffer[1] = 0x00; + data_buffer[2] = 0x00; + data_buffer[3] = 0x00; + + memcpy(data_buffer + 4, buffer, length); + + if(pcap == NULL) { + tun_error("pcap not open"); + return -1; + } + + length = pcap_inject(pcap, data_buffer, length + 4); + + if(length < 0) { + tun_error("injecting packet: %s", pcap_geterr(pcap)); + return length; + } + + tun_noerror(); + + length -= 4; + + if(length < 0) { + return 0; + } + + return length; +} diff --git a/src/bsd/tunemu.h b/src/bsd/tunemu.h new file mode 100644 index 0000000..e0452a8 --- /dev/null +++ b/src/bsd/tunemu.h @@ -0,0 +1,32 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef TUNEMU_H +#define TUNEMU_H + +typedef char tunemu_device[7]; + +extern char tunemu_error[]; + +int tunemu_open(tunemu_device dev); +int tunemu_close(int fd); +int tunemu_read(int fd, char *buffer, int length); +int tunemu_write(int fd, char *buffer, int length); + +#endif diff --git a/src/conf.c b/src/conf.c index bc29e07..3f81877 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1,9 +1,10 @@ /* conf.c -- configuration code Copyright (C) 1998 Robert van der Meulen - 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen - 2000 Cris van Pelt + 1998-2005 Ivo Timmermans + 2000-2014 Guus Sliepen + 2010-2011 Julien Muchembled + 2000 Cris van Pelt 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 @@ -15,609 +16,587 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: conf.c,v 1.9.4.55 2002/04/09 11:42:48 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include /* for cp */ -#include - -#include "conf.h" -#include "netutl.h" /* for str2address */ - #include "system.h" +#include "avl_tree.h" +#include "connection.h" +#include "conf.h" +#include "list.h" +#include "logger.h" +#include "netutl.h" /* for str2address */ +#include "protocol.h" +#include "utils.h" /* for cp */ +#include "xalloc.h" + avl_tree_t *config_tree; -int debug_lvl = 0; -int pingtimeout = 0; /* seconds before timeout */ -char *confbase = NULL; /* directory in which all config files are */ -char *netname = NULL; /* name of the vpn network */ +int pinginterval = 0; /* seconds between pings */ +int pingtimeout = 0; /* seconds to wait for response */ +char *confbase = NULL; /* directory in which all config files are */ +char *netname = NULL; /* name of the vpn network */ +list_t *cmdline_conf = NULL; /* global/host configuration values given at the command line */ -int config_compare(config_t *a, config_t *b) -{ - int result; - result = strcasecmp(a->variable, b->variable); +static int config_compare(const config_t *a, const config_t *b) { + int result; - if(result) - return result; + result = strcasecmp(a->variable, b->variable); - result = a->line - b->line; + if(result) { + return result; + } - if(result) - return result; - else - return strcmp(a->file, b->file); + /* give priority to command line options */ + result = !b->file - !a->file; + + if(result) { + return result; + } + + result = a->line - b->line; + + if(result) { + return result; + } else { + return a->file ? strcmp(a->file, b->file) : 0; + } } -void init_configuration(avl_tree_t **config_tree) -{ -cp - *config_tree = avl_alloc_tree((avl_compare_t)config_compare, (avl_action_t)free_config); -cp +void init_configuration(avl_tree_t **config_tree) { + *config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config); } -void exit_configuration(avl_tree_t **config_tree) -{ -cp - avl_delete_tree(*config_tree); - *config_tree = NULL; -cp +void exit_configuration(avl_tree_t **config_tree) { + avl_delete_tree(*config_tree); + *config_tree = NULL; } -config_t *new_config(void) -{ - config_t *cfg; -cp - cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg)); - - return cfg; +config_t *new_config(void) { + return xmalloc_and_zero(sizeof(config_t)); } -void free_config(config_t *cfg) -{ -cp - if(cfg->variable) - free(cfg->variable); - if(cfg->value) - free(cfg->value); - if(cfg->file) - free(cfg->file); - free(cfg); -cp +void free_config(config_t *cfg) { + free(cfg->variable); + free(cfg->value); + free(cfg->file); + free(cfg); } -void config_add(avl_tree_t *config_tree, config_t *cfg) -{ -cp - avl_insert(config_tree, cfg); -cp +void config_add(avl_tree_t *config_tree, config_t *cfg) { + avl_insert(config_tree, cfg); } -config_t *lookup_config(avl_tree_t *config_tree, char *variable) -{ - config_t cfg, *found; -cp - cfg.variable = variable; - cfg.file = ""; - cfg.line = 0; +config_t *lookup_config(const avl_tree_t *config_tree, char *variable) { + config_t cfg, *found; - found = avl_search_closest_greater(config_tree, &cfg); + cfg.variable = variable; + cfg.file = NULL; + cfg.line = 0; - if(!found) - return NULL; + found = avl_search_closest_greater(config_tree, &cfg); - if(strcasecmp(found->variable, variable)) - return NULL; + if(!found) { + return NULL; + } - return found; + if(strcasecmp(found->variable, variable)) { + return NULL; + } + + return found; } -config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg) -{ - avl_node_t *node; - config_t *found; -cp - node = avl_search_node(config_tree, cfg); +config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg) { + avl_node_t *node; + config_t *found; - if(node) - { - if(node->next) - { - found = (config_t *)node->next->data; - if(!strcasecmp(found->variable, cfg->variable)) - return found; - } - } + node = avl_search_node(config_tree, cfg); - return NULL; + if(node) { + if(node->next) { + found = node->next->data; + + if(!strcasecmp(found->variable, cfg->variable)) { + return found; + } + } + } + + return NULL; } -int get_config_bool(config_t *cfg, int *result) -{ -cp - if(!cfg) - return 0; +bool get_config_bool(const config_t *cfg, bool *result) { + if(!cfg) { + return false; + } - if(!strcasecmp(cfg->value, "yes")) - { - *result = 1; - return 1; - } - else if(!strcasecmp(cfg->value, "no")) - { - *result = 0; - return 1; - } + if(!strcasecmp(cfg->value, "yes")) { + *result = true; + return true; + } else if(!strcasecmp(cfg->value, "no")) { + *result = false; + return true; + } - syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); + logger(LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); - return 0; + return false; } -int get_config_int(config_t *cfg, int *result) -{ -cp - if(!cfg) - return 0; +bool get_config_int(const config_t *cfg, int *result) { + if(!cfg) { + return false; + } - if(sscanf(cfg->value, "%d", result) == 1) - return 1; + if(sscanf(cfg->value, "%d", result) == 1) { + return true; + } - syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; + logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); + + return false; } -int get_config_string(config_t *cfg, char **result) -{ -cp - if(!cfg) - return 0; +bool get_config_string(const config_t *cfg, char **result) { + if(!cfg) { + return false; + } - *result = xstrdup(cfg->value); - return 1; + *result = xstrdup(cfg->value); + + return true; } -int get_config_address(config_t *cfg, struct addrinfo **result) -{ - struct addrinfo *ai; -cp - if(!cfg) - return 0; +bool get_config_address(const config_t *cfg, struct addrinfo **result) { + struct addrinfo *ai; - ai = str2addrinfo(cfg->value, NULL, 0); + if(!cfg) { + return false; + } - if(ai) - { - *result = ai; - return 1; - } + ai = str2addrinfo(cfg->value, NULL, 0); - syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; + if(ai) { + *result = ai; + return true; + } + + logger(LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); + + return false; } -int get_config_port(config_t *cfg, port_t *result) -{ -cp - if(!cfg) - return 0; +bool get_config_subnet(const config_t *cfg, subnet_t **result) { + subnet_t subnet = {0}; - if(sscanf(cfg->value, "%hu", result) == 1) - { - *result = htons(*result); - return 1; - } + if(!cfg) { + return false; + } - syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; -} + if(!str2net(&subnet, cfg->value)) { + logger(LOG_ERR, "Subnet expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); + return false; + } -int get_config_subnet(config_t *cfg, subnet_t **result) -{ - subnet_t *subnet; -cp - if(!cfg) - return 0; + /* Teach newbies what subnets are... */ - subnet = str2net(cfg->value); + if(((subnet.type == SUBNET_IPV4) + && !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t))) + || ((subnet.type == SUBNET_IPV6) + && !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)))) { + logger(LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); + return false; + } - if(!subnet) - { - syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; - } + *(*result = new_subnet()) = subnet; - /* Teach newbies what subnets are... */ - - if(((subnet->type == SUBNET_IPV4) && maskcheck((char *)&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t))) - || ((subnet->type == SUBNET_IPV6) && maskcheck((char *)&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t)))) - { - syslog(LOG_ERR, _("Network address and prefix length do not match for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - free(subnet); - return 0; - } - - *result = subnet; - - return 1; + return true; } /* - Read exactly one line and strip the trailing newline if any. If the - file was on EOF, return NULL. Otherwise, return all the data in a - dynamically allocated buffer. - - If line is non-NULL, it will be used as an initial buffer, to avoid - unnecessary mallocing each time this function is called. If buf is - given, and buf needs to be expanded, the var pointed to by buflen - will be increased. + Read exactly one line and strip the trailing newline if any. */ -char *readline(FILE *fp, char **buf, size_t *buflen) -{ - char *newline = NULL; - char *p; - char *line; /* The array that contains everything that has been read - so far */ - char *idx; /* Read into this pointer, which points to an offset - within line */ - size_t size, newsize; /* The size of the current array pointed to by - line */ - size_t maxlen; /* Maximum number of characters that may be read with - fgets. This is newsize - oldsize. */ +static char *readline(FILE *fp, char *buf, size_t buflen) { + char *newline = NULL; + char *p; - if(feof(fp)) - return NULL; - - if((buf != NULL) && (buflen != NULL)) - { - size = *buflen; - line = *buf; - } - else - { - size = 100; - line = xmalloc(size); - } - - maxlen = size; - idx = line; - *idx = 0; - for(;;) - { - errno = 0; - p = fgets(idx, maxlen, fp); - if(p == NULL) /* EOF or error */ - { - if(feof(fp)) - break; - - /* otherwise: error; let the calling function print an error - message if applicable */ - free(line); - return NULL; + if(feof(fp)) { + return NULL; } - newline = strchr(p, '\n'); - if(newline == NULL) - /* We haven't yet read everything to the end of the line */ - { - newsize = size << 1; - line = xrealloc(line, newsize); - idx = &line[size - 1]; - maxlen = newsize - size + 1; - size = newsize; - } - else - { - *newline = '\0'; /* kill newline */ - break; /* yay */ - } - } + p = fgets(buf, buflen, fp); - if((buf != NULL) && (buflen != NULL)) - { - *buflen = size; - *buf = line; - } - return line; + if(!p) { + return NULL; + } + + newline = strchr(p, '\n'); + + if(!newline) { + return buf; + } + + *newline = '\0'; /* kill newline */ + + if(newline > p && newline[-1] == '\r') { /* and carriage return if necessary */ + newline[-1] = '\0'; + } + + return buf; +} + +config_t *parse_config_line(char *line, const char *fname, int lineno) { + config_t *cfg; + int len; + char *variable, *value, *eol; + variable = value = line; + + eol = line + strlen(line); + + while(strchr("\t ", *--eol)) { + *eol = '\0'; + } + + len = strcspn(value, "\t ="); + value += len; + value += strspn(value, "\t "); + + if(*value == '=') { + value++; + value += strspn(value, "\t "); + } + + variable[len] = '\0'; + + if(!*value) { + const char err[] = "No value for variable"; + + if(fname) + logger(LOG_ERR, "%s `%s' on line %d while reading config file %s", + err, variable, lineno, fname); + else + logger(LOG_ERR, "%s `%s' in command line option %d", + err, variable, lineno); + + return NULL; + } + + cfg = new_config(); + cfg->variable = xstrdup(variable); + cfg->value = xstrdup(value); + cfg->file = fname ? xstrdup(fname) : NULL; + cfg->line = lineno; + + return cfg; } /* Parse a configuration file and put the results in the configuration tree starting at *base. */ -int read_config_file(avl_tree_t *config_tree, const char *fname) -{ - int err = -2; /* Parse error */ - FILE *fp; - char *buffer, *line; - char *variable, *value; - int lineno = 0, ignore = 0; - config_t *cfg; - size_t bufsize; +bool read_config_file(avl_tree_t *config_tree, const char *fname) { + FILE *fp; + char buffer[MAX_STRING_SIZE]; + char *line; + int lineno = 0; + bool ignore = false; + config_t *cfg; + bool result = false; -cp - if((fp = fopen (fname, "r")) == NULL) - { - syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno)); - return -3; - } + fp = fopen(fname, "r"); - bufsize = 100; - buffer = xmalloc(bufsize); - - for(;;) - { - if((line = readline(fp, &buffer, &bufsize)) == NULL) - { - err = -1; - break; + if(!fp) { + logger(LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); + return false; } - if(feof(fp)) - { - err = 0; - break; + for(;;) { + line = readline(fp, buffer, sizeof(buffer)); + + if(!line) { + if(feof(fp)) { + result = true; + } + + break; + } + + lineno++; + + if(!*line || *line == '#') { + continue; + } + + if(ignore) { + if(!strncmp(line, "-----END", 8)) { + ignore = false; + } + + continue; + } + + if(!strncmp(line, "-----BEGIN", 10)) { + ignore = true; + continue; + } + + cfg = parse_config_line(line, fname, lineno); + + if(!cfg) { + break; + } + + config_add(config_tree, cfg); } - lineno++; + fclose(fp); - if((variable = strtok(line, "\t =")) == NULL) - continue; /* no tokens on this line */ - - if(variable[0] == '#') - continue; /* comment: ignore */ - - if(!strcmp(variable, "-----BEGIN")) - ignore = 1; - - if(!ignore) - { - if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#') - { - syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"), - variable, lineno, fname); - break; - } - - cfg = new_config(); - cfg->variable = xstrdup(variable); - cfg->value = xstrdup(value); - cfg->file = xstrdup(fname); - cfg->line = lineno; - - config_add(config_tree, cfg); - } - - if(!strcmp(variable, "-----END")) - ignore = 0; - } - - free(buffer); - fclose (fp); -cp - return err; + return result; } -int read_server_config() -{ - char *fname; - int x; -cp - asprintf(&fname, "%s/tinc.conf", confbase); - x = read_config_file(config_tree, fname); - if(x == -1) /* System error: complain */ - { - syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno)); - } - free(fname); -cp - return x; +void read_config_options(avl_tree_t *config_tree, const char *prefix) { + size_t prefix_len = prefix ? strlen(prefix) : 0; + + for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) { + const config_t *cfg = node->data; + + if(!prefix) { + if(strchr(cfg->variable, '.')) { + continue; + } + } else { + if(strncmp(prefix, cfg->variable, prefix_len) || + cfg->variable[prefix_len] != '.') { + continue; + } + } + + config_t *new = new_config(); + + if(prefix) { + new->variable = xstrdup(cfg->variable + prefix_len + 1); + } else { + new->variable = xstrdup(cfg->variable); + } + + new->value = xstrdup(cfg->value); + new->file = NULL; + new->line = cfg->line; + + config_add(config_tree, new); + } } -int isadir(const char* f) -{ - struct stat s; +bool read_server_config(void) { + char fname[PATH_MAX]; + bool x; - if(stat(f, &s) < 0) - return 0; - else - return S_ISDIR(s.st_mode); -} + read_config_options(config_tree, NULL); -int is_safe_path(const char *file) -{ - char *p; - const char *f; - char x; - struct stat s; - char l[MAXBUFSIZE]; + snprintf(fname, sizeof(fname), "%s/tinc.conf", confbase); + errno = 0; + x = read_config_file(config_tree, fname); - if(*file != '/') - { - syslog(LOG_ERR, _("`%s' is not an absolute path"), file); - return 0; - } + // We will try to read the conf files in the "conf.d" dir + if(x) { + char dname[PATH_MAX]; + snprintf(dname, sizeof(dname), "%s/conf.d", confbase); + DIR *dir = opendir(dname); - p = strrchr(file, '/'); + // If we can find this dir + if(dir) { + struct dirent *ep; - if(p == file) /* It's in the root */ - p++; + // We list all the files in it + while(x && (ep = readdir(dir))) { + size_t l = strlen(ep->d_name); - x = *p; - *p = '\0'; + // And we try to read the ones that end with ".conf" + if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) { + if((size_t)snprintf(fname, sizeof(fname), "%s/%s", dname, ep->d_name) >= sizeof(fname)) { + logger(LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name); + return false; + } - f = file; -check1: - if(lstat(f, &s) < 0) - { - syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); - return 0; - } + x = read_config_file(config_tree, fname); + } + } - if(s.st_uid != geteuid()) - { - syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), - f, s.st_uid, geteuid()); - return 0; - } - - if(S_ISLNK(s.st_mode)) - { - syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), - f); - - if(readlink(f, l, MAXBUFSIZE) < 0) - { - syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno)); - return 0; - } - - f = l; - goto check1; - } - - *p = x; - f = file; - -check2: - if(lstat(f, &s) < 0 && errno != ENOENT) - { - syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); - return 0; - } - - if(errno == ENOENT) - return 1; - - if(s.st_uid != geteuid()) - { - syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), - f, s.st_uid, geteuid()); - return 0; - } - - if(S_ISLNK(s.st_mode)) - { - syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), - f); - - if(readlink(f, l, MAXBUFSIZE) < 0) - { - syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno)); - return 0; - } - - f = l; - goto check2; - } - - if(s.st_mode & 0007) - { - /* Accessible by others */ - syslog(LOG_ERR, _("`%s' has unsecure permissions"), - f); - return 0; - } - - return 1; -} - -FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode) -{ - FILE *r; - char *directory; - char *fn; - - /* Check stdin and stdout */ - if(!isatty(0) || !isatty(1)) - { - /* Argh, they are running us from a script or something. Write - the files to the current directory and let them burn in hell - for ever. */ - fn = xstrdup(filename); - } - else - { - /* Ask for a file and/or directory name. */ - fprintf(stdout, _("Please enter a file to save %s to [%s]: "), - what, filename); - fflush(stdout); - - if((fn = readline(stdin, NULL, NULL)) == NULL) - { - fprintf(stderr, _("Error while reading stdin: %s\n"), strerror(errno)); - return NULL; + closedir(dir); + } } - if(strlen(fn) == 0) - /* User just pressed enter. */ - fn = xstrdup(filename); - } + if(!x && errno) { + logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); + } - if((strchr(fn, '/') == NULL) || (fn[0] != '/')) - { - /* The directory is a relative path or a filename. */ - char *p; - - directory = get_current_dir_name(); - asprintf(&p, "%s/%s", directory, fn); - free(fn); - free(directory); - fn = p; - } - - umask(0077); /* Disallow everything for group and other */ - - /* Open it first to keep the inode busy */ - if((r = fopen(fn, mode)) == NULL) - { - fprintf(stderr, _("Error opening file `%s': %s\n"), - fn, strerror(errno)); - free(fn); - return NULL; - } - - /* Then check the file for nasty attacks */ - if(!is_safe_path(fn)) /* Do not permit any directories that are - readable or writeable by other users. */ - { - fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n" - "I will not create or overwrite this file.\n"), - fn); - fclose(r); - free(fn); - return NULL; - } - - free(fn); - - return r; + return x; } + +bool read_connection_config(connection_t *c) { + char fname[PATH_MAX]; + bool x; + + read_config_options(c->config_tree, c->name); + + snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, c->name); + x = read_config_file(c->config_tree, fname); + + return x; +} + +static void disable_old_keys(const char *filename) { + char tmpfile[PATH_MAX] = ""; + char buf[1024]; + bool disabled = false; + FILE *r, *w; + + r = fopen(filename, "r"); + + if(!r) { + return; + } + + int len = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); + + if(len < 0 || len >= PATH_MAX) { + fprintf(stderr, "Pathname too long: %s.tmp\n", filename); + w = NULL; + } else { + w = fopen(tmpfile, "w"); + } + + while(fgets(buf, sizeof(buf), r)) { + if(!strncmp(buf, "-----BEGIN RSA", 14)) { + buf[11] = 'O'; + buf[12] = 'L'; + buf[13] = 'D'; + disabled = true; + } else if(!strncmp(buf, "-----END RSA", 12)) { + buf[ 9] = 'O'; + buf[10] = 'L'; + buf[11] = 'D'; + disabled = true; + } + + if(w && fputs(buf, w) < 0) { + disabled = false; + break; + } + } + + if(w) { + fclose(w); + } + + fclose(r); + + if(!w && disabled) { + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + return; + } + + if(disabled) { +#ifdef HAVE_MINGW + // We cannot atomically replace files on Windows. + char bakfile[PATH_MAX] = ""; + snprintf(bakfile, sizeof(bakfile), "%s.bak", filename); + + if(rename(filename, bakfile) || rename(tmpfile, filename)) { + rename(bakfile, filename); +#else + + if(rename(tmpfile, filename)) { +#endif + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + } else { +#ifdef HAVE_MINGW + unlink(bakfile); +#endif + fprintf(stderr, "Warning: old key(s) found and disabled.\n"); + } + } + + unlink(tmpfile); +} + +FILE *ask_and_open(const char *filename, const char *what) { + FILE *r; + char directory[PATH_MAX]; + char line[PATH_MAX]; + char abspath[PATH_MAX]; + const char *fn; + + /* Check stdin and stdout */ + if(!isatty(0) || !isatty(1)) { + /* Argh, they are running us from a script or something. Write + the files to the current directory and let them burn in hell + for ever. */ + fn = filename; + } else { + /* Ask for a file and/or directory name. */ + fprintf(stdout, "Please enter a file to save %s to [%s]: ", + what, filename); + fflush(stdout); + + fn = readline(stdin, line, sizeof(line)); + + if(!fn) { + fprintf(stderr, "Error while reading stdin: %s\n", + strerror(errno)); + return NULL; + } + + if(!strlen(fn)) + /* User just pressed enter. */ + { + fn = filename; + } + } + +#ifdef HAVE_MINGW + + if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) { +#else + + if(fn[0] != '/') { +#endif + /* The directory is a relative path or a filename. */ + getcwd(directory, sizeof(directory)); + + if((size_t)snprintf(abspath, sizeof(abspath), "%s/%s", directory, fn) >= sizeof(abspath)) { + fprintf(stderr, "Pathname too long: %s/%s\n", directory, fn); + return NULL; + } + + fn = abspath; + } + + umask(0077); /* Disallow everything for group and other */ + + disable_old_keys(fn); + + /* Open it first to keep the inode busy */ + + r = fopen(fn, "a"); + + if(!r) { + fprintf(stderr, "Error opening file `%s': %s\n", + fn, strerror(errno)); + return NULL; + } + + return r; +} + + diff --git a/src/conf.h b/src/conf.h index bf399dd..770ada7 100644 --- a/src/conf.h +++ b/src/conf.h @@ -1,7 +1,10 @@ +#ifndef TINC_CONF_H +#define TINC_CONF_H + /* conf.h -- header for conf.c - Copyright (C) 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans + 2000-2012 Guus Sliepen 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 @@ -13,58 +16,52 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: conf.h,v 1.6.4.32 2002/02/18 16:25:16 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_CONF_H__ -#define __TINC_CONF_H__ - -#include -#include -#include - -#include -#include "net.h" -#include "subnet.h" +#include "avl_tree.h" +#include "list.h" typedef struct config_t { - char *variable; - char *value; - char *file; - int line; + char *variable; + char *value; + char *file; + int line; } config_t; +#include "subnet.h" + extern avl_tree_t *config_tree; -extern int debug_lvl; +extern int pinginterval; extern int pingtimeout; extern int maxtimeout; -extern int bypass_security; +extern int mintimeout; +extern bool bypass_security; extern char *confbase; extern char *netname; +extern list_t *cmdline_conf; -extern void init_configuration(avl_tree_t **); -extern void exit_configuration(avl_tree_t **); -extern config_t *new_config(void); -extern void free_config(config_t *); -extern void config_add(avl_tree_t *, config_t *); -extern config_t *lookup_config(avl_tree_t *, char *); -extern config_t *lookup_config_next(avl_tree_t *, config_t *); -extern int get_config_bool(config_t *, int *); -extern int get_config_int(config_t *, int *); -extern int get_config_port(config_t *, port_t *); -extern int get_config_string(config_t *, char **); -extern int get_config_address(config_t *, struct addrinfo **); -struct subnet_t; /* Needed for next line. */ -extern int get_config_subnet(config_t *, struct subnet_t **); +extern void init_configuration(avl_tree_t **config_tree); +extern void exit_configuration(avl_tree_t **config_tree); +extern config_t *new_config(void) __attribute__((__malloc__)); +extern void free_config(config_t *cfg); +extern void config_add(avl_tree_t *config_tree, config_t *cfg); +extern config_t *lookup_config(const avl_tree_t *config_tree, char *variable); +extern config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg); +extern bool get_config_bool(const config_t *cfg, bool *result); +extern bool get_config_int(const config_t *cfg, int *result); +extern bool get_config_string(const config_t *cfg, char **result); +extern bool get_config_address(const config_t *cfg, struct addrinfo **result); +extern bool get_config_subnet(const config_t *cfg, struct subnet_t **result); -extern int read_config_file(avl_tree_t *, const char *); -extern int read_server_config(void); -extern FILE *ask_and_safe_open(const char*, const char*, const char *); -extern int is_safe_path(const char *); +extern config_t *parse_config_line(char *line, const char *fname, int lineno); +extern bool read_config_file(avl_tree_t *config_tree, const char *fname); +extern void read_config_options(avl_tree_t *config_tree, const char *prefix); +extern bool read_server_config(void); +extern bool read_connection_config(struct connection_t *c); +extern FILE *ask_and_open(const char *fname, const char *what); -#endif /* __TINC_CONF_H__ */ +#endif diff --git a/src/connection.c b/src/connection.c index 391982a..d137af1 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1,7 +1,8 @@ /* connection.c -- connection list management - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2016 Guus Sliepen , + 2000-2005 Ivo Timmermans + 2008 Max Rijevski 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 @@ -13,125 +14,138 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: connection.c,v 1.1.2.29 2002/03/22 13:31:18 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include - -#include -#include - -#include "net.h" /* Don't ask. */ -#include "netutl.h" -#include "config.h" -#include "conf.h" -#include -#include "subnet.h" - -#include "xalloc.h" #include "system.h" -avl_tree_t *connection_tree; /* Meta connections */ +#include "avl_tree.h" +#include "conf.h" +#include "logger.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" -int connection_compare(connection_t *a, connection_t *b) -{ - return a - b; +avl_tree_t *connection_tree; /* Meta connections */ +connection_t *everyone; + +static int connection_compare(const connection_t *a, const connection_t *b) { + return a < b ? -1 : a == b ? 0 : 1; } -void init_connections(void) -{ -cp - connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL); -cp +void init_connections(void) { + connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, (avl_action_t) free_connection); + everyone = new_connection(); + everyone->name = xstrdup("everyone"); + everyone->hostname = xstrdup("BROADCAST"); } -void exit_connections(void) -{ -cp - avl_delete_tree(connection_tree); -cp +void exit_connections(void) { + avl_delete_tree(connection_tree); + free_connection(everyone); } -connection_t *new_connection(void) -{ - connection_t *c; -cp - c = (connection_t *)xmalloc_and_zero(sizeof(connection_t)); +connection_t *new_connection(void) { + connection_t *c; - if(!c) - return NULL; + c = xmalloc_and_zero(sizeof(connection_t)); - gettimeofday(&c->start, NULL); -cp - return c; + if(!c) { + return NULL; + } + + gettimeofday(&c->start, NULL); + + return c; } -void free_connection(connection_t *c) -{ -cp - if(c->hostname) - free(c->hostname); - if(c->inkey) - free(c->inkey); - if(c->outkey) - free(c->outkey); - if(c->mychallenge) - free(c->mychallenge); - if(c->hischallenge) - free(c->hischallenge); - free(c); -cp +void free_connection_partially(connection_t *c) { + free(c->inkey); + free(c->outkey); + free(c->mychallenge); + free(c->hischallenge); + free(c->outbuf); + + c->inkey = NULL; + c->outkey = NULL; + c->mychallenge = NULL; + c->hischallenge = NULL; + c->outbuf = NULL; + + c->status.pinged = false; + c->status.active = false; + c->status.connecting = false; + c->status.timeout = false; + c->status.encryptout = false; + c->status.decryptin = false; + c->status.mst = false; + + c->options = 0; + c->buflen = 0; + c->reqlen = 0; + c->tcplen = 0; + c->allow_request = 0; + c->outbuflen = 0; + c->outbufsize = 0; + c->outbufstart = 0; + c->last_ping_time = 0; + c->last_flushed_time = 0; + c->inbudget = 0; + c->outbudget = 0; + + if(c->inctx) { + EVP_CIPHER_CTX_reset(c->inctx); + free(c->inctx); + c->inctx = NULL; + } + + if(c->outctx) { + EVP_CIPHER_CTX_reset(c->outctx); + free(c->outctx); + c->outctx = NULL; + } + + if(c->rsa_key) { + RSA_free(c->rsa_key); + c->rsa_key = NULL; + } } -void connection_add(connection_t *c) -{ -cp - avl_insert(connection_tree, c); -cp +void free_connection(connection_t *c) { + free_connection_partially(c); + + free(c->name); + free(c->hostname); + + if(c->config_tree) { + exit_configuration(&c->config_tree); + } + + free(c); } -void connection_del(connection_t *c) -{ -cp - avl_delete(connection_tree, c); -cp +void connection_add(connection_t *c) { + avl_insert(connection_tree, c); } -void dump_connections(void) -{ - avl_node_t *node; - connection_t *c; -cp - syslog(LOG_DEBUG, _("Connections:")); - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"), - c->name, c->hostname, c->options, c->socket, c->status); - } - - syslog(LOG_DEBUG, _("End of connections.")); -cp +void connection_del(connection_t *c) { + avl_delete(connection_tree, c); } -int read_connection_config(connection_t *c) -{ - char *fname; - int x; -cp - asprintf(&fname, "%s/hosts/%s", confbase, c->name); - x = read_config_file(c->config_tree, fname); - free(fname); -cp - return x; +void dump_connections(void) { + avl_node_t *node; + connection_t *c; + + logger(LOG_DEBUG, "Connections:"); + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + logger(LOG_DEBUG, " %s at %s options %x socket %d status %04x outbuf %d/%d/%d", + c->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof(c->status)), + c->outbufsize, c->outbufstart, c->outbuflen); + } + + logger(LOG_DEBUG, "End of connections."); } diff --git a/src/connection.h b/src/connection.h index 0cdcc09..d619e85 100644 --- a/src/connection.h +++ b/src/connection.h @@ -1,7 +1,10 @@ +#ifndef TINC_CONNECTION_H +#define TINC_CONNECTION_H + /* connection.h -- header for connection.c - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2016 Guus Sliepen , + 2000-2005 Ivo Timmermans 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 @@ -13,109 +16,108 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: connection.h,v 1.1.2.26 2002/02/20 19:25:09 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_CONNECTION_H__ -#define __TINC_CONNECTION_H__ +#include +#include -#include - -#include -#include - -#ifdef HAVE_OPENSSL_EVP_H -# include -#else -# include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_cleanup(c) #endif -#ifdef HAVE_OPENSSL_RSA_H -# include -#else -# include -#endif +#include "avl_tree.h" -#include "net.h" -#include "conf.h" - -#include "node.h" -#include "edge.h" - -#define OPTION_INDIRECT 0x0001 -#define OPTION_TCPONLY 0x0002 +#define OPTION_INDIRECT 0x0001 +#define OPTION_TCPONLY 0x0002 +#define OPTION_PMTU_DISCOVERY 0x0004 +#define OPTION_CLAMP_MSS 0x0008 typedef struct connection_status_t { - int pinged:1; /* sent ping */ - int active:1; /* 1 if active.. */ - int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ - int termreq:1; /* the termination of this connection was requested */ - int remove:1; /* Set to 1 if you want this connection removed */ - int timeout:1; /* 1 if gotten timeout */ - int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - int decryptin:1; /* 1 if we have to decrypt incoming traffic */ - int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - int unused:18; + unsigned int pinged: 1; /* sent ping */ + unsigned int active: 1; /* 1 if active.. */ + unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */ + unsigned int unused_termreq: 1; /* the termination of this connection was requested */ + unsigned int remove: 1; /* Set to 1 if you want this connection removed */ + unsigned int timeout: 1; /* 1 if gotten timeout */ + unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */ + unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */ + unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */ + unsigned int proxy_passed: 1; /* 1 if we are connecting via a proxy and we have finished talking with it */ + unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */ + unsigned int unused: 21; } connection_status_t; +#include "edge.h" +#include "net.h" +#include "node.h" + typedef struct connection_t { - char *name; /* name he claims to have */ + char *name; /* name he claims to have */ - sockaddr_t address; /* his real (internet) ip */ - char *hostname; /* the hostname of its real ip */ - int protocol_version; /* used protocol */ + union sockaddr_t address; /* his real (internet) ip */ + char *hostname; /* the hostname of its real ip */ + int protocol_version; /* used protocol */ - int socket; /* socket used for this connection */ - long int options; /* options for this connection */ - struct connection_status_t status; /* status info */ - int estimated_weight; /* estimation for the weight of the edge for this connection */ - struct timeval start; /* time this connection was started, used for above estimation */ - struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ + int socket; /* socket used for this connection */ + uint32_t options; /* options for this connection */ + connection_status_t status; /* status info */ + int estimated_weight; /* estimation for the weight of the edge for this connection */ + struct timeval start; /* time this connection was started, used for above estimation */ + struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ - struct node_t *node; /* node associated with the other end */ - struct edge_t *edge; /* edge associated with this connection */ + struct node_t *node; /* node associated with the other end */ + struct edge_t *edge; /* edge associated with this connection */ - RSA *rsa_key; /* his public/private key */ - const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ - const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ - EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ - EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ - char *inkey; /* His symmetric meta key + iv */ - char *outkey; /* Our symmetric meta key + iv */ - int inkeylength; /* Length of his key + iv */ - int outkeylength; /* Length of our key + iv */ - const EVP_MD *indigest; - const EVP_MD *outdigest; - int inmaclength; - int outmaclength; - int incompression; - int outcompression; - char *mychallenge; /* challenge we received from him */ - char *hischallenge; /* challenge we sent to him */ + RSA *rsa_key; /* his public/private key */ + const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ + const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ + EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ + EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ + uint64_t inbudget; /* Encrypted bytes send budget */ + uint64_t outbudget; /* Encrypted bytes receive budget */ + char *inkey; /* His symmetric meta key + iv */ + char *outkey; /* Our symmetric meta key + iv */ + int inkeylength; /* Length of his key + iv */ + int outkeylength; /* Length of our key + iv */ + const EVP_MD *indigest; + const EVP_MD *outdigest; + int inmaclength; + int outmaclength; + int incompression; + int outcompression; + char *mychallenge; /* challenge we received from him */ + char *hischallenge; /* challenge we sent to him */ - char buffer[MAXBUFSIZE]; /* metadata input buffer */ - int buflen; /* bytes read into buffer */ - int tcplen; /* length of incoming TCPpacket */ - int allow_request; /* defined if there's only one request possible */ + char buffer[MAXBUFSIZE]; /* metadata input buffer */ + int buflen; /* bytes read into buffer */ + int reqlen; /* length of incoming request */ + length_t tcplen; /* length of incoming TCPpacket */ + int allow_request; /* defined if there's only one request possible */ - time_t last_ping_time; /* last time we saw some activity from the other end */ + char *outbuf; /* metadata output buffer */ + int outbufstart; /* index of first meaningful byte in output buffer */ + int outbuflen; /* number of meaningful bytes in output buffer */ + int outbufsize; /* number of bytes allocated to output buffer */ - avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ + time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */ + time_t last_flushed_time; /* last time buffer was empty. Only meaningful if outbuflen > 0 */ + + avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ } connection_t; extern avl_tree_t *connection_tree; +extern connection_t *everyone; extern void init_connections(void); extern void exit_connections(void); -extern connection_t *new_connection(void); -extern void free_connection(connection_t *); -extern void connection_add(connection_t *); -extern void connection_del(connection_t *); +extern connection_t *new_connection(void) __attribute__((__malloc__)); +extern void free_connection(connection_t *c); +extern void free_connection_partially(connection_t *c); +extern void connection_add(connection_t *c); +extern void connection_del(connection_t *c); extern void dump_connections(void); -extern int read_connection_config(connection_t *); -#endif /* __TINC_CONNECTION_H__ */ +#endif diff --git a/src/cygwin/device.c b/src/cygwin/device.c new file mode 100644 index 0000000..1165d67 --- /dev/null +++ b/src/cygwin/device.c @@ -0,0 +1,287 @@ +/* + device.c -- Interaction with Windows tap driver in a Cygwin environment + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2016 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "../system.h" +#include "../net.h" + +#include +#include + +#include "../conf.h" +#include "../device.h" +#include "../logger.h" +#include "../route.h" +#include "../utils.h" +#include "../xalloc.h" + +#include "../mingw/common.h" + +int device_fd = -1; +static HANDLE device_handle = INVALID_HANDLE_VALUE; +char *device = NULL; +char *iface = NULL; +static const char *device_info = "Windows tap device"; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static pid_t reader_pid; +static int sp[2]; + +static bool setup_device(void) { + HKEY key, key2; + int i, err; + + char regpath[1024]; + char adapterid[1024]; + char adaptername[1024]; + char tapname[1024]; + char gelukt = 0; + long len; + + bool found = false; + + get_config_string(lookup_config(config_tree, "Device"), &device); + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + if(device && iface) { + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + } + + /* Open registry and look for network adapters */ + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) { + logger(LOG_ERR, "Unable to read registry: %s", winerror(GetLastError())); + return false; + } + + for(i = 0; ; i++) { + len = sizeof(adapterid); + + if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) { + break; + } + + /* Find out more about this adapter */ + + snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) { + continue; + } + + len = sizeof(adaptername); + err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); + + RegCloseKey(key2); + + if(err) { + continue; + } + + if(device) { + if(!strcmp(device, adapterid)) { + found = true; + break; + } else { + continue; + } + } + + if(iface) { + if(!strcmp(iface, adaptername)) { + found = true; + break; + } else { + continue; + } + } + + snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + + if(device_handle != INVALID_HANDLE_VALUE) { + CloseHandle(device_handle); + found = true; + break; + } + } + + RegCloseKey(key); + + if(!found) { + logger(LOG_ERR, "No Windows tap device found!"); + return false; + } + + if(!device) { + device = xstrdup(adapterid); + } + + if(!iface) { + iface = xstrdup(adaptername); + } + + snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device); + + /* Now we are going to open this device twice: once for reading and once for writing. + We do this because apparently it isn't possible to check for activity in the select() loop. + Furthermore I don't really know how to do it the "Windows" way. */ + + if(socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, sp)) { + logger(LOG_DEBUG, "System call `%s' failed: %s", "socketpair", strerror(errno)); + return false; + } + + /* The parent opens the tap device for writing. */ + + device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + + if(device_handle == INVALID_HANDLE_VALUE) { + logger(LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError())); + return false; + } + + device_fd = sp[0]; + + /* Get MAC address from tap device */ + + if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { + logger(LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError())); + return false; + } + + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = 1; + } + + /* Now we start the child */ + + reader_pid = fork(); + + if(reader_pid == -1) { + logger(LOG_DEBUG, "System call `%s' failed: %s", "fork", strerror(errno)); + return false; + } + + if(!reader_pid) { + /* The child opens the tap device for reading, blocking. + It passes everything it reads to the socket. */ + + char buf[MTU]; + long lenin; + + CloseHandle(device_handle); + + device_handle = CreateFile(tapname, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + + if(device_handle == INVALID_HANDLE_VALUE) { + logger(LOG_ERR, "Could not open Windows tap device %s (%s) for reading: %s", device, iface, winerror(GetLastError())); + buf[0] = 0; + write(sp[1], buf, 1); + exit(1); + } + + logger(LOG_DEBUG, "Tap reader forked and running."); + + /* Notify success */ + + buf[0] = 1; + write(sp[1], buf, 1); + + /* Pass packets */ + + for(;;) { + ReadFile(device_handle, buf, MTU, &lenin, NULL); + write(sp[1], buf, lenin); + } + } + + read(device_fd, &gelukt, 1); + + if(gelukt != 1) { + logger(LOG_DEBUG, "Tap reader failed!"); + return false; + } + + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); + + return true; +} + +static void close_device(void) { + close(sp[0]); + close(sp[1]); + CloseHandle(device_handle); + + kill(reader_pid, SIGKILL); + + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + if((lenin = read(sp[0], packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + long lenout; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + if(!WriteFile(device_handle, packet->data, packet->len, &lenout, NULL)) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError())); + return false; + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t os_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/device.c b/src/device.c deleted file mode 100644 index e896f54..0000000 --- a/src/device.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - device.c -- Interaction with Linux ethertap and tun/tap device - Copyright (C) 2001-2002 Ivo Timmermans , - 2001-2002 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.c,v 1.1.2.8 2002/03/24 16:36:56 guus Exp $ -*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_TUNTAP - #ifdef LINUX_IF_TUN_H - #include LINUX_IF_TUN_H - #else - #include - #endif - #define DEFAULT_DEVICE "/dev/misc/net/tun" -#else - #define DEFAULT_DEVICE "/dev/tap0" -#endif - -#include -#include "conf.h" -#include "net.h" -#include "subnet.h" - -#include "system.h" - -#define DEVICE_TYPE_ETHERTAP 0 -#define DEVICE_TYPE_TUNTAP 1 - -int device_fd = -1; -int device_type; -char *device; -char *interface; -char ifrname[IFNAMSIZ]; -char *device_info; - -int device_total_in = 0; -int device_total_out = 0; - -extern subnet_t mymac; - -/* - open the local ethertap device -*/ -int setup_device(void) -{ - struct ifreq ifr; - -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) -#ifdef HAVE_TUNTAP - interface = netname; -#else - interface = rindex(device, '/')?rindex(device, '/')+1:device; -#endif -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - -#ifdef HAVE_TUNTAP - /* Ok now check if this is an old ethertap or a new tun/tap thingie */ - - memset(&ifr, 0, sizeof(ifr)); -cp - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if (interface) - strncpy(ifr.ifr_name, interface, IFNAMSIZ); -cp - if (!ioctl(device_fd, TUNSETIFF, (void *) &ifr)) - { - device_info = _("Linux tun/tap device"); - device_type = DEVICE_TYPE_TUNTAP; - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else - if (!ioctl(device_fd, (('T'<< 8) | 202), (void *) &ifr)) - { - syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device); - device_type = DEVICE_TYPE_TUNTAP; - device_info = _("Linux tun/tap device"); - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else -#endif - { - device_info = _("Linux ethertap device"); - device_type = DEVICE_TYPE_ETHERTAP; - interface = rindex(device, '/')?rindex(device, '/')+1:device; - } - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; -} - -void close_device(void) -{ -cp - close(device_fd); -} - -/* - read, encrypt and send data that is - available through the ethertap device -*/ -int read_packet(vpn_packet_t *packet) -{ - int lenin; -cp - if(device_type == DEVICE_TYPE_TUNTAP) - { - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - packet->len = lenin; - } - else /* ethertap */ - { - if((lenin = read(device_fd, packet->data - 2, MTU + 2)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - packet->len = lenin - 2; - } - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } - - return 0; -cp -} - -int write_packet(vpn_packet_t *packet) -{ -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(device_type == DEVICE_TYPE_TUNTAP) - { - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } - else/* ethertap */ - { - *(short int *)(packet->data - 2) = packet->len; - if(write(device_fd, packet->data - 2, packet->len + 2) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } - - device_total_out += packet->len; -cp - return 0; -} - -void dump_device_stats(void) -{ -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} diff --git a/src/device.h b/src/device.h index 3d3aa76..6bfc44d 100644 --- a/src/device.h +++ b/src/device.h @@ -1,7 +1,10 @@ +#ifndef TINC_DEVICE_H +#define TINC_DEVICE_H + /* - net.h -- generic header for device.c - Copyright (C) 2001-2002 Ivo Timmermans - 2001-2002 Guus Sliepen + device.h -- generic header for device.c + Copyright (C) 2001-2005 Ivo Timmermans + 2001-2012 Guus Sliepen 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 @@ -13,24 +16,32 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_DEVICE_H__ -#define __TINC_DEVICE_H__ +#include "net.h" extern int device_fd; extern char *device; -extern char *interface; -extern int setup_device(void); -extern void close_device(void); -extern int read_packet(vpn_packet_t *); -extern int write_packet(vpn_packet_t *); -extern void dump_device_stats(void); +extern char *iface; -#endif /* __TINC_DEVICE_H__ */ +typedef struct devops_t { + bool (*setup)(void); + void (*close)(void); + bool (*read)(struct vpn_packet_t *packet); + bool (*write)(struct vpn_packet_t *packet); + void (*dump_stats)(void); +} devops_t; + +extern const devops_t os_devops; +extern const devops_t dummy_devops; +extern const devops_t raw_socket_devops; +extern const devops_t multicast_devops; +extern const devops_t uml_devops; +extern const devops_t vde_devops; +extern devops_t devops; + +#endif diff --git a/src/dropin.c b/src/dropin.c new file mode 100644 index 0000000..93511f1 --- /dev/null +++ b/src/dropin.c @@ -0,0 +1,142 @@ +/* + dropin.c -- a set of drop-in replacements for libc functions + Copyright (C) 2000-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "xalloc.h" + +#ifndef HAVE_DAEMON +/* + Replacement for the daemon() function. + + The daemon() function is for programs wishing to detach themselves + from the controlling terminal and run in the background as system + daemons. + + Unless the argument nochdir is non-zero, daemon() changes the + current working directory to the root (``/''). + + Unless the argument noclose is non-zero, daemon() will redirect + standard input, standard output and standard error to /dev/null. +*/ +int daemon(int nochdir, int noclose) { +#ifdef HAVE_FORK + pid_t pid; + int fd; + + pid = fork(); + + /* Check if forking failed */ + if(pid < 0) { + perror("fork"); + exit(-1); + } + + /* If we are the parent, terminate */ + if(pid) { + exit(0); + } + + /* Detach by becoming the new process group leader */ + if(setsid() < 0) { + perror("setsid"); + return -1; + } + + /* Change working directory to the root (to avoid keeping mount + points busy) */ + if(!nochdir) { + chdir("/"); + } + + /* Redirect stdin/out/err to /dev/null */ + if(!noclose) { + fd = open("/dev/null", O_RDWR); + + if(fd < 0) { + perror("opening /dev/null"); + return -1; + } else { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + } + } + + return 0; +#else + return -1; +#endif +} +#endif + +#ifndef HAVE_ASPRINTF +int asprintf(char **buf, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = vasprintf(buf, fmt, ap); + va_end(ap); + return result; +} + +int vasprintf(char **buf, const char *fmt, va_list ap) { + int status; + va_list aq; + int len; + + len = 4096; + *buf = xmalloc(len); + + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + buf[len - 1] = 0; + va_end(aq); + + if(status >= 0) { + *buf = xrealloc(*buf, status + 1); + } + + if(status > len - 1) { + len = status; + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + va_end(aq); + } + + return status; +} +#endif + +#ifndef HAVE_GETTIMEOFDAY +int gettimeofday(struct timeval *tv, void *tz) { + tv->tv_sec = time(NULL); + tv->tv_usec = 0; + return 0; +} +#endif + +#ifndef HAVE_USLEEP +int usleep(long long usec) { + struct timeval tv = {usec / 1000000, (usec / 1000) % 1000}; + select(0, NULL, NULL, NULL, &tv); + return 0; +} +#endif diff --git a/src/dropin.h b/src/dropin.h new file mode 100644 index 0000000..012099b --- /dev/null +++ b/src/dropin.h @@ -0,0 +1,48 @@ +#ifndef TINC_DROPIN_H +#define TINC_DROPIN_H + +/* + dropin.h -- header file for dropin.c + Copyright (C) 2000-2005 Ivo Timmermans, + 2000-2011 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "fake-getaddrinfo.h" +#include "fake-getnameinfo.h" + +#ifndef HAVE_DAEMON +extern int daemon(int nochdir, int noclose); +#endif + +#ifndef HAVE_GET_CURRENT_DIR_NAME +extern char *get_current_dir_name(void); +#endif + +#ifndef HAVE_ASPRINTF +extern int asprintf(char **buf, const char *fmt, ...); +extern int vasprintf(char **buf, const char *fmt, va_list ap); +#endif + +#ifndef HAVE_GETTIMEOFDAY +extern int gettimeofday(struct timeval *tv, void *tz); +#endif + +#ifndef HAVE_USLEEP +extern int usleep(long long usec); +#endif + +#endif diff --git a/src/dummy_device.c b/src/dummy_device.c new file mode 100644 index 0000000..d1d751b --- /dev/null +++ b/src/dummy_device.c @@ -0,0 +1,66 @@ +/* + device.c -- Dummy device + Copyright (C) 2011 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "device.h" +#include "logger.h" +#include "net.h" +#include "xalloc.h" + +static const char *device_info = "dummy device"; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static bool setup_device(void) { + device = xstrdup("dummy"); + iface = xstrdup("dummy"); + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); + return true; +} + +static void close_device(void) { + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + (void)packet; + return false; +} + +static bool write_packet(vpn_packet_t *packet) { + device_total_out += packet->len; + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t dummy_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/edge.c b/src/edge.c index c35af07..c30d6cc 100644 --- a/src/edge.c +++ b/src/edge.c @@ -1,7 +1,7 @@ /* edge.c -- edge tree management - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2006 Guus Sliepen , + 2000-2005 Ivo Timmermans 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 @@ -13,199 +13,121 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: edge.c,v 1.1.2.10 2002/03/27 15:26:43 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include - -#include -#include - -#include "net.h" /* Don't ask. */ -#include "netutl.h" -#include "config.h" -#include "conf.h" -#include -#include "subnet.h" - -#include "xalloc.h" #include "system.h" -avl_tree_t *edge_tree; /* Tree with all known edges (replaces active_tree) */ -avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */ +#include "avl_tree.h" +#include "edge.h" +#include "logger.h" +#include "netutl.h" +#include "node.h" +#include "utils.h" +#include "xalloc.h" -int edge_compare(edge_t *a, edge_t *b) -{ - int result; +avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */ - result = strcmp(a->from.node->name, b->from.node->name); - - if(result) - return result; - else - return strcmp(a->to.node->name, b->to.node->name); +static int edge_compare(const edge_t *a, const edge_t *b) { + return strcmp(a->to->name, b->to->name); } -/* Evil edge_compare() from a parallel universe ;) +static int edge_weight_compare(const edge_t *a, const edge_t *b) { + int result; -int edge_compare(edge_t *a, edge_t *b) -{ - int result; + result = a->weight - b->weight; - return (result = strcmp(a->from.node->name, b->from.node->name)) || (result = strcmp(a->to.node->name, b->to.node->name)), result; + if(result) { + return result; + } + + result = strcmp(a->from->name, b->from->name); + + if(result) { + return result; + } + + return strcmp(a->to->name, b->to->name); } -*/ - -int edge_name_compare(edge_t *a, edge_t *b) -{ - int result; - char *name_a1, *name_a2, *name_b1, *name_b2; - - if(strcmp(a->from.node->name, a->to.node->name) < 0) - name_a1 = a->from.node->name, name_a2 = a->to.node->name; - else - name_a1 = a->to.node->name, name_a2 = a->from.node->name; - - if(strcmp(b->from.node->name, b->to.node->name) < 0) - name_b1 = b->from.node->name, name_b2 = b->to.node->name; - else - name_b1 = b->to.node->name, name_b2 = b->from.node->name; - - result = strcmp(name_a1, name_b1); - - if(result) - return result; - else - return strcmp(name_a2, name_b2); +void init_edges(void) { + edge_weight_tree = avl_alloc_tree((avl_compare_t) edge_weight_compare, NULL); } -int edge_weight_compare(edge_t *a, edge_t *b) -{ - int result; - - result = a->weight - b->weight; - - if(result) - return result; - else - return edge_name_compare(a, b); +avl_tree_t *new_edge_tree(void) { + return avl_alloc_tree((avl_compare_t) edge_compare, (avl_action_t) free_edge); } -void init_edges(void) -{ -cp - edge_tree = avl_alloc_tree((avl_compare_t)edge_compare, NULL); - edge_weight_tree = avl_alloc_tree((avl_compare_t)edge_weight_compare, NULL); -cp +void free_edge_tree(avl_tree_t *edge_tree) { + avl_delete_tree(edge_tree); } -avl_tree_t *new_edge_tree(void) -{ -cp - return avl_alloc_tree((avl_compare_t)edge_name_compare, NULL); -cp -} - -void free_edge_tree(avl_tree_t *edge_tree) -{ -cp - avl_delete_tree(edge_tree); -cp -} - -void exit_edges(void) -{ -cp - avl_delete_tree(edge_tree); -cp +void exit_edges(void) { + avl_delete_tree(edge_weight_tree); } /* Creation and deletion of connection elements */ -edge_t *new_edge(void) -{ - edge_t *e; -cp - e = (edge_t *)xmalloc_and_zero(sizeof(*e)); -cp - return e; +edge_t *new_edge(void) { + return xmalloc_and_zero(sizeof(edge_t)); } -void free_edge(edge_t *e) -{ -cp - free(e); -cp +void free_edge(edge_t *e) { + sockaddrfree(&e->address); + + free(e); } -void edge_add(edge_t *e) -{ -cp - avl_insert(edge_tree, e); - avl_insert(edge_weight_tree, e); - avl_insert(e->from.node->edge_tree, e); - avl_insert(e->to.node->edge_tree, e); -cp +void edge_add(edge_t *e) { + avl_insert(edge_weight_tree, e); + avl_insert(e->from->edge_tree, e); + + e->reverse = lookup_edge(e->to, e->from); + + if(e->reverse) { + e->reverse->reverse = e; + } } -void edge_del(edge_t *e) -{ -cp - avl_delete(edge_tree, e); - avl_delete(edge_weight_tree, e); - avl_delete(e->from.node->edge_tree, e); - avl_delete(e->to.node->edge_tree, e); -cp +void edge_del(edge_t *e) { + if(e->reverse) { + e->reverse->reverse = NULL; + } + + avl_delete(edge_weight_tree, e); + avl_delete(e->from->edge_tree, e); } -edge_t *lookup_edge(node_t *from, node_t *to) -{ - edge_t v, *result; -cp - v.from.node = from; - v.to.node = to; +edge_t *lookup_edge(node_t *from, node_t *to) { + edge_t v; - result = avl_search(edge_tree, &v); + v.from = from; + v.to = to; - if(result) - return result; -cp - v.from.node = to; - v.to.node = from; - - return avl_search(edge_tree, &v); + return avl_search(from->edge_tree, &v); } -void dump_edges(void) -{ - avl_node_t *node; - edge_t *e; - char *from_udp, *to_udp; -cp - syslog(LOG_DEBUG, _("Edges:")); +void dump_edges(void) { + avl_node_t *node, *node2; + node_t *n; + edge_t *e; + char *address; - for(node = edge_tree->head; node; node = node->next) - { - e = (edge_t *)node->data; - from_udp = sockaddr2hostname(&e->from.udpaddress); - to_udp = sockaddr2hostname(&e->to.udpaddress); - syslog(LOG_DEBUG, _(" %s at %s - %s at %s options %lx weight %d"), - e->from.node->name, from_udp, - e->to.node->name, to_udp, - e->options, e->weight); - free(from_udp); - free(to_udp); - } + logger(LOG_DEBUG, "Edges:"); - syslog(LOG_DEBUG, _("End of edges.")); -cp + for(node = node_tree->head; node; node = node->next) { + n = node->data; + + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = node2->data; + address = sockaddr2hostname(&e->address); + logger(LOG_DEBUG, " %s to %s at %s options %x weight %d", + e->from->name, e->to->name, address, e->options, e->weight); + free(address); + } + } + + logger(LOG_DEBUG, "End of edges."); } diff --git a/src/edge.h b/src/edge.h index 604082f..a7a6302 100644 --- a/src/edge.h +++ b/src/edge.h @@ -1,7 +1,10 @@ +#ifndef TINC_EDGE_H +#define TINC_EDGE_H + /* edge.h -- header for edge.c - Copyright (C) 2001-2002 Guus Sliepen , - 2001-2002 Ivo Timmermans + Copyright (C) 2001-2006 Guus Sliepen , + 2001-2005 Ivo Timmermans 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 @@ -13,50 +16,39 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: edge.h,v 1.1.2.7 2002/03/22 11:43:46 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_EDGE_H__ -#define __TINC_EDGE_H__ - -#include - +#include "avl_tree.h" +#include "connection.h" #include "net.h" #include "node.h" -#include "connection.h" - -typedef struct halfconnection_t { - struct node_t *node; /* node associated with this end of the connection */ -// sockaddr_t tcpaddress; /* real (internet) ip on this end of the meta connection */ - sockaddr_t udpaddress; /* real (internet) ip on this end of the vpn connection */ -} halfconnection_t; typedef struct edge_t { - struct halfconnection_t from; - struct halfconnection_t to; + struct node_t *from; + struct node_t *to; + sockaddr_t address; - long int options; /* options turned on for this edge */ - int weight; /* weight of this edge */ - - struct connection_t *connection; /* connection associated with this edge, if available */ + uint32_t options; /* options turned on for this edge */ + int weight; /* weight of this edge */ + + struct connection_t *connection; /* connection associated with this edge, if available */ + struct edge_t *reverse; /* edge in the opposite direction, if available */ } edge_t; -extern avl_tree_t *edge_tree; /* Tree with all known edges (replaces active_tree) */ -extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ +extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ extern void init_edges(void); extern void exit_edges(void); -extern edge_t *new_edge(void); -extern void free_edge(edge_t *); -extern avl_tree_t *new_edge_tree(void); -extern void free_edge_tree(avl_tree_t *); -extern void edge_add(edge_t *); -extern void edge_del(edge_t *); -extern edge_t *lookup_edge(struct node_t *, struct node_t *); +extern edge_t *new_edge(void) __attribute__((__malloc__)); +extern void free_edge(edge_t *e); +extern avl_tree_t *new_edge_tree(void) __attribute__((__malloc__)); +extern void free_edge_tree(avl_tree_t *edge_tree); +extern void edge_add(edge_t *e); +extern void edge_del(edge_t *e); +extern edge_t *lookup_edge(struct node_t *from, struct node_t *to); extern void dump_edges(void); -#endif /* __TINC_EDGE_H__ */ +#endif diff --git a/src/ethernet.h b/src/ethernet.h new file mode 100644 index 0000000..32f5553 --- /dev/null +++ b/src/ethernet.h @@ -0,0 +1,89 @@ +#ifndef TINC_ETHERNET_H +#define TINC_ETHERNET_H + +/* + ethernet.h -- missing Ethernet related definitions + Copyright (C) 2005 Ivo Timmermans + 2006 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +#ifndef ARPHRD_ETHER +#define ARPHRD_ETHER 1 +#endif + +#ifndef ETH_P_IP +#define ETH_P_IP 0x0800 +#endif + +#ifndef ETH_P_ARP +#define ETH_P_ARP 0x0806 +#endif + +#ifndef ETH_P_IPV6 +#define ETH_P_IPV6 0x86DD +#endif + +#ifndef ETH_P_8021Q +#define ETH_P_8021Q 0x8100 +#endif + +#ifndef HAVE_STRUCT_ETHER_HEADER +struct ether_header { + uint8_t ether_dhost[ETH_ALEN]; + uint8_t ether_shost[ETH_ALEN]; + uint16_t ether_type; +} __attribute__((__packed__)); +#endif + +#ifndef HAVE_STRUCT_ARPHDR +struct arphdr { + uint16_t ar_hrd; + uint16_t ar_pro; + uint8_t ar_hln; + uint8_t ar_pln; + uint16_t ar_op; +} __attribute__((__packed__)); + +#define ARPOP_REQUEST 1 +#define ARPOP_REPLY 2 +#define ARPOP_RREQUEST 3 +#define ARPOP_RREPLY 4 +#define ARPOP_InREQUEST 8 +#define ARPOP_InREPLY 9 +#define ARPOP_NAK 10 +#endif + +#ifndef HAVE_STRUCT_ETHER_ARP +struct ether_arp { + struct arphdr ea_hdr; + uint8_t arp_sha[ETH_ALEN]; + uint8_t arp_spa[4]; + uint8_t arp_tha[ETH_ALEN]; + uint8_t arp_tpa[4]; +} __attribute__((__packed__)); +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op +#endif + +#endif diff --git a/src/event.c b/src/event.c index 028483b..1223222 100644 --- a/src/event.c +++ b/src/event.c @@ -1,7 +1,7 @@ /* event.c -- event queue - Copyright (C) 2002 Guus Sliepen , - 2002 Ivo Timmermans + Copyright (C) 2002-2009 Guus Sliepen , + 2002-2005 Ivo Timmermans 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 @@ -13,98 +13,109 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: event.c,v 1.1.4.2 2002/03/01 14:09:30 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "event.h" - #include "system.h" +#include "avl_tree.h" +#include "event.h" +#include "utils.h" +#include "xalloc.h" + avl_tree_t *event_tree; extern time_t now; -int id; +static int id; -int event_compare(event_t *a, event_t *b) -{ - if(a->time > b->time) - return 1; - if(a->time < b->time) - return -1; - return a->id - b->id; +static int event_compare(const event_t *a, const event_t *b) { + if(a->time > b->time) { + return 1; + } + + if(a->time < b->time) { + return -1; + } + + return a->id - b->id; } -void init_events(void) -{ -cp - event_tree = avl_alloc_tree((avl_compare_t)event_compare, NULL); -cp +void init_events(void) { + event_tree = avl_alloc_tree((avl_compare_t) event_compare, (avl_action_t) free_event); } -void exit_events(void) -{ -cp - avl_delete_tree(event_tree); -cp +void exit_events(void) { + avl_delete_tree(event_tree); } -event_t *new_event(void) -{ - event_t *event; -cp - event = (event_t *)xmalloc_and_zero(sizeof(*event)); -cp - return event; +void expire_events(void) { + avl_node_t *node; + event_t *event; + time_t diff; + + /* + * Make all events appear expired by subtracting the difference between + * the expiration time of the last event and the current time. + */ + + if(!event_tree->tail) { + return; + } + + event = event_tree->tail->data; + + if(event->time <= now) { + return; + } + + diff = event->time - now; + + for(node = event_tree->head; node; node = node->next) { + event = node->data; + event->time -= diff; + } } -void free_event(event_t *event) -{ -cp - free(event); -cp +event_t *new_event(void) { + return xmalloc_and_zero(sizeof(event_t)); } -void event_add(event_t *event) -{ -cp - event->id = ++id; - avl_insert(event_tree, event); -cp +void free_event(event_t *event) { + free(event); } -void event_del(event_t *event) -{ -cp - avl_delete(event_tree, event); -cp +void event_add(event_t *event) { + event->id = ++id; + avl_insert(event_tree, event); } -event_t *get_expired_event(void) -{ - event_t *event; -cp - if(event_tree->head) - { - event = (event_t *)event_tree->head->data; - if(event->time < now) - { - avl_delete(event_tree, event); - return event; - } - } -cp - return NULL; +void event_del(event_t *event) { + avl_delete(event_tree, event); +} + +event_t *get_expired_event(void) { + event_t *event; + + if(event_tree->head) { + event = event_tree->head->data; + + if(event->time <= now) { + avl_node_t *node = event_tree->head; + avl_unlink_node(event_tree, node); + free(node); + return event; + } + } + + return NULL; +} + +event_t *peek_next_event(void) { + if(event_tree->head) { + return event_tree->head->data; + } + + return NULL; } diff --git a/src/event.h b/src/event.h index 7a35612..6d521bb 100644 --- a/src/event.h +++ b/src/event.h @@ -1,7 +1,10 @@ +#ifndef TINC_EVENT_H +#define TINC_EVENT_H + /* event.h -- header for event.c - Copyright (C) 2002 Guus Sliepen , - 2002 Ivo Timmermans + Copyright (C) 2002-2009 Guus Sliepen , + 2002-2005 Ivo Timmermans 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 @@ -13,36 +16,32 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: event.h,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_EVENT_H__ -#define __TINC_EVENT_H__ +#include "avl_tree.h" -#include -#include - -avl_tree_t *event_tree; +extern avl_tree_t *event_tree; typedef void (*event_handler_t)(void *); -typedef struct { - time_t time; - int id; - event_handler_t handler; - void *data; +typedef struct event { + time_t time; + int id; + event_handler_t handler; + void *data; } event_t; extern void init_events(void); extern void exit_events(void); -extern event_t *new_event(void); -extern void free_event(event_t *); -extern void event_add(event_t *); -extern void event_del(event_t *); +extern void expire_events(void); +extern event_t *new_event(void) __attribute__((__malloc__)); +extern void free_event(event_t *event); +extern void event_add(event_t *event); +extern void event_del(event_t *event); extern event_t *get_expired_event(void); +extern event_t *peek_next_event(void); -#endif /* __TINC_EVENT_H__ */ +#endif diff --git a/src/fake-getaddrinfo.c b/src/fake-getaddrinfo.c new file mode 100644 index 0000000..1ee11c5 --- /dev/null +++ b/src/fake-getaddrinfo.c @@ -0,0 +1,108 @@ +/* + * fake library for ssh + * + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). + * These functions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include "system.h" + +#include "ipv4.h" +#include "ipv6.h" +#include "fake-getaddrinfo.h" +#include "xalloc.h" + +#if !HAVE_DECL_GAI_STRERROR +char *gai_strerror(int ecode) { + switch(ecode) { + case EAI_NODATA: + return "No address associated with hostname"; + + case EAI_MEMORY: + return "Memory allocation failure"; + + case EAI_FAMILY: + return "Address family not supported"; + + default: + return "Unknown error"; + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#if !HAVE_DECL_FREEADDRINFO +void freeaddrinfo(struct addrinfo *ai) { + struct addrinfo *next; + + while(ai) { + next = ai->ai_next; + free(ai); + ai = next; + } +} +#endif /* !HAVE_FREEADDRINFO */ + +#if !HAVE_DECL_GETADDRINFO +static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) { + struct addrinfo *ai; + + ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + return ai; +} + +int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { + struct addrinfo *prev = NULL; + struct hostent *hp; + struct in_addr in = {0}; + int i; + uint16_t port = 0; + + if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) { + return EAI_FAMILY; + } + + if(servname) { + port = htons(atoi(servname)); + } + + if(hints && hints->ai_flags & AI_PASSIVE) { + *res = malloc_ai(port, htonl(0x00000000)); + return 0; + } + + if(!hostname) { + *res = malloc_ai(port, htonl(0x7f000001)); + return 0; + } + + hp = gethostbyname(hostname); + + if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) { + return EAI_NODATA; + } + + for(i = 0; hp->h_addr_list[i]; i++) { + *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); + + if(prev) { + prev->ai_next = *res; + } + + prev = *res; + } + + return 0; +} +#endif /* !HAVE_GETADDRINFO */ diff --git a/src/fake-getaddrinfo.h b/src/fake-getaddrinfo.h new file mode 100644 index 0000000..f10cb83 --- /dev/null +++ b/src/fake-getaddrinfo.h @@ -0,0 +1,57 @@ +#ifndef TINC_FAKE_GETADDRINFO_H +#define TINC_FAKE_GETADDRINFO_H + +#ifndef EAI_NODATA +#define EAI_NODATA 1 +#endif + +#ifndef EAI_MEMORY +#define EAI_MEMORY 2 +#endif + +#ifndef EAI_FAMILY +#define EAI_FAMILY 3 +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE 1 +# define AI_CANONNAME 2 +#endif + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST 2 +# define NI_NAMEREQD 4 +# define NI_NUMERICSERV 8 +#endif + +#ifndef AI_NUMERICHOST +#define AI_NUMERICHOST 4 +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#if !HAVE_DECL_GETADDRINFO +int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); +#endif /* !HAVE_GETADDRINFO */ + +#if !HAVE_DECL_GAI_STRERROR +char *gai_strerror(int ecode); +#endif /* !HAVE_GAI_STRERROR */ + +#if !HAVE_DECL_FREEADDRINFO +void freeaddrinfo(struct addrinfo *ai); +#endif /* !HAVE_FREEADDRINFO */ + +#endif diff --git a/src/fake-getnameinfo.c b/src/fake-getnameinfo.c new file mode 100644 index 0000000..e51bce2 --- /dev/null +++ b/src/fake-getnameinfo.c @@ -0,0 +1,64 @@ +/* + * fake library for ssh + * + * This file includes getnameinfo(). + * These functions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include "system.h" + +#include "fake-getnameinfo.h" +#include "fake-getaddrinfo.h" + +#if !HAVE_DECL_GETNAMEINFO + +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + int len; + + if(sa->sa_family != AF_INET) { + return EAI_FAMILY; + } + + if(serv && servlen) { + len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); + + if(len < 0 || len >= servlen) { + return EAI_MEMORY; + } + } + + if(!host || !hostlen) { + return 0; + } + + if(flags & NI_NUMERICHOST) { + len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr)); + + if(len < 0 || len >= hostlen) { + return EAI_MEMORY; + } + + return 0; + } + + hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET); + + if(!hp || !hp->h_name || !hp->h_name[0]) { + return EAI_NODATA; + } + + len = snprintf(host, hostlen, "%s", hp->h_name); + + if(len < 0 || len >= hostlen) { + return EAI_MEMORY; + } + + return 0; +} +#endif /* !HAVE_GETNAMEINFO */ diff --git a/src/fake-getnameinfo.h b/src/fake-getnameinfo.h new file mode 100644 index 0000000..4f24ad1 --- /dev/null +++ b/src/fake-getnameinfo.h @@ -0,0 +1,16 @@ +#ifndef TINC_FAKE_GETNAMEINFO_H +#define TINC_FAKE_GETNAMEINFO_H + +#if !HAVE_DECL_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags); +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#endif diff --git a/src/freebsd/device.c b/src/freebsd/device.c deleted file mode 100644 index 2f5f32e..0000000 --- a/src/freebsd/device.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - device.c -- Interaction with FreeBSD tap device - Copyright (C) 2001-2002 Ivo Timmermans , - 2001-2002 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.c,v 1.1.2.4 2002/02/18 16:25:19 guus Exp $ -*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "conf.h" -#include "net.h" -#include "subnet.h" - -#include "system.h" - -#define DEFAULT_DEVICE "/dev/tap0" - -int device_fd = -1; -int device_type; -char *device; -char *interface; -char *device_info; -int device_total_in = 0; -int device_total_out = 0; - -extern subnet_t mymac; - -/* - open the local ethertap device -*/ -int setup_device(void) -{ -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("FreeBSD tap device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; -} - -void close_device(void) -{ -cp - close(device_fd); -} - -/* - read, encrypt and send data that is - available through the ethertap device -*/ -int read_packet(vpn_packet_t *packet) -{ - int lenin; -cp - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - packet->len = lenin; - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), - packet->len, device_info); - - return 0; -cp -} - -int write_packet(vpn_packet_t *packet) -{ -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} - -void dump_device_stats(void) -{ -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..741c7f2 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,1051 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +#ifdef HAVE_STRING_H +#include +#endif + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#include +#endif /* GNU C library. */ + +#ifdef VMS +#include +#if HAVE_STRING_H - 0 +#include +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) +/* It's not Unix, really. See? Capital letters. */ +#include +#define getpid() GetCurrentProcessId() +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv(); + +static char * +my_index(str, chr) +const char *str; +int chr; +{ + while(*str) { + if(*str == chr) { + return (char *) str; + } + + str++; + } + + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen(const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +extern pid_t libc_pid; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__((__unused__)) +store_args_and_env(int argc, char *const *argv) { + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element(libc_subinit, store_args_and_env); + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char tmp = getopt_nonoption_flags[ch1]; \ + getopt_nonoption_flags[ch1] = getopt_nonoption_flags[ch2]; \ + getopt_nonoption_flags[ch2] = tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange(char **); +#endif + +static void +exchange(argv) +char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + + /* First make sure the handling of the `getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if(nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc(top + 1); + + if(new_str == NULL) { + nonoption_flags_len = nonoption_flags_max_len = 0; + } else { + memcpy(new_str, getopt_nonoption_flags, nonoption_flags_max_len); + memset(&new_str[nonoption_flags_max_len], '\0', + top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + getopt_nonoption_flags = new_str; + } + } + +#endif + + while(top > middle && middle > bottom) { + if(top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for(i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS(bottom + i, top - (middle - bottom) + i); + } + + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for(i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS(bottom + i, middle + i); + } + + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize(int, char *const *, const char *); +#endif +static const char * +_getopt_initialize(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if(optstring[0] == '-') { + ordering = RETURN_IN_ORDER; + ++optstring; + } else if(optstring[0] == '+') { + ordering = REQUIRE_ORDER; + ++optstring; + } else if(posixly_correct != NULL) { + ordering = REQUIRE_ORDER; + } else { + ordering = PERMUTE; + } + +#ifdef _LIBC + + if(posixly_correct == NULL + && argc == original_argc && argv == original_argv) { + if(nonoption_flags_max_len == 0) { + if(getopt_nonoption_flags == NULL + || getopt_nonoption_flags[0] == '\0') { + nonoption_flags_max_len = -1; + } else { + const char *orig_str = getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen(orig_str); + + if(nonoption_flags_max_len < argc) { + nonoption_flags_max_len = argc; + } + + getopt_nonoption_flags = + (char *) malloc(nonoption_flags_max_len); + + if(getopt_nonoption_flags == NULL) { + nonoption_flags_max_len = -1; + } else { + memcpy(getopt_nonoption_flags, orig_str, len); + memset(&getopt_nonoption_flags[len], '\0', + nonoption_flags_max_len - len); + } + } + } + + nonoption_flags_len = nonoption_flags_max_len; + } else { + nonoption_flags_len = 0; + } + +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal(argc, argv, optstring, longopts, longind, long_only) +int argc; +char *const *argv; +const char *optstring; +const struct option *longopts; +int *longind; +int long_only; +{ + optarg = NULL; + + if(optind == 0 || !getopt_initialized) { + if(optind == 0) { + optind = 1; /* Don't scan ARGV[0], the program name. */ + } + + optstring = _getopt_initialize(argc, argv, optstring); + getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && getopt_nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if(nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if(last_nonopt > optind) { + last_nonopt = optind; + } + + if(first_nonopt > optind) { + first_nonopt = optind; + } + + if(ordering == PERMUTE) { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if(first_nonopt != last_nonopt && last_nonopt != optind) { + exchange((char **) argv); + } else if(last_nonopt != optind) { + first_nonopt = optind; + } + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while(optind < argc && NONOPTION_P) { + optind++; + } + + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if(optind != argc && !strcmp(argv[optind], "--")) { + optind++; + + if(first_nonopt != last_nonopt && last_nonopt != optind) { + exchange((char **) argv); + } else if(first_nonopt == last_nonopt) { + first_nonopt = optind; + } + + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if(optind == argc) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if(first_nonopt != last_nonopt) { + optind = first_nonopt; + } + + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if(NONOPTION_P) { + if(ordering == REQUIRE_ORDER) { + return -1; + } + + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if(longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for(nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for(p = longopts, option_index = 0; p->name; p++, option_index++) + if(!strncmp(p->name, nextchar, nameend - nextchar)) { + if((unsigned int)(nameend - nextchar) + == (unsigned int) strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if(pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + { + ambig = 1; + } + } + + if(ambig && !exact) { + if(opterr) + fprintf(stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if(pfound != NULL) { + option_index = indfound; + optind++; + + if(*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if(pfound->has_arg) { + optarg = nameend + 1; + } else { + if(opterr) { + if(argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf(stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } else if(pfound->has_arg == 1) { + if(optind < argc) { + optarg = argv[optind++]; + } else { + if(opterr) + fprintf(stderr, + "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + + nextchar += strlen(nextchar); + + if(longind != NULL) { + *longind = option_index; + } + + if(pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if(!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) { + if(opterr) { + if(argv[optind][1] == '-') + /* --option */ + fprintf(stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf(stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if(*nextchar == '\0') { + ++optind; + } + + if(temp == NULL || c == ':') { + if(opterr) { + if(posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, "%s: illegal option -- %c\n", + argv[0], c); + else + fprintf(stderr, "%s: invalid option -- %c\n", + argv[0], c); + } + + optopt = c; + return '?'; + } + + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if(temp[0] == 'W' && temp[1] == ';') { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if(*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if(optind == argc) { + if(opterr) { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + + optopt = c; + + if(optstring[0] == ':') { + c = ':'; + } else { + c = '?'; + } + + return c; + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + { + optarg = argv[optind++]; + } + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for(nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for(p = longopts, option_index = 0; p->name; p++, option_index++) + if(!strncmp(p->name, nextchar, nameend - nextchar)) { + if((unsigned int)(nameend - nextchar) == strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if(pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + { + ambig = 1; + } + } + + if(ambig && !exact) { + if(opterr) + fprintf(stderr, "%s: option `-W %s' is ambiguous\n", + argv[0], argv[optind]); + + nextchar += strlen(nextchar); + optind++; + return '?'; + } + + if(pfound != NULL) { + option_index = indfound; + + if(*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if(pfound->has_arg) { + optarg = nameend + 1; + } else { + if(opterr) + fprintf(stderr, + "%s: option `-W %s' doesn't allow an argument\n", + argv[0], pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } else if(pfound->has_arg == 1) { + if(optind < argc) { + optarg = argv[optind++]; + } else { + if(opterr) + fprintf(stderr, + "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + + nextchar += strlen(nextchar); + + if(longind != NULL) { + *longind = option_index; + } + + if(pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + + return pfound->val; + } + + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + + if(temp[1] == ':') { + if(temp[2] == ':') { + /* This is an option that accepts an argument optionally. */ + if(*nextchar != '\0') { + optarg = nextchar; + optind++; + } else { + optarg = NULL; + } + + nextchar = NULL; + } else { + /* This is an option that requires an argument. */ + if(*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if(optind == argc) { + if(opterr) { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, + "%s: option requires an argument -- %c\n", + argv[0], c); + } + + optopt = c; + + if(optstring[0] == ':') { + c = ':'; + } else { + c = '?'; + } + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + { + optarg = argv[optind++]; + } + + nextchar = NULL; + } + } + + return c; + } +} + +int +getopt(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; +{ + return _getopt_internal(argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main(argc, argv) +int argc; +char **argv; +{ + int c; + int digit_optind = 0; + + while(1) { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + + if(c == -1) { + break; + } + + switch(c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(digit_optind != 0 && digit_optind != this_option_optind) { + printf("digits occur in two different argv-elements.\n"); + } + + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + if(optind < argc) { + printf("non-option ARGV-elements: "); + + while(optind < argc) { + printf("%s ", argv[optind++]); + } + + printf("\n"); + } + + exit(0); +} + +#endif /* TEST */ diff --git a/src/getopt.h b/src/getopt.h new file mode 100644 index 0000000..ab1d40b --- /dev/null +++ b/src/getopt.h @@ -0,0 +1,132 @@ +#ifndef TINC_GETOPT_H +#define TINC_GETOPT_H + +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef cplusplus +extern "C" { +#endif + + /* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + + extern char *optarg; + + /* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + extern int optind; + + /* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + + extern int opterr; + + /* Set to an option character which was unrecognized. */ + + extern int optopt; + + /* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + + struct option { +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; + + /* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ + /* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ + extern int getopt(int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ + extern int getopt(); +#endif /* __GNU_LIBRARY__ */ + extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + extern int getopt_long_only(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + + /* Internal only. Users should not call this directly. */ + extern int _getopt_internal(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ + extern int getopt(); + extern int getopt_long(); + extern int getopt_long_only(); + + extern int _getopt_internal(); +#endif /* __STDC__ */ + +#ifdef cplusplus +} +#endif + +#endif diff --git a/lib/getopt1.c b/src/getopt1.c similarity index 50% rename from lib/getopt1.c rename to src/getopt1.c index 6507ba1..3ccb150 100644 --- a/lib/getopt1.c +++ b/src/getopt1.c @@ -14,13 +14,13 @@ 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. */ +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ #ifdef HAVE_CONFIG_H -#include +#include "../config.h" #endif #include "getopt.h" @@ -60,19 +60,19 @@ USA. */ #include #endif -#ifndef NULL +#ifndef NULL #define NULL 0 #endif int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); + return _getopt_internal(argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -81,109 +81,115 @@ getopt_long (argc, argv, options, long_options, opt_index) instead. */ int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long_only(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); + return _getopt_internal(argc, argv, options, long_options, opt_index, 1); } -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST #include int -main (argc, argv) - int argc; - char **argv; +main(argc, argv) +int argc; +char **argv; { - int c; - int digit_optind = 0; + int c; + int digit_optind = 0; - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; + while(1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; + c = getopt_long(argc, argv, "abc:d:0123456789", + long_options, &option_index); - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; + if(c == -1) { + break; + } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; + switch(c) { + case 0: + printf("option %s", long_options[option_index].name); - case 'a': - printf ("option a\n"); - break; + if(optarg) { + printf(" with arg %s", optarg); + } - case 'b': - printf ("option b\n"); - break; + printf("\n"); + break; - case 'c': - printf ("option c with value `%s'\n", optarg); - break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(digit_optind != 0 && digit_optind != this_option_optind) { + printf("digits occur in two different argv-elements.\n"); + } - case 'd': - printf ("option d with value `%s'\n", optarg); - break; + digit_optind = this_option_optind; + printf("option %c\n", c); + break; - case '?': - break; + case 'a': + printf("option a\n"); + break; - default: - printf ("?? getopt returned character code 0%o ??\n", c); + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case 'd': + printf("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } + if(optind < argc) { + printf("non-option ARGV-elements: "); - exit (0); + while(optind < argc) { + printf("%s ", argv[optind++]); + } + + printf("\n"); + } + + exit(0); } #endif /* TEST */ diff --git a/src/graph.c b/src/graph.c index 53152a5..c63fdf9 100644 --- a/src/graph.c +++ b/src/graph.c @@ -1,7 +1,7 @@ /* graph.c -- graph algorithms - Copyright (C) 2001-2002 Guus Sliepen , - 2001-2002 Ivo Timmermans + Copyright (C) 2001-2014 Guus Sliepen , + 2001-2005 Ivo Timmermans 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 @@ -13,11 +13,9 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: graph.c,v 1.1.2.11 2002/03/24 16:28:27 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* We need to generate two trees from the graph: @@ -44,247 +42,349 @@ destination address and port of a node if possible. */ -#include "config.h" - -#include -#include -#include "config.h" -#include -#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) - #include -#endif -#include - -#include -#include +#include "system.h" +#include "avl_tree.h" +#include "conf.h" +#include "connection.h" +#include "device.h" +#include "edge.h" +#include "graph.h" +#include "logger.h" #include "netutl.h" #include "node.h" -#include "edge.h" -#include "connection.h" #include "process.h" +#include "protocol.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" -#include "system.h" +static bool graph_changed = true; /* Implementation of Kruskal's algorithm. Running time: O(EN) Please note that sorting on weight is already done by add_edge(). */ -void mst_kruskal(void) -{ - avl_node_t *node, *next; - edge_t *e; - node_t *n; - connection_t *c; - int nodes = 0; - int safe_edges = 0; - int skipped; +static void mst_kruskal(void) { + avl_node_t *node, *next; + edge_t *e; + node_t *n; + connection_t *c; + int nodes = 0; + int safe_edges = 0; + bool skipped; - /* Clear MST status on connections */ + /* Clear MST status on connections */ - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - c->status.mst = 0; - } + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + c->status.mst = false; + } - /* Do we have something to do at all? */ - - if(!edge_weight_tree->head) - return; + /* Do we have something to do at all? */ - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, "Running Kruskal's algorithm:"); + if(!edge_weight_tree->head) { + return; + } - /* Clear visited status on nodes */ + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Running Kruskal's algorithm:"); - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - n->status.visited = 0; - nodes++; - } + /* Clear visited status on nodes */ - /* Starting point */ - - ((edge_t *)edge_weight_tree->head->data)->from.node->status.visited = 1; + for(node = node_tree->head; node; node = node->next) { + n = node->data; + n->status.visited = false; + nodes++; + } - /* Add safe edges */ + /* Starting point */ - for(skipped = 0, node = edge_weight_tree->head; node; node = next) - { - next = node->next; - e = (edge_t *)node->data; + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; - if(e->from.node->status.visited == e->to.node->status.visited) - { - skipped = 1; - continue; - } + if(e->from->status.reachable) { + e->from->status.visited = true; + break; + } + } - e->from.node->status.visited = 1; - e->to.node->status.visited = 1; - if(e->connection) - e->connection->status.mst = 1; + /* Add safe edges */ - safe_edges++; + for(skipped = false, node = edge_weight_tree->head; node; node = next) { + next = node->next; + e = node->data; - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from.node->name, e->to.node->name, e->weight); + if(!e->reverse || e->from->status.visited == e->to->status.visited) { + skipped = true; + continue; + } - if(skipped) - { - next = edge_weight_tree->head; - continue; - } - } + e->from->status.visited = true; + e->to->status.visited = true; - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, safe_edges); + if(e->connection) { + e->connection->status.mst = true; + } + + if(e->reverse->connection) { + e->reverse->connection->status.mst = true; + } + + safe_edges++; + + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, + e->to->name, e->weight); + + if(skipped) { + skipped = false; + next = edge_weight_tree->head; + continue; + } + } + + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, + safe_edges); } /* Implementation of a simple breadth-first search algorithm. Running time: O(E) */ -void sssp_bfs(void) -{ - avl_node_t *node, *from, *next, *to; - edge_t *e; - node_t *n; - halfconnection_t to_hc, from_hc; - avl_tree_t *todo_tree; - int indirect; - char *name; +static void sssp_bfs(void) { + avl_node_t *node, *next, *to; + edge_t *e; + node_t *n; + list_t *todo_list; + list_node_t *from, *todonext; + bool indirect; + char *name; + char *address, *port; + char *envp[8] = {NULL}; + int i; - todo_tree = avl_alloc_tree(NULL, NULL); + todo_list = list_alloc(NULL); - /* Clear visited status on nodes */ + /* Clear visited status on nodes */ - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - n->status.visited = 0; - n->status.indirect = 1; - } - - /* Begin with myself */ - - myself->status.visited = 1; - myself->status.indirect = 0; - myself->nexthop = myself; - myself->via = myself; - node = avl_alloc_node(); - node->data = myself; - avl_insert_top(todo_tree, node); - - /* Loop while todo_tree is filled */ - - while(todo_tree->head) - { - for(from = todo_tree->head; from; from = next) /* "from" is the node from which we start */ - { - next = from->next; - n = (node_t *)from->data; - - for(to = n->edge_tree->head; to; to = to->next) /* "to" is the edge connected to "from" */ - { - e = (edge_t *)to->data; - - if(e->from.node == n) /* "from_hc" is the halfconnection with .node == from */ - to_hc = e->to, from_hc = e->from; - else - to_hc = e->from, from_hc = e->to; - - /* Situation: - - / - / - ------(n)from_hc-----to_hc - \ - \ - - n->address is set to the to_hc.udpaddress of the edge left of n. - We are currently examining the edge right of n: - - - If from_hc.udpaddress != n->address, then to_hc.node is probably - not reachable for the nodes left of n. We do as if the indirectdata - flag is set on edge e. - - If edge e provides for better reachability of to_hc.node, update - to_hc.node and (re)add it to the todo_tree to (re)examine the reachability - of nodes behind it. - */ - - indirect = n->status.indirect || e->options & OPTION_INDIRECT || ((n != myself) && sockaddrcmp(&n->address, &from_hc.udpaddress)); - - if(to_hc.node->status.visited && (!to_hc.node->status.indirect || indirect)) - continue; - - to_hc.node->status.visited = 1; - to_hc.node->status.indirect = indirect; - to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop; - to_hc.node->via = indirect ? n->via : to_hc.node; - to_hc.node->options = e->options; - if(sockaddrcmp(&to_hc.node->address, &to_hc.udpaddress)) - { - node = avl_unlink(node_udp_tree, to_hc.node); - to_hc.node->address = to_hc.udpaddress; - if(to_hc.node->hostname) - free(to_hc.node->hostname); - to_hc.node->hostname = sockaddr2hostname(&to_hc.udpaddress); - avl_insert_node(node_udp_tree, node); - } - node = avl_alloc_node(); - node->data = to_hc.node; - avl_insert_before(todo_tree, from, node); - } - - avl_delete_node(todo_tree, from); - } - } - - avl_free_tree(todo_tree); - - /* Check reachability status. */ - - for(node = node_tree->head; node; node = next) - { - next = node->next; - n = (node_t *)node->data; - - if(n->status.visited) - { - if(!n->status.reachable) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Node %s (%s) became reachable"), n->name, n->hostname); - n->status.reachable = 1; - asprintf(&name, "hosts/%s-up", n->name); - execute_script(name); - free(name); + for(node = node_tree->head; node; node = node->next) { + n = node->data; + n->status.visited = false; + n->status.indirect = true; } - } - else - { - if(n->status.reachable) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), n->name, n->hostname); - n->status.reachable = 0; - n->status.validkey = 0; - n->status.waitingforkey = 0; - n->sent_seqno = 0; - asprintf(&name, "hosts/%s-down", n->name); - execute_script(name); - free(name); + + /* Begin with myself */ + + myself->status.visited = true; + myself->status.indirect = false; + myself->nexthop = myself; + myself->prevedge = NULL; + myself->via = myself; + list_insert_head(todo_list, myself); + + /* Loop while todo_list is filled */ + + for(from = todo_list->head; from; from = todonext) { /* "from" is the node from which we start */ + n = from->data; + + for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */ + e = to->data; + + if(!e->reverse) { + continue; + } + + /* Situation: + + / + / + ----->(n)---e-->(e->to) + \ + \ + + Where e is an edge, (n) and (e->to) are nodes. + n->address is set to the e->address of the edge left of n to n. + We are currently examining the edge e right of n from n: + + - If edge e provides for better reachability of e->to, update + e->to and (re)add it to the todo_list to (re)examine the reachability + of nodes behind it. + */ + + indirect = n->status.indirect || e->options & OPTION_INDIRECT; + + if(e->to->status.visited + && (!e->to->status.indirect || indirect)) { + continue; + } + + // Only update nexthop the first time we visit this node. + + if(!e->to->status.visited) { + e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; + } + + e->to->status.visited = true; + e->to->status.indirect = indirect; + e->to->prevedge = e; + e->to->via = indirect ? n->via : e->to; + e->to->options = e->options; + + if(e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN) { + update_node_udp(e->to, &e->address); + } + + list_insert_tail(todo_list, e->to); + } + + todonext = from->next; + list_delete_node(todo_list, from); + } + + list_free(todo_list); + + /* Check reachability status. */ + + for(node = node_tree->head; node; node = next) { + next = node->next; + n = node->data; + + if(n->status.visited != n->status.reachable) { + n->status.reachable = !n->status.reachable; + + if(n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became reachable", + n->name, n->hostname); + } else { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became unreachable", + n->name, n->hostname); + } + + /* TODO: only clear status.validkey if node is unreachable? */ + + n->status.validkey = false; + n->last_req_key = 0; + + n->maxmtu = MTU; + n->minmtu = 0; + n->mtuprobes = 0; + + if(n->mtuevent) { + event_del(n->mtuevent); + n->mtuevent = NULL; + } + + xasprintf(&envp[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); + xasprintf(&envp[3], "NODE=%s", n->name); + sockaddr2str(&n->address, &address, &port); + xasprintf(&envp[4], "REMOTEADDRESS=%s", address); + xasprintf(&envp[5], "REMOTEPORT=%s", port); + xasprintf(&envp[6], "NAME=%s", myself->name); + + execute_script(n->status.reachable ? "host-up" : "host-down", envp); + + xasprintf(&name, + n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", + n->name); + execute_script(name, envp); + + free(name); + free(address); + free(port); + + for(i = 0; i < 7; i++) { + free(envp[i]); + } + + subnet_update(n, NULL, n->status.reachable); + + if(!n->status.reachable) { + update_node_udp(n, NULL); + memset(&n->status, 0, sizeof(n->status)); + n->options = 0; + } else if(n->connection) { + send_ans_key(n); + } + } } - } - } } -void graph(void) -{ - mst_kruskal(); - sssp_bfs(); +void graph(void) { + subnet_cache_flush(); + sssp_bfs(); + mst_kruskal(); + graph_changed = true; +} + + + +/* Dump nodes and edges to a graphviz file. + + The file can be converted to an image with + dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true +*/ + +void dump_graph(void) { + avl_node_t *node; + node_t *n; + edge_t *e; + char *filename = NULL, *tmpname = NULL; + FILE *file, *pipe = NULL; + + if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename)) { + return; + } + + graph_changed = false; + + ifdebug(PROTOCOL) logger(LOG_NOTICE, "Dumping graph"); + + if(filename[0] == '|') { + file = pipe = popen(filename + 1, "w"); + } else { + xasprintf(&tmpname, "%s.new", filename); + file = fopen(tmpname, "w"); + } + + if(!file) { + logger(LOG_ERR, "Unable to open graph dump file %s: %s", filename, strerror(errno)); + free(filename); + free(tmpname); + return; + } + + fprintf(file, "digraph {\n"); + + /* dump all nodes first */ + for(node = node_tree->head; node; node = node->next) { + n = node->data; + fprintf(file, " \"%s\" [label = \"%s\"];\n", n->name, n->name); + } + + /* now dump all edges */ + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; + fprintf(file, " \"%s\" -> \"%s\";\n", e->from->name, e->to->name); + } + + fprintf(file, "}\n"); + + if(pipe) { + pclose(pipe); + } else { + fclose(file); +#ifdef HAVE_MINGW + unlink(filename); +#endif + + if(rename(tmpname, filename)) { + logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno)); + } + + free(tmpname); + } + + free(filename); } diff --git a/src/graph.h b/src/graph.h index 3c8c0d5..fafffcb 100644 --- a/src/graph.h +++ b/src/graph.h @@ -1,7 +1,10 @@ +#ifndef TINC_GRAPH_H +#define TINC_GRAPH_H + /* graph.h -- header for graph.c - Copyright (C) 2001-2002 Guus Sliepen , - 2001-2002 Ivo Timmermans + Copyright (C) 2001-2012 Guus Sliepen , + 2001-2005 Ivo Timmermans 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 @@ -13,13 +16,12 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: graph.h,v 1.1.2.3 2002/02/10 21:57:54 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ extern void graph(void); -extern void mst_kruskal(void); -extern void sssp_bfs(void); +extern void dump_graph(void); + +#endif diff --git a/src/have.h b/src/have.h new file mode 100644 index 0000000..11fa56a --- /dev/null +++ b/src/have.h @@ -0,0 +1,214 @@ +#ifndef TINC_HAVE_H +#define TINC_HAVE_H + +/* + have.h -- include headers which are known to exist + Copyright (C) 1998-2005 Ivo Timmermans + 2003-2015 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_MINGW +#ifdef WITH_WINDOWS2000 +#define WINVER Windows2000 +#else +#define WINVER WindowsXP +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_MINGW +#include +#include +#include +#include +#endif + +#ifdef HAVE_STDBOOL_H +#include +#endif + +#ifdef HAVE_TERMIOS_H +#include +#endif + +#ifdef HAVE_ALLOCA_H +#include +#endif + +/* Include system specific headers */ + +#ifdef HAVE_SYSLOG_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_FILE_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_DIRENT_H +#include +#endif + +/* SunOS really wants sys/socket.h BEFORE net/if.h, + and FreeBSD wants these lines below the rest. */ + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NET_IF_TYPES_H +#include +#endif + +#ifdef HAVE_NET_IF_TUN_H +#include +#endif + +#ifdef HAVE_NET_TUN_IF_TUN_H +#include +#endif + +#ifdef HAVE_NET_IF_TAP_H +#include +#endif + +#ifdef HAVE_NET_TAP_IF_TAP_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NETINET_TCP_H +#include +#endif + +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#ifdef HAVE_NETINET_IP6_H +#include +#endif + +#ifdef HAVE_NET_ETHERNET_H +#include +#endif + +#ifdef HAVE_NET_IF_ARP_H +#include +#endif + +#ifdef HAVE_NETINET_IP_ICMP_H +#include +#endif + +#ifdef HAVE_NETINET_ICMP6_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_ARPA_NAMESER_H +#include +#ifdef STATUS +#undef STATUS +#endif +#endif + +#ifdef HAVE_RESOLV_H +#include +#endif + +#ifdef HAVE_LINUX_IF_TUN_H +#include +#endif + +#endif diff --git a/src/ipv4.h b/src/ipv4.h new file mode 100644 index 0000000..7979f7d --- /dev/null +++ b/src/ipv4.h @@ -0,0 +1,149 @@ +#ifndef TINC_IPV4_H +#define TINC_IPV4_H + +/* + ipv4.h -- missing IPv4 related definitions + Copyright (C) 2005 Ivo Timmermans + 2006-2012 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef AF_INET +#define AF_INET 2 +#endif + +#ifndef IPPROTO_ICMP +#define IPPROTO_ICMP 1 +#endif + +#ifndef ICMP_DEST_UNREACH +#define ICMP_DEST_UNREACH 3 +#endif + +#ifndef ICMP_FRAG_NEEDED +#define ICMP_FRAG_NEEDED 4 +#endif + +#ifndef ICMP_NET_UNKNOWN +#define ICMP_NET_UNKNOWN 6 +#endif + +#ifndef ICMP_TIME_EXCEEDED +#define ICMP_TIME_EXCEEDED 11 +#endif + +#ifndef ICMP_EXC_TTL +#define ICMP_EXC_TTL 0 +#endif + +#ifndef ICMP_NET_UNREACH +#define ICMP_NET_UNREACH 0 +#endif + +#ifndef ICMP_NET_ANO +#define ICMP_NET_ANO 9 +#endif + +#ifndef IP_MSS +#define IP_MSS 576 +#endif + +#ifndef HAVE_STRUCT_IP +struct ip { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl: 4; + unsigned int ip_v: 4; +#else + unsigned int ip_v: 4; + unsigned int ip_hl: 4; +#endif + uint8_t ip_tos; + uint16_t ip_len; + uint16_t ip_id; + uint16_t ip_off; +#define IP_RF 0x8000 +#define IP_DF 0x4000 +#define IP_MF 0x2000 + uint8_t ip_ttl; + uint8_t ip_p; + uint16_t ip_sum; + struct in_addr ip_src, ip_dst; +} __attribute__((__packed__)); +#endif + +#ifndef IP_OFFMASK +#define IP_OFFMASK 0x1fff +#endif + +#ifndef HAVE_STRUCT_ICMP +struct icmp { + uint8_t icmp_type; + uint8_t icmp_code; + uint16_t icmp_cksum; + union { + uint8_t ih_pptr; + struct in_addr ih_gwaddr; + struct ih_idseq { + uint16_t icd_id; + uint16_t icd_seq; + } ih_idseq; + uint32_t ih_void; + + + struct ih_pmtu { + uint16_t ipm_void; + uint16_t ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + uint8_t irt_num_addrs; + uint8_t irt_wpa; + uint16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct { + uint32_t its_otime; + uint32_t its_rtime; + uint32_t its_ttime; + } id_ts; + struct { + struct ip idi_ip; + } id_ip; + uint32_t id_mask; + uint8_t id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_radv +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +} __attribute__((__packed__)); +#endif + +#endif diff --git a/src/ipv6.h b/src/ipv6.h new file mode 100644 index 0000000..1642278 --- /dev/null +++ b/src/ipv6.h @@ -0,0 +1,130 @@ +#ifndef TINC_IPV6_H +#define TINC_IPV6_H + +/* + ipv6.h -- missing IPv6 related definitions + Copyright (C) 2005 Ivo Timmermans + 2006-2012 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef AF_INET6 +#define AF_INET6 10 +#endif + +#ifndef IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + union { + uint8_t u6_addr8[16]; + uint16_t u6_addr16[8]; + uint32_t u6_addr32[4]; + } in6_u; +} __attribute__((__packed__)); +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + uint16_t sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; +} __attribute__((__packed__)); +#endif + +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((const uint32_t *) (a))[0] == 0) \ + && (((const uint32_t *) (a))[1] == 0) \ + && (((const uint32_t *) (a))[2] == htonl (0xffff))) +#endif + +#ifndef HAVE_STRUCT_IP6_HDR +struct ip6_hdr { + union { + struct ip6_hdrctl { + uint32_t ip6_un1_flow; + uint16_t ip6_un1_plen; + uint8_t ip6_un1_nxt; + uint8_t ip6_un1_hlim; + } ip6_un1; + uint8_t ip6_un2_vfc; + } ip6_ctlun; + struct in6_addr ip6_src; + struct in6_addr ip6_dst; +} __attribute__((__packed__)); +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim +#endif + +#ifndef HAVE_STRUCT_ICMP6_HDR +struct icmp6_hdr { + uint8_t icmp6_type; + uint8_t icmp6_code; + uint16_t icmp6_cksum; + union { + uint32_t icmp6_un_data32[1]; + uint16_t icmp6_un_data16[2]; + uint8_t icmp6_un_data8[4]; + } icmp6_dataun; +} __attribute__((__packed__)); +#define ICMP6_DST_UNREACH_NOROUTE 0 +#define ICMP6_DST_UNREACH 1 +#define ICMP6_PACKET_TOO_BIG 2 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_DST_UNREACH_ADMIN 1 +#define ICMP6_DST_UNREACH_ADDR 3 +#define ICMP6_TIME_EXCEED_TRANSIT 0 +#define ND_NEIGHBOR_SOLICIT 135 +#define ND_NEIGHBOR_ADVERT 136 +#define icmp6_data32 icmp6_dataun.icmp6_un_data32 +#define icmp6_data16 icmp6_dataun.icmp6_un_data16 +#define icmp6_data8 icmp6_dataun.icmp6_un_data8 +#define icmp6_mtu icmp6_data32[0] +#endif + +#ifndef HAVE_STRUCT_ND_NEIGHBOR_SOLICIT +struct nd_neighbor_solicit { + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; +} __attribute__((__packed__)); +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define nd_ns_type nd_ns_hdr.icmp6_type +#define nd_ns_code nd_ns_hdr.icmp6_code +#define nd_ns_cksum nd_ns_hdr.icmp6_cksum +#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] +#endif + +#ifndef HAVE_STRUCT_ND_OPT_HDR +struct nd_opt_hdr { + uint8_t nd_opt_type; + uint8_t nd_opt_len; +} __attribute__((__packed__)); +#endif + +#endif diff --git a/src/linux/device.c b/src/linux/device.c index e896f54..38debe8 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Linux ethertap and tun/tap device - Copyright (C) 2001-2002 Ivo Timmermans , - 2001-2002 Guus Sliepen + Copyright (C) 2001-2005 Ivo Timmermans, + 2001-2014 Guus Sliepen 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 @@ -13,212 +13,259 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.c,v 1.1.2.8 2002/03/24 16:36:56 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "../system.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_TUNTAP - #ifdef LINUX_IF_TUN_H - #include LINUX_IF_TUN_H - #else - #include - #endif - #define DEFAULT_DEVICE "/dev/misc/net/tun" +#ifdef HAVE_LINUX_IF_TUN_H +#include +#define DEFAULT_DEVICE "/dev/net/tun" #else - #define DEFAULT_DEVICE "/dev/tap0" +#define DEFAULT_DEVICE "/dev/tap0" #endif -#include -#include "conf.h" -#include "net.h" -#include "subnet.h" +#include "../conf.h" +#include "../device.h" +#include "../logger.h" +#include "../net.h" +#include "../route.h" +#include "../utils.h" +#include "../xalloc.h" -#include "system.h" - -#define DEVICE_TYPE_ETHERTAP 0 -#define DEVICE_TYPE_TUNTAP 1 +typedef enum device_type_t { + DEVICE_TYPE_ETHERTAP, + DEVICE_TYPE_TUN, + DEVICE_TYPE_TAP, +} device_type_t; int device_fd = -1; -int device_type; -char *device; -char *interface; -char ifrname[IFNAMSIZ]; -char *device_info; +static device_type_t device_type; +char *device = NULL; +char *iface = NULL; +static char *type = NULL; +static char ifrname[IFNAMSIZ]; +static const char *device_info; -int device_total_in = 0; -int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; -extern subnet_t mymac; +static bool setup_device(void) { + struct ifreq ifr; + bool t1q = false; -/* - open the local ethertap device -*/ -int setup_device(void) -{ - struct ifreq ifr; + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + device = xstrdup(DEFAULT_DEVICE); + } -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) +#ifdef HAVE_LINUX_IF_TUN_H + if(netname != NULL) { + iface = xstrdup(netname); + } - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) -#ifdef HAVE_TUNTAP - interface = netname; #else - interface = rindex(device, '/')?rindex(device, '/')+1:device; + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); #endif -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ + device_fd = open(device, O_RDWR | O_NONBLOCK); - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; + if(device_fd < 0) { + logger(LOG_ERR, "Could not open %s: %s", device, strerror(errno)); + return false; + } -#ifdef HAVE_TUNTAP - /* Ok now check if this is an old ethertap or a new tun/tap thingie */ - - memset(&ifr, 0, sizeof(ifr)); -cp - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if (interface) - strncpy(ifr.ifr_name, interface, IFNAMSIZ); -cp - if (!ioctl(device_fd, TUNSETIFF, (void *) &ifr)) - { - device_info = _("Linux tun/tap device"); - device_type = DEVICE_TYPE_TUNTAP; - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else - if (!ioctl(device_fd, (('T'<< 8) | 202), (void *) &ifr)) - { - syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device); - device_type = DEVICE_TYPE_TUNTAP; - device_info = _("Linux tun/tap device"); - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif - { - device_info = _("Linux ethertap device"); - device_type = DEVICE_TYPE_ETHERTAP; - interface = rindex(device, '/')?rindex(device, '/')+1:device; - } - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; +#ifdef HAVE_LINUX_IF_TUN_H + /* Ok now check if this is an old ethertap or a new tun/tap thingie */ + + memset(&ifr, 0, sizeof(ifr)); + + get_config_string(lookup_config(config_tree, "DeviceType"), &type); + + if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) { + logger(LOG_ERR, "Unknown device type %s!", type); + return false; + } + + if((type && !strcasecmp(type, "tun")) || (!type && routing_mode == RMODE_ROUTER)) { + ifr.ifr_flags = IFF_TUN; + device_type = DEVICE_TYPE_TUN; + device_info = "Linux tun/tap device (tun mode)"; + } else { + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + device_type = DEVICE_TYPE_TAP; + device_info = "Linux tun/tap device (tap mode)"; + } + +#ifdef IFF_ONE_QUEUE + + /* Set IFF_ONE_QUEUE flag... */ + if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q) { + ifr.ifr_flags |= IFF_ONE_QUEUE; + } + +#endif + + if(iface) { + strncpy(ifr.ifr_name, iface, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + } + + if(!ioctl(device_fd, TUNSETIFF, &ifr)) { + strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + ifrname[IFNAMSIZ - 1] = 0; + free(iface); + iface = xstrdup(ifrname); + } else if(errno == EPERM || errno == EBUSY) { + logger(LOG_ERR, "Error while trying to configure %s: %s", device, strerror(errno)); + return false; + } else if(!ioctl(device_fd, (('T' << 8) | 202), &ifr)) { + logger(LOG_WARNING, "Old ioctl() request was needed for %s", device); + strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + ifrname[IFNAMSIZ - 1] = 0; + free(iface); + iface = xstrdup(ifrname); + } else +#endif + { + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + device_info = "Linux ethertap device"; + device_type = DEVICE_TYPE_ETHERTAP; + free(iface); + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); + } + + if(overwrite_mac && !ioctl(device_fd, SIOCGIFHWADDR, &ifr)) { + memcpy(mymac.x, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + } + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; } -void close_device(void) -{ -cp - close(device_fd); +static void close_device(void) { + close(device_fd); + + free(type); + free(device); + free(iface); } -/* - read, encrypt and send data that is - available through the ethertap device -*/ -int read_packet(vpn_packet_t *packet) -{ - int lenin; -cp - if(device_type == DEVICE_TYPE_TUNTAP) - { - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } +static bool read_packet(vpn_packet_t *packet) { + int lenin; - packet->len = lenin; - } - else /* ethertap */ - { - if((lenin = read(device_fd, packet->data - 2, MTU + 2)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + switch(device_type) { + case DEVICE_TYPE_TUN: + lenin = read(device_fd, packet->data + 10, MTU - 10); - packet->len = lenin - 2; - } + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", + device_info, device, strerror(errno)); + return false; + } - device_total_in += packet->len; + memset(packet->data, 0, 12); + packet->len = lenin + 10; + break; - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } + case DEVICE_TYPE_TAP: + lenin = read(device_fd, packet->data, MTU); - return 0; -cp + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", + device_info, device, strerror(errno)); + return false; + } + + packet->len = lenin; + break; + + case DEVICE_TYPE_ETHERTAP: + lenin = read(device_fd, packet->data - 2, MTU + 2); + + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", + device_info, device, strerror(errno)); + return false; + } + + packet->len = lenin - 2; + break; + } + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; } -int write_packet(vpn_packet_t *packet) -{ -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); - if(device_type == DEVICE_TYPE_TUNTAP) - { - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } - else/* ethertap */ - { - *(short int *)(packet->data - 2) = packet->len; - if(write(device_fd, packet->data - 2, packet->len + 2) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } + switch(device_type) { + case DEVICE_TYPE_TUN: + packet->data[10] = packet->data[11] = 0; - device_total_out += packet->len; -cp - return 0; + if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_TAP: + if(write(device_fd, packet->data, packet->len) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_ETHERTAP: + memcpy(packet->data - 2, &packet->len, 2); + + if(write(device_fd, packet->data - 2, packet->len + 2) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; + } + + device_total_out += packet->len; + + return true; } -void dump_device_stats(void) -{ -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } + +const devops_t os_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..a807c6d --- /dev/null +++ b/src/list.c @@ -0,0 +1,178 @@ +/* + list.c -- functions to deal with double linked lists + Copyright (C) 2000-2005 Ivo Timmermans + 2000-2006 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "list.h" +#include "xalloc.h" + +/* (De)constructors */ + +list_t *list_alloc(list_action_t delete) { + list_t *list; + + list = xmalloc_and_zero(sizeof(list_t)); + list->delete = delete; + + return list; +} + +void list_free(list_t *list) { + free(list); +} + +list_node_t *list_alloc_node(void) { + return xmalloc_and_zero(sizeof(list_node_t)); +} + +void list_free_node(list_t *list, list_node_t *node) { + if(node->data && list->delete) { + list->delete(node->data); + } + + free(node); +} + +/* Insertion and deletion */ + +list_node_t *list_insert_head(list_t *list, void *data) { + list_node_t *node; + + node = list_alloc_node(); + + node->data = data; + node->prev = NULL; + node->next = list->head; + list->head = node; + + if(node->next) { + node->next->prev = node; + } else { + list->tail = node; + } + + list->count++; + + return node; +} + +list_node_t *list_insert_tail(list_t *list, void *data) { + list_node_t *node; + + node = list_alloc_node(); + + node->data = data; + node->next = NULL; + node->prev = list->tail; + list->tail = node; + + if(node->prev) { + node->prev->next = node; + } else { + list->head = node; + } + + list->count++; + + return node; +} + +void list_unlink_node(list_t *list, list_node_t *node) { + if(node->prev) { + node->prev->next = node->next; + } else { + list->head = node->next; + } + + if(node->next) { + node->next->prev = node->prev; + } else { + list->tail = node->prev; + } + + list->count--; +} + +void list_delete_node(list_t *list, list_node_t *node) { + list_unlink_node(list, node); + list_free_node(list, node); +} + +void list_delete_head(list_t *list) { + list_delete_node(list, list->head); +} + +void list_delete_tail(list_t *list) { + list_delete_node(list, list->tail); +} + +/* Head/tail lookup */ + +void *list_get_head(list_t *list) { + if(list->head) { + return list->head->data; + } else { + return NULL; + } +} + +void *list_get_tail(list_t *list) { + if(list->tail) { + return list->tail->data; + } else { + return NULL; + } +} + +/* Fast list deletion */ + +void list_delete_list(list_t *list) { + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; + list_free_node(list, node); + } + + list_free(list); +} + +/* Traversing */ + +void list_foreach_node(list_t *list, list_action_node_t action) { + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; + action(node); + } +} + +void list_foreach(list_t *list, list_action_t action) { + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; + + if(node->data) { + action(node->data); + } + } +} diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..b2a9b3d --- /dev/null +++ b/src/list.h @@ -0,0 +1,78 @@ +#ifndef TINC_LIST_H +#define TINC_LIST_H + +/* + list.h -- header file for list.c + Copyright (C) 2000-2005 Ivo Timmermans + 2000-2006 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +typedef struct list_node_t { + struct list_node_t *prev; + struct list_node_t *next; + + /* Payload */ + + void *data; +} list_node_t; + +typedef void (*list_action_t)(const void *); +typedef void (*list_action_node_t)(const list_node_t *); + +typedef struct list_t { + list_node_t *head; + list_node_t *tail; + int count; + + /* Callbacks */ + + list_action_t delete; +} list_t; + +/* (De)constructors */ + +extern list_t *list_alloc(list_action_t) __attribute__((__malloc__)); +extern void list_free(list_t *list); +extern list_node_t *list_alloc_node(void); +extern void list_free_node(list_t *list, list_node_t *node); + +/* Insertion and deletion */ + +extern list_node_t *list_insert_head(list_t *list, void *data); +extern list_node_t *list_insert_tail(list_t *list, void *data); + +extern void list_unlink_node(list_t *list, list_node_t *node); +extern void list_delete_node(list_t *list, list_node_t *node); + +extern void list_delete_head(list_t *list); +extern void list_delete_tail(list_t *list); + +/* Head/tail lookup */ + +extern void *list_get_head(list_t *list); +extern void *list_get_tail(list_t *list); + +/* Fast list deletion */ + +extern void list_delete_list(list_t *list); + +/* Traversing */ + +extern void list_foreach(list_t *list, list_action_t action); +extern void list_foreach_node(list_t *list, list_action_node_t action); + +#endif diff --git a/src/logger.c b/src/logger.c new file mode 100644 index 0000000..8d4aea1 --- /dev/null +++ b/src/logger.c @@ -0,0 +1,171 @@ +/* + logger.c -- logging code + Copyright (C) 2004-2016 Guus Sliepen + 2004-2005 Ivo Timmermans + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "conf.h" +#include "logger.h" + +debug_t debug_level = DEBUG_NOTHING; +static logmode_t logmode = LOGMODE_STDERR; +static pid_t logpid; +extern char *logfilename; +static FILE *logfile = NULL; +#ifdef HAVE_MINGW +static HANDLE loghandle = NULL; +#endif +static const char *logident = NULL; + +void openlogger(const char *ident, logmode_t mode) { + logident = ident; + logmode = mode; + + switch(mode) { + case LOGMODE_STDERR: + logpid = getpid(); + break; + + case LOGMODE_FILE: + logpid = getpid(); + logfile = fopen(logfilename, "a"); + + if(!logfile) { + fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno)); + logmode = LOGMODE_NULL; + } + + break; + + case LOGMODE_SYSLOG: +#ifdef HAVE_MINGW + loghandle = RegisterEventSource(NULL, logident); + + if(!loghandle) { + fprintf(stderr, "Could not open log handle!"); + logmode = LOGMODE_NULL; + } + + break; +#else +#ifdef HAVE_SYSLOG_H + openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON); + break; +#endif +#endif + + case LOGMODE_NULL: + break; + } +} + +void reopenlogger() { + if(logmode != LOGMODE_FILE) { + return; + } + + fflush(logfile); + FILE *newfile = fopen(logfilename, "a"); + + if(!newfile) { + logger(LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno)); + return; + } + + fclose(logfile); + logfile = newfile; +} + +void logger(int priority, const char *format, ...) { + va_list ap; + char timestr[32] = ""; + time_t now; + + va_start(ap, format); + + switch(logmode) { + case LOGMODE_STDERR: + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + fflush(stderr); + break; + + case LOGMODE_FILE: + now = time(NULL); + strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now)); + fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid); + vfprintf(logfile, format, ap); + fprintf(logfile, "\n"); + fflush(logfile); + break; + + case LOGMODE_SYSLOG: +#ifdef HAVE_MINGW + { + char message[4096]; + const char *messages[] = {message}; + vsnprintf(message, sizeof(message), format, ap); + message[sizeof(message) - 1] = 0; + ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL); + } + +#else +#ifdef HAVE_SYSLOG_H +#ifdef HAVE_VSYSLOG + vsyslog(priority, format, ap); +#else + { + char message[4096]; + vsnprintf(message, sizeof(message), format, ap); + syslog(priority, "%s", message); + } +#endif + break; +#endif +#endif + + case LOGMODE_NULL: + break; + } + + va_end(ap); +} + +void closelogger(void) { + switch(logmode) { + case LOGMODE_FILE: + fclose(logfile); + break; + + case LOGMODE_SYSLOG: +#ifdef HAVE_MINGW + DeregisterEventSource(loghandle); + break; +#else +#ifdef HAVE_SYSLOG_H + closelog(); + break; +#endif +#endif + + case LOGMODE_NULL: + case LOGMODE_STDERR: + break; + } +} diff --git a/src/logger.h b/src/logger.h new file mode 100644 index 0000000..5a17ffb --- /dev/null +++ b/src/logger.h @@ -0,0 +1,75 @@ +#ifndef TINC_LOGGER_H +#define TINC_LOGGER_H + +/* + logger.h -- header file for logger.c + Copyright (C) 2003-2016 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +typedef enum debug_t { + DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */ + DEBUG_ALWAYS = 0, + DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */ + DEBUG_ERROR = 2, /* Show error messages received from other hosts */ + DEBUG_STATUS = 2, /* Show status messages received from other hosts */ + DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */ + DEBUG_META = 4, /* Show contents of every request that is sent/received */ + DEBUG_TRAFFIC = 5, /* Show network traffic information */ + DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */ + DEBUG_SCARY_THINGS = 10, /* You have been warned */ +} debug_t; + +typedef enum logmode_t { + LOGMODE_NULL, + LOGMODE_STDERR, + LOGMODE_FILE, + LOGMODE_SYSLOG +} logmode_t; + +#ifdef HAVE_MINGW +#define LOG_EMERG EVENTLOG_ERROR_TYPE +#define LOG_ALERT EVENTLOG_ERROR_TYPE +#define LOG_CRIT EVENTLOG_ERROR_TYPE +#define LOG_ERR EVENTLOG_ERROR_TYPE +#define LOG_WARNING EVENTLOG_WARNING_TYPE +#define LOG_NOTICE EVENTLOG_INFORMATION_TYPE +#define LOG_INFO EVENTLOG_INFORMATION_TYPE +#define LOG_DEBUG EVENTLOG_INFORMATION_TYPE +#else +#ifndef HAVE_SYSLOG_H +enum { + LOG_EMERG, + LOG_ALERT, + LOG_CRIT, + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG, +}; +#endif +#endif + +extern debug_t debug_level; +extern void openlogger(const char *ident, logmode_t mode); +extern void reopenlogger(void); +extern void logger(int priority, const char *format, ...) __attribute__((__format__(printf, 2, 3))); +extern void closelogger(void); + +#define ifdebug(l) if(debug_level >= DEBUG_##l) + +#endif diff --git a/src/meta.c b/src/meta.c index b51c64d..ee55ecd 100644 --- a/src/meta.c +++ b/src/meta.c @@ -1,7 +1,8 @@ /* meta.c -- handle the meta communication - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2017 Guus Sliepen , + 2000-2005 Ivo Timmermans + 2006 Scott Lamb 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 @@ -13,198 +14,245 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: meta.c,v 1.1.2.25 2002/03/01 14:09:31 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" -#include -#include - -#include -#include -#include -#include -/* This line must be below the rest for FreeBSD */ -#include -#include +#include "system.h" +#include #include -#include "net.h" +#include "avl_tree.h" #include "connection.h" -#include "system.h" +#include "logger.h" +#include "meta.h" +#include "net.h" #include "protocol.h" +#include "proxy.h" +#include "utils.h" +#include "xalloc.h" -int send_meta(connection_t *c, char *buffer, int length) -{ - char *bufp; - int outlen; - char outbuf[MAXBUFSIZE]; -cp - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, - c->name, c->hostname); +bool send_meta(connection_t *c, const char *buffer, int length) { + int outlen; + int result; - if(c->status.encryptout) - { - EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); - bufp = outbuf; - length = outlen; - } - else - bufp = buffer; + ifdebug(META) logger(LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length, + c->name, c->hostname); - if(write(c->socket, bufp, length) < 0) - { - syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno)); - return -1; - } -cp - return 0; + if(!c->outbuflen) { + c->last_flushed_time = now; + } + + /* Find room in connection's buffer */ + if(length + c->outbuflen > c->outbufsize) { + c->outbufsize = length + c->outbuflen; + c->outbuf = xrealloc(c->outbuf, c->outbufsize); + } + + if(length + c->outbuflen + c->outbufstart > c->outbufsize) { + memmove(c->outbuf, c->outbuf + c->outbufstart, c->outbuflen); + c->outbufstart = 0; + } + + /* Add our data to buffer */ + if(c->status.encryptout) { + /* Check encryption limits */ + if((uint64_t)length > c->outbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname); + return false; + } else { + c->outbudget -= length; + } + + result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen, + &outlen, (unsigned char *)buffer, length); + + if(!result || outlen < length) { + logger(LOG_ERR, "Error while encrypting metadata to %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } else if(outlen > length) { + logger(LOG_EMERG, "Encrypted data too long! Heap corrupted!"); + abort(); + } + + c->outbuflen += outlen; + } else { + memcpy(c->outbuf + c->outbufstart + c->outbuflen, buffer, length); + c->outbuflen += length; + } + + return true; } -void broadcast_meta(connection_t *from, char *buffer, int length) -{ - avl_node_t *node; - connection_t *c; -cp - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c != from && c->status.active) - send_meta(c, buffer, length); - } -cp +bool flush_meta(connection_t *c) { + int result; + + ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s)", + c->outbuflen, c->name, c->hostname); + + while(c->outbuflen) { + result = send(c->socket, c->outbuf + c->outbufstart, c->outbuflen, 0); + + if(result <= 0) { + if(!errno || errno == EPIPE) { + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)", + c->name, c->hostname); + } else if(errno == EINTR) { + continue; + } else if(sockwouldblock(sockerrno)) { + ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block", + c->outbuflen, c->name, c->hostname); + return true; + } else { + logger(LOG_ERR, "Flushing meta data to %s (%s) failed: %s", c->name, + c->hostname, sockstrerror(sockerrno)); + } + + return false; + } + + c->outbufstart += result; + c->outbuflen -= result; + } + + c->outbufstart = 0; /* avoid unnecessary memmoves */ + return true; } -int receive_meta(connection_t *c) -{ - int x, l = sizeof(x); - int oldlen, i; - int lenin, reqlen; - int decrypted = 0; - char inbuf[MAXBUFSIZE]; -cp - if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) - { - syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, __LINE__, c->socket, strerror(errno), - c->name, c->hostname); - return -1; - } - if(x) - { - syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"), - c->name, c->hostname, strerror(x)); - return -1; - } +void broadcast_meta(connection_t *from, const char *buffer, int length) { + avl_node_t *node; + connection_t *c; - /* Strategy: - - Read as much as possible from the TCP socket in one go. - - Decrypt it. - - Check if a full request is in the input buffer. - - If yes, process request and remove it from the buffer, - then check again. - - If not, keep stuff in buffer and exit. - */ + for(node = connection_tree->head; node; node = node->next) { + c = node->data; - lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen); - - if(lenin<=0) - { - if(lenin==0) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), - c->name, c->hostname); - } - else - if(errno==EINTR) - return 0; - else - syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"), - c->name, c->hostname, strerror(errno)); - - return -1; - } - - oldlen = c->buflen; - c->buflen += lenin; - - while(lenin) - { - /* Decrypt */ - - if(c->status.decryptin && !decrypted) - { - EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin); - memcpy(c->buffer + oldlen, inbuf, lenin); - decrypted = 1; - } - - /* Are we receiving a TCPpacket? */ - - if(c->tcplen) - { - if(c->tcplen <= c->buflen) - { - receive_tcppacket(c, c->buffer, c->tcplen); - - c->buflen -= c->tcplen; - lenin -= c->tcplen; - memmove(c->buffer, c->buffer + c->tcplen, c->buflen); - oldlen = 0; - c->tcplen = 0; - continue; - } - else - { - break; - } - } - - /* Otherwise we are waiting for a request */ - - reqlen = 0; - - for(i = oldlen; i < c->buflen; i++) - { - if(c->buffer[i] == '\n') - { - c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ - reqlen = i + 1; - break; - } - } - - if(reqlen) - { - if(receive_request(c)) - return -1; - - c->buflen -= reqlen; - lenin -= reqlen; - memmove(c->buffer, c->buffer + reqlen, c->buflen); - oldlen = 0; - continue; - } - else - { - break; - } - } - - if(c->buflen >= MAXBUFSIZE) - { - syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"), - c->name, c->hostname); - return -1; - } - - c->last_ping_time = now; -cp - return 0; + if(c != from && c->status.active) { + send_meta(c, buffer, length); + } + } +} + +bool receive_meta(connection_t *c) { + int oldlen, i, result; + int lenin, lenout, reqlen; + bool decrypted = false; + char inbuf[MAXBUFSIZE]; + + /* Strategy: + - Read as much as possible from the TCP socket in one go. + - Decrypt it. + - Check if a full request is in the input buffer. + - If yes, process request and remove it from the buffer, + then check again. + - If not, keep stuff in buffer and exit. + */ + + lenin = recv(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen, 0); + + if(lenin <= 0) { + if(!lenin || !errno) { + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)", + c->name, c->hostname); + } else if(sockwouldblock(sockerrno)) { + return true; + } else + logger(LOG_ERR, "Metadata socket read error for %s (%s): %s", + c->name, c->hostname, sockstrerror(sockerrno)); + + return false; + } + + oldlen = c->buflen; + c->buflen += lenin; + + while(lenin > 0) { + reqlen = 0; + + /* Is it proxy metadata? */ + + if(c->allow_request == PROXY) { + reqlen = receive_proxy_meta(c); + + if(reqlen < 0) { + return false; + } + + goto consume; + } + + /* Decrypt */ + + if(c->status.decryptin && !decrypted) { + /* Check decryption limits */ + if((uint64_t)lenin > c->inbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname); + return false; + } else { + c->inbudget -= lenin; + } + + result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin); + + if(!result || lenout != lenin) { + logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + memcpy(c->buffer + oldlen, inbuf, lenin); + decrypted = true; + } + + /* Are we receiving a TCPpacket? */ + + if(c->tcplen) { + if(c->tcplen <= c->buflen) { + if(c->allow_request != ALL) { + logger(LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); + return false; + } + + receive_tcppacket(c, c->buffer, c->tcplen); + reqlen = c->tcplen; + c->tcplen = 0; + } + } else { + /* Otherwise we are waiting for a request */ + + for(i = oldlen; i < c->buflen; i++) { + if(c->buffer[i] == '\n') { + c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ + c->reqlen = reqlen = i + 1; + break; + } + } + + if(reqlen && !receive_request(c)) { + return false; + } + } + +consume: + + if(reqlen) { + c->buflen -= reqlen; + lenin -= reqlen - oldlen; + memmove(c->buffer, c->buffer + reqlen, c->buflen); + oldlen = 0; + continue; + } else { + break; + } + } + + if(c->buflen >= MAXBUFSIZE) { + logger(LOG_ERR, "Metadata read buffer overflow for %s (%s)", + c->name, c->hostname); + return false; + } + + return true; } diff --git a/src/meta.h b/src/meta.h index d54573e..36914f1 100644 --- a/src/meta.h +++ b/src/meta.h @@ -1,7 +1,10 @@ +#ifndef TINC_META_H +#define TINC_META_H + /* meta.h -- header for meta.c - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2006 Guus Sliepen , + 2000-2005 Ivo Timmermans 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 @@ -13,20 +16,16 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: meta.h,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_META_H__ -#define __TINC_META_H__ - #include "connection.h" -extern int send_meta(connection_t *, const char *, int); -extern int broadcast_meta(connection_t *, const char *, int); -extern int receive_meta(connection_t *); +extern bool send_meta(struct connection_t *c, const char *buffer, int length); +extern void broadcast_meta(struct connection_t *c, const char *buffer, int length); +extern bool flush_meta(struct connection_t *c); +extern bool receive_meta(struct connection_t *c); -#endif /* __TINC_META_H__ */ +#endif diff --git a/src/mingw/common.h b/src/mingw/common.h new file mode 100644 index 0000000..41b9dc5 --- /dev/null +++ b/src/mingw/common.h @@ -0,0 +1,75 @@ +/* + * TAP-Win32 -- A kernel driver to provide virtual tap device functionality + * on Windows. Originally derived from the CIPE-Win32 + * project by Damion K. Wilson, with extensive modifications by + * James Yonan. + * + * All source code which derives from the CIPE-Win32 project is + * Copyright (C) Damion K. Wilson, 2003, and is released under the + * GPL version 2 (see below). + * + * All other source code is Copyright (C) James Yonan, 2003-2004, + * and is released under the GPL version 2 (see below). + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +//=============================================== +// This file is included both by OpenVPN and +// the TAP-Win32 driver and contains definitions +// common to both. +//=============================================== + +//============= +// TAP IOCTLs +//============= + +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +//================= +// Registry keys +//================= + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +//====================== +// Filesystem prefixes +//====================== + +#define USERMODEDEVICEDIR "\\\\.\\Global\\" +#define SYSDEVICEDIR "\\Device\\" +#define USERDEVICEDIR "\\DosDevices\\Global\\" +#define TAPSUFFIX ".tap" + +//========================================================= +// TAP_COMPONENT_ID -- This string defines the TAP driver +// type -- different component IDs can reside in the system +// simultaneously. +//========================================================= + +#define TAP_COMPONENT_ID "tap0801" diff --git a/src/mingw/device.c b/src/mingw/device.c new file mode 100644 index 0000000..321c515 --- /dev/null +++ b/src/mingw/device.c @@ -0,0 +1,322 @@ +/* + device.c -- Interaction with Windows tap driver in a MinGW environment + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2016 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "../system.h" + +#include +#include + +#include "../conf.h" +#include "../device.h" +#include "../logger.h" +#include "../net.h" +#include "../route.h" +#include "../utils.h" +#include "../xalloc.h" + +#include "common.h" + +int device_fd = -1; +static HANDLE device_handle = INVALID_HANDLE_VALUE; +char *device = NULL; +char *iface = NULL; +static const char *device_info = "Windows tap device"; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +extern char *myport; +OVERLAPPED r_overlapped; +OVERLAPPED w_overlapped; + +static DWORD WINAPI tapreader(void *bla) { + int status; + DWORD len; + vpn_packet_t packet; + int errors = 0; + + logger(LOG_DEBUG, "Tap reader running"); + + /* Read from tap device and send to parent */ + + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + for(;;) { + ResetEvent(r_overlapped.hEvent); + + status = ReadFile(device_handle, packet.data, MTU, &len, &r_overlapped); + + if(!status) { + if(GetLastError() == ERROR_IO_PENDING) { + WaitForSingleObject(r_overlapped.hEvent, INFINITE); + + if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE)) { + continue; + } + } else { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + errors++; + + if(errors >= 10) { + EnterCriticalSection(&mutex); + running = false; + LeaveCriticalSection(&mutex); + } + + usleep(1000000); + continue; + } + } + + errors = 0; + packet.len = len; + packet.priority = 0; + + EnterCriticalSection(&mutex); + route(myself, &packet); + LeaveCriticalSection(&mutex); + } + + return 0; +} + +static bool setup_device(void) { + HKEY key, key2; + int i; + + char regpath[1024]; + char adapterid[1024]; + char adaptername[1024]; + char tapname[1024]; + DWORD len; + unsigned long status; + + bool found = false; + + int err; + HANDLE thread; + + get_config_string(lookup_config(config_tree, "Device"), &device); + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + if(device && iface) { + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + } + + /* Open registry and look for network adapters */ + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) { + logger(LOG_ERR, "Unable to read registry: %s", winerror(GetLastError())); + return false; + } + + for(i = 0; ; i++) { + len = sizeof(adapterid); + + if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) { + break; + } + + /* Find out more about this adapter */ + + snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) { + continue; + } + + len = sizeof(adaptername); + err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len); + + RegCloseKey(key2); + + if(err) { + continue; + } + + if(device) { + if(!strcmp(device, adapterid)) { + found = true; + break; + } else { + continue; + } + } + + if(iface) { + if(!strcmp(iface, adaptername)) { + found = true; + break; + } else { + continue; + } + } + + snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + + if(device_handle != INVALID_HANDLE_VALUE) { + found = true; + break; + } + } + + RegCloseKey(key); + + if(!found) { + logger(LOG_ERR, "No Windows tap device found!"); + return false; + } + + if(!device) { + device = xstrdup(adapterid); + } + + if(!iface) { + iface = xstrdup(adaptername); + } + + /* Try to open the corresponding tap device */ + + if(device_handle == INVALID_HANDLE_VALUE) { + snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device); + device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + } + + if(device_handle == INVALID_HANDLE_VALUE) { + logger(LOG_ERR, "%s (%s) is not a usable Windows tap device: %s", device, iface, winerror(GetLastError())); + return false; + } + + /* Get MAC address from tap device */ + + if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { + logger(LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError())); + return false; + } + + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = 1; + } + + /* Create overlapped events for tap I/O */ + + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + w_overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + + /* Start the tap reader */ + + thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL); + + if(!thread) { + logger(LOG_ERR, "System call `%s' failed: %s", "CreateThread", winerror(GetLastError())); + return false; + } + + /* Set media status for newer TAP-Win32 devices */ + + status = true; + DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL); + + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); + + return true; +} + +static void close_device(void) { + CloseHandle(device_handle); + + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + return false; +} + +static bool write_packet(vpn_packet_t *packet) { + DWORD lenout; + static vpn_packet_t queue; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + /* Check if there is something in progress */ + + if(queue.len) { + DWORD size; + BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE); + + if(success) { + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + int err = GetLastError(); + + if(err != ERROR_IO_INCOMPLETE) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err)); + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Previous overlapped write still in progress"); + // drop this packet + return true; + } + } + } + + /* Otherwise, try to write. */ + + memcpy(queue.data, packet->data, packet->len); + + if(!WriteFile(device_handle, queue.data, packet->len, &lenout, &w_overlapped)) { + int err = GetLastError(); + + if(err != ERROR_IO_PENDING) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err)); + return false; + } + + // Write is being done asynchronously. + queue.len = packet->len; + } else { + // Write was completed immediately. + ResetEvent(&w_overlapped); + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t os_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/multicast_device.c b/src/multicast_device.c new file mode 100644 index 0000000..93a40c4 --- /dev/null +++ b/src/multicast_device.c @@ -0,0 +1,247 @@ +/* + device.c -- multicast socket + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2014 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "conf.h" +#include "device.h" +#include "net.h" +#include "logger.h" +#include "netutl.h" +#include "utils.h" +#include "route.h" +#include "xalloc.h" + +static const char *device_info = "multicast socket"; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static struct addrinfo *ai = NULL; +static mac_t ignore_src = {{0}}; + +static bool setup_device(void) { + char *host; + char *port; + char *space; + int ttl = 1; + + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + logger(LOG_ERR, "Device variable required for %s", device_info); + return false; + } + + host = xstrdup(device); + space = strchr(host, ' '); + + if(!space) { + logger(LOG_ERR, "Port number required for %s", device_info); + free(host); + return false; + } + + *space++ = 0; + port = space; + space = strchr(port, ' '); + + if(space) { + *space++ = 0; + ttl = atoi(space); + } + + ai = str2addrinfo(host, port, SOCK_DGRAM); + + if(!ai) { + free(host); + return false; + } + + device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP); + + if(device_fd < 0) { + logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno)); + free(host); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + static const int one = 1; + setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); + + if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) { + closesocket(device_fd); + logger(LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno)); + free(host); + return false; + } + + switch(ai->ai_family) { +#ifdef IP_ADD_MEMBERSHIP + + case AF_INET: { + struct ip_mreq mreq; + struct sockaddr_in in; + memcpy(&in, ai->ai_addr, sizeof(in)); + mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + + if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq))) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + free(host); + return false; + } + +#ifdef IP_MULTICAST_LOOP + setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof(one)); +#endif +#ifdef IP_MULTICAST_TTL + setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl)); +#endif + } + break; +#endif + +#ifdef IPV6_JOIN_GROUP + + case AF_INET6: { + struct ipv6_mreq mreq; + struct sockaddr_in6 in6; + memcpy(&in6, ai->ai_addr, sizeof(in6)); + memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof(mreq.ipv6mr_multiaddr)); + mreq.ipv6mr_interface = in6.sin6_scope_id; + + if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof(mreq))) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + free(host); + return false; + } + +#ifdef IPV6_MULTICAST_LOOP + setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof(one)); +#endif +#ifdef IPV6_MULTICAST_HOPS + setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl)); +#endif + } + break; +#endif + + default: + logger(LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family); + closesocket(device_fd); + free(host); + return false; + } + + free(host); + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} + +static void close_device(void) { + close(device_fd); + + free(device); + free(iface); + + if(ai) { + freeaddrinfo(ai); + } +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + if((lenin = recv(device_fd, (void *)packet->data, MTU, 0)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + if(!memcmp(&ignore_src, packet->data + 6, sizeof(ignore_src))) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info); + packet->len = 0; + return true; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + device_total_out += packet->len; + + memcpy(&ignore_src, packet->data + 6, sizeof(ignore_src)); + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t multicast_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; + +#if 0 + +static bool not_supported(void) { + logger(LOG_ERR, "Raw socket device not supported on this platform"); + return false; +} + +const devops_t multicast_devops = { + .setup = not_supported, + .close = NULL, + .read = NULL, + .write = NULL, + .dump_stats = NULL, +}; +#endif diff --git a/src/net.c b/src/net.c index 1df4e9e..37ae116 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,9 @@ /* net.c -- most of the network code - Copyright (C) 1998-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans, + 2000-2015 Guus Sliepen + 2006 Scott Lamb + 2011 Loïc Grenié 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 @@ -13,217 +15,266 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: net.c,v 1.35.4.169 2002/04/01 21:28:05 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#ifdef HAVE_LINUX - #include - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* SunOS really wants sys/socket.h BEFORE net/if.h, - and FreeBSD wants these lines below the rest. */ -#include -#include -#include +#include "system.h" #include -#include -#include -#include -#include - +#include "utils.h" +#include "avl_tree.h" #include "conf.h" #include "connection.h" +#include "device.h" +#include "event.h" +#include "graph.h" +#include "logger.h" #include "meta.h" #include "net.h" #include "netutl.h" #include "process.h" #include "protocol.h" -#include "subnet.h" -#include "graph.h" -#include "process.h" #include "route.h" -#include "device.h" -#include "event.h" +#include "subnet.h" +#include "xalloc.h" -#include "system.h" - -int do_purge = 0; -int sighup = 0; -int sigalrm = 0; +bool do_purge = false; +volatile bool running = false; +#ifdef HAVE_PSELECT +bool graph_dump = false; +#endif time_t now = 0; +int contradicting_add_edge = 0; +int contradicting_del_edge = 0; +static int sleeptime = 10; /* Purge edges and subnets of unreachable nodes. Use carefully. */ -void purge(void) -{ - avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext, *cnode; - node_t *n; - edge_t *e; - subnet_t *s; - connection_t *c; -cp - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_DEBUG, _("Purging unreachable nodes")); +static void purge(void) { + avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext; + node_t *n; + edge_t *e; + subnet_t *s; - for(nnode = node_tree->head; nnode; nnode = nnext) - { - nnext = nnode->next; - n = (node_t *)nnode->data; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Purging unreachable nodes"); - if(!n->status.reachable) - { - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname); + /* Remove all edges and subnets owned by unreachable nodes. */ - for(snode = n->subnet_tree->head; snode; snode = snext) - { - snext = snode->next; - s = (subnet_t *)snode->data; + for(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = nnode->data; - for(cnode = connection_tree->head; cnode; cnode = cnode->next) - { - c = (connection_t *)cnode->data; - if(c->status.active) - send_del_subnet(c, s); - } + if(!n->status.reachable) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Purging node %s (%s)", n->name, + n->hostname); - subnet_del(n, s); - } + for(snode = n->subnet_tree->head; snode; snode = snext) { + snext = snode->next; + s = snode->data; + send_del_subnet(everyone, s); - for(enode = n->edge_tree->head; enode; enode = enext) - { - enext = enode->next; - e = (edge_t *)enode->data; + if(!strictsubnets) { + subnet_del(n, s); + } + } - for(cnode = connection_tree->head; cnode; cnode = cnode->next) - { - c = (connection_t *)cnode->data; - if(c->status.active) - send_del_edge(c, e); - } + for(enode = n->edge_tree->head; enode; enode = enext) { + enext = enode->next; + e = enode->data; - edge_del(e); - } + if(!tunnelserver) { + send_del_edge(everyone, e); + } - node_del(n); - } - } -cp + edge_del(e); + } + } + } + + /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */ + + for(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = nnode->data; + + if(!n->status.reachable) { + for(enode = edge_weight_tree->head; enode; enode = enext) { + enext = enode->next; + e = enode->data; + + if(e->to == n) { + break; + } + } + + if(!enode && (!strictsubnets || !n->subnet_tree->head)) + /* in strictsubnets mode do not delete nodes with subnets */ + { + node_del(n); + } + } + } } /* put all file descriptors in an fd_set array While we're at it, purge stuff that needs to be removed. */ -void build_fdset(fd_set *fs) -{ - avl_node_t *node, *next; - connection_t *c; - int i; -cp - FD_ZERO(fs); +static int build_fdset(fd_set *readset, fd_set *writeset) { + avl_node_t *node, *next; + connection_t *c; + int i, max = 0; - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; + FD_ZERO(readset); + FD_ZERO(writeset); - if(c->status.remove) - connection_del(c); - else - FD_SET(c->socket, fs); - } + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; - if(!connection_tree->head) - purge(); + if(c->status.remove) { + connection_del(c); - for(i = 0; i < listen_sockets; i++) - { - FD_SET(listen_socket[i].tcp, fs); - FD_SET(listen_socket[i].udp, fs); - } + if(!connection_tree->head) { + purge(); + } + } else { + FD_SET(c->socket, readset); - FD_SET(device_fd, fs); -cp + if(c->outbuflen > 0 || c->status.connecting) { + FD_SET(c->socket, writeset); + } + + if(c->socket > max) { + max = c->socket; + } + } + } + + for(i = 0; i < listen_sockets; i++) { + FD_SET(listen_socket[i].tcp, readset); + + if(listen_socket[i].tcp > max) { + max = listen_socket[i].tcp; + } + + FD_SET(listen_socket[i].udp, readset); + + if(listen_socket[i].udp > max) { + max = listen_socket[i].udp; + } + } + + if(device_fd >= 0) { + FD_SET(device_fd, readset); + } + + if(device_fd > max) { + max = device_fd; + } + + return max; +} + +/* Put a misbehaving connection in the tarpit */ +void tarpit(int fd) { + static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + static int next_pit = 0; + + if(pits[next_pit] != -1) { + closesocket(pits[next_pit]); + } + + pits[next_pit++] = fd; + + if(next_pit >= (int)(sizeof pits / sizeof pits[0])) { + next_pit = 0; + } } /* Terminate a connection: - Close the socket - - Remove associated edge and tell other connections about it if report = 1 + - Remove associated edge and tell other connections about it if report = true - Check if we need to retry making an outgoing connection - Deactivate the host */ -void terminate_connection(connection_t *c, int report) -{ - avl_node_t *node; - connection_t *other; -cp - if(c->status.remove) - return; +void terminate_connection(connection_t *c, bool report) { + if(c->status.remove) { + return; + } - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Closing connection with %s (%s)"), - c->name, c->hostname); + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Closing connection with %s (%s)", + c->name, c->hostname); - c->status.remove = 1; - c->status.active = 0; + c->status.remove = true; + c->status.active = false; - if(c->node) - c->node->connection = NULL; + if(c->node) { + c->node->connection = NULL; + } - if(c->socket) - close(c->socket); + if(c->socket) { + if(c->status.tarpit) { + tarpit(c->socket); + } else { + closesocket(c->socket); + } + } - if(c->edge) - { - if(report) - { - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_del_edge(other, c->edge); - } - } + if(c->edge) { + if(!c->node) { + logger(LOG_ERR, "Connection to %s (%s) has an edge but node is NULL!", c->name, c->hostname); + // And that should never happen. + abort(); + } - edge_del(c->edge); + if(report && !tunnelserver) { + send_del_edge(everyone, c->edge); + } - /* Run MST and SSSP algorithms */ + edge_del(c->edge); + c->edge = NULL; - graph(); - } + /* Run MST and SSSP algorithms */ - /* Check if this was our outgoing connection */ + graph(); - if(c->outgoing) - { - retry_outgoing(c->outgoing); - c->outgoing = NULL; - } -cp + /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */ + + if(report && !c->node->status.reachable) { + edge_t *e; + e = lookup_edge(c->node, myself); + + if(e) { + if(!tunnelserver) { + send_del_edge(everyone, e); + } + + edge_del(e); + } + } + } + + free_connection_partially(c); + + /* Check if this was our outgoing connection */ + + if(c->outgoing) { + c->status.remove = false; + do_outgoing_connection(c); + } + +#ifndef HAVE_MINGW + /* Clean up dead proxy processes */ + + while(waitpid(-1, NULL, WNOHANG) > 0); + +#endif } /* @@ -234,216 +285,427 @@ cp end does not reply in time, we consider them dead and close the connection. */ -void check_dead_connections(void) -{ - avl_node_t *node, *next; - connection_t *c; -cp - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; - if(c->last_ping_time + pingtimeout < now) - { - if(c->status.active) - { - if(c->status.pinged) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_INFO, _("%s (%s) didn't respond to PING"), - c->name, c->hostname); - c->status.timeout = 1; - terminate_connection(c, 1); - } - else - { - send_ping(c); - } - } - else - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"), - c->name, c->hostname); - terminate_connection(c, 0); - } - } - } -cp +static void check_dead_connections(void) { + avl_node_t *node, *next; + connection_t *c; + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + + if(c->last_ping_time + pingtimeout <= now) { + if(c->status.active) { + if(c->status.pinged) { + ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", + c->name, c->hostname, (long)(now - c->last_ping_time)); + c->status.timeout = true; + terminate_connection(c, true); + } else if(c->last_ping_time + pinginterval <= now) { + send_ping(c); + } + } else { + if(c->status.remove) { + logger(LOG_WARNING, "Old connection_t for %s (%s) status %04x still lingering, deleting...", + c->name, c->hostname, bitfield_to_int(&c->status, sizeof(c->status))); + connection_del(c); + continue; + } + + ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication", + c->name, c->hostname); + + if(c->status.connecting) { + c->status.connecting = false; + closesocket(c->socket); + do_outgoing_connection(c); + } else { + c->status.tarpit = true; + terminate_connection(c, false); + } + } + } + + if(c->outbuflen > 0 && c->last_flushed_time + pingtimeout <= now) { + if(c->status.active) { + ifdebug(CONNECTIONS) logger(LOG_INFO, + "%s (%s) could not flush for %ld seconds (%d bytes remaining)", + c->name, c->hostname, (long)(now - c->last_flushed_time), c->outbuflen); + c->status.timeout = true; + terminate_connection(c, true); + } + } + } } /* check all connections to see if anything happened on their sockets */ -void check_network_activity(fd_set *f) -{ - connection_t *c; - avl_node_t *node; - int result, i; - int len = sizeof(result); - vpn_packet_t packet; -cp - if(FD_ISSET(device_fd, f)) - { - if(!read_packet(&packet)) - route_outgoing(&packet); - } +static void check_network_activity(fd_set *readset, fd_set *writeset) { + connection_t *c; + avl_node_t *node; + int result, i; + socklen_t len = sizeof(result); + vpn_packet_t packet; + static int errors = 0; - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; + /* check input from kernel */ + if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { + if(devops.read(&packet)) { + if(packet.len) { + errors = 0; + packet.priority = 0; + route(myself, &packet); + } + } else { + usleep(errors * 50000); + errors++; - if(c->status.remove) - continue; + if(errors > 10) { + logger(LOG_ERR, "Too many errors from %s, exiting!", device); + running = false; + } + } + } - if(FD_ISSET(c->socket, f)) - { - if(c->status.connecting) - { - c->status.connecting = 0; - getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len); - if(!result) - finish_connecting(c); - else - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result)); - close(c->socket); - do_outgoing_connection(c); - continue; - } - } - if(receive_meta(c) < 0) - { - terminate_connection(c, c->status.active); - continue; - } - } - } + /* check meta connections */ + for(node = connection_tree->head; node; node = node->next) { + c = node->data; - for(i = 0; i < listen_sockets; i++) - { - if(FD_ISSET(listen_socket[i].udp, f)) - handle_incoming_vpn_data(listen_socket[i].udp); - if(FD_ISSET(listen_socket[i].tcp, f)) - handle_new_meta_connection(listen_socket[i].tcp); - } -cp + if(c->status.remove) { + continue; + } + + if(FD_ISSET(c->socket, writeset)) { + if(c->status.connecting) { + c->status.connecting = false; + getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); + + if(!result) { + finish_connecting(c); + } else { + ifdebug(CONNECTIONS) logger(LOG_DEBUG, + "Error while connecting to %s (%s): %s", + c->name, c->hostname, sockstrerror(result)); + closesocket(c->socket); + do_outgoing_connection(c); + continue; + } + } + + if(!flush_meta(c)) { + terminate_connection(c, c->status.active); + continue; + } + } + + if(FD_ISSET(c->socket, readset)) { + if(!receive_meta(c)) { + c->status.tarpit = true; + terminate_connection(c, c->status.active); + continue; + } + } + } + + for(i = 0; i < listen_sockets; i++) { + if(FD_ISSET(listen_socket[i].udp, readset)) { + handle_incoming_vpn_data(i); + } + + if(FD_ISSET(listen_socket[i].tcp, readset)) { + handle_new_meta_connection(listen_socket[i].tcp); + } + } } /* this is where it all happens... */ -void main_loop(void) -{ - fd_set fset; - struct timeval tv; - int r; - time_t last_ping_check; - event_t *event; -cp - last_ping_check = now; +int main_loop(void) { + fd_set readset, writeset; +#ifdef HAVE_PSELECT + struct timespec tv; + sigset_t omask, block_mask; + time_t next_event; +#else + struct timeval tv; +#endif + int r, maxfd; + time_t last_ping_check, last_config_check, last_graph_dump; + event_t *event; - srand(now); + last_ping_check = now; + last_config_check = now; + last_graph_dump = now; - for(;;) - { - now = time(NULL); + srand(now); - tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ - tv.tv_usec = 0; +#ifdef HAVE_PSELECT - build_fdset(&fset); + if(lookup_config(config_tree, "GraphDumpFile")) { + graph_dump = true; + } - if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0) - { - if(errno != EINTR && errno != EAGAIN) - { - syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno)); - cp_trace(); - dump_connections(); - return; - } + /* Block SIGHUP & SIGALRM */ + sigemptyset(&block_mask); + sigaddset(&block_mask, SIGHUP); + sigaddset(&block_mask, SIGALRM); + sigprocmask(SIG_BLOCK, &block_mask, &omask); +#endif - continue; - } + running = true; - check_network_activity(&fset); + while(running) { +#ifdef HAVE_PSELECT + next_event = last_ping_check + pingtimeout; - if(do_purge) - { - purge(); - do_purge = 0; - } + if(graph_dump && next_event > last_graph_dump + 60) { + next_event = last_graph_dump + 60; + } - /* Let's check if everybody is still alive */ + if((event = peek_next_event()) && next_event > event->time) { + next_event = event->time; + } - if(last_ping_check + pingtimeout < now) - { - check_dead_connections(); - last_ping_check = now; + if(next_event <= now) { + tv.tv_sec = 0; + } else { + tv.tv_sec = next_event - now; + } - if(routing_mode== RMODE_SWITCH) - age_mac(); + tv.tv_nsec = 0; +#else + tv.tv_sec = 1; + tv.tv_usec = 0; +#endif - age_past_requests(); + maxfd = build_fdset(&readset, &writeset); - /* Should we regenerate our key? */ +#ifdef HAVE_MINGW + LeaveCriticalSection(&mutex); +#endif +#ifdef HAVE_PSELECT + r = pselect(maxfd + 1, &readset, &writeset, NULL, &tv, &omask); +#else + r = select(maxfd + 1, &readset, &writeset, NULL, &tv); +#endif + now = time(NULL); +#ifdef HAVE_MINGW + EnterCriticalSection(&mutex); +#endif - if(keyexpires < now) - { - if(debug_lvl >= DEBUG_STATUS) - syslog(LOG_INFO, _("Regenerating symmetric key")); + if(r < 0) { + if(!sockwouldblock(sockerrno)) { + logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno)); + dump_connections(); + return 1; + } + } - RAND_pseudo_bytes(myself->key, myself->keylength); - send_key_changed(myself->connection, myself); - keyexpires = now + keylifetime; - } - } + if(r > 0) { + check_network_activity(&readset, &writeset); + } + if(do_purge) { + purge(); + do_purge = false; + } - while((event = get_expired_event())) - { - event->handler(event->data); - free(event); - } + /* Let's check if everybody is still alive */ - if(sigalrm) - { - syslog(LOG_INFO, _("Flushing event queue")); + if(last_ping_check + pingtimeout <= now) { + check_dead_connections(); + last_ping_check = now; - while(event_tree->head) - { - event = (event_t *)event_tree->head->data; - event->handler(event->data); - event_del(event); - } - sigalrm = 0; - } + if(routing_mode == RMODE_SWITCH) { + age_subnets(); + } - if(sighup) - { - sighup = 0; - close_network_connections(); - exit_configuration(&config_tree); + age_past_requests(); - syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds...")); - sleep(5); + /* Should we regenerate our key? */ - init_configuration(&config_tree); + if(keyexpires <= now) { + avl_node_t *node; + node_t *n; - if(read_server_config()) - { - syslog(LOG_ERR, _("Unable to reread configuration file, exitting.")); - exit(1); - } + ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys"); - if(setup_network_connections()) - return; + for(node = node_tree->head; node; node = node->next) { + n = node->data; - continue; - } - } -cp + if(n->inkey) { + free(n->inkey); + n->inkey = NULL; + } + } + + send_key_changed(); + keyexpires = now + keylifetime; + } + + /* Detect ADD_EDGE/DEL_EDGE storms that are caused when + * two tinc daemons with the same name are on the VPN. + * If so, sleep a while. If this happens multiple times + * in a row, sleep longer. */ + + if(contradicting_del_edge > 100 && contradicting_add_edge > 100) { + logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime); + usleep(sleeptime * 1000000LL); + sleeptime *= 2; + + if(sleeptime < 0) { + sleeptime = 3600; + } + } else { + sleeptime /= 2; + + if(sleeptime < 10) { + sleeptime = 10; + } + } + + contradicting_add_edge = 0; + contradicting_del_edge = 0; + } + + if(sigalrm) { + avl_node_t *node; + logger(LOG_INFO, "Flushing event queue"); + expire_events(); + + for(node = connection_tree->head; node; node = node->next) { + connection_t *c = node->data; + + if(c->status.active) { + send_ping(c); + } + } + + sigalrm = false; + } + + while((event = get_expired_event())) { + event->handler(event->data); + free_event(event); + } + + if(sighup) { + connection_t *c; + avl_node_t *node, *next; + char *fname; + struct stat s; + + sighup = false; + + reopenlogger(); + + /* Reread our own configuration file */ + + exit_configuration(&config_tree); + init_configuration(&config_tree); + + if(!read_server_config()) { + logger(LOG_ERR, "Unable to reread configuration file, exitting."); + return 1; + } + + /* Cancel non-active outgoing connections */ + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + + c->outgoing = NULL; + + if(c->status.connecting) { + terminate_connection(c, false); + connection_del(c); + } + } + + /* Wipe list of outgoing connections */ + + for(list_node_t *node = outgoing_list->head; node; node = node->next) { + outgoing_t *outgoing = node->data; + + if(outgoing->event) { + event_del(outgoing->event); + } + } + + list_delete_list(outgoing_list); + + /* Close connections to hosts that have a changed or deleted host config file */ + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); + + if(stat(fname, &s) || s.st_mtime > last_config_check) { + terminate_connection(c, c->status.active); + } + + free(fname); + } + + last_config_check = now; + + /* If StrictSubnet is set, expire deleted Subnets and read new ones in */ + + if(strictsubnets) { + subnet_t *subnet; + + for(node = subnet_tree->head; node; node = node->next) { + subnet = node->data; + subnet->expires = 1; + } + + load_all_subnets(); + + for(node = subnet_tree->head; node; node = next) { + next = node->next; + subnet = node->data; + + if(subnet->expires == 1) { + send_del_subnet(everyone, subnet); + + if(subnet->owner->status.reachable) { + subnet_update(subnet->owner, subnet, false); + } + + subnet_del(subnet->owner, subnet); + } else if(subnet->expires == -1) { + subnet->expires = 0; + } else { + send_add_subnet(everyone, subnet); + + if(subnet->owner->status.reachable) { + subnet_update(subnet->owner, subnet, true); + } + } + } + } + + /* Try to make outgoing connections */ + + try_outgoing_connections(); + } + + /* Dump graph if wanted every 60 seconds*/ + + if(last_graph_dump + 60 <= now) { + dump_graph(); + last_graph_dump = now; + } + } + +#ifdef HAVE_PSELECT + /* Restore SIGHUP & SIGALARM mask */ + sigprocmask(SIG_SETMASK, &omask, NULL); +#endif + + return 0; } diff --git a/src/net.h b/src/net.h index 922c5cf..a9becb6 100644 --- a/src/net.h +++ b/src/net.h @@ -1,7 +1,10 @@ +#ifndef TINC_NET_H +#define TINC_NET_H + /* net.h -- header for net.c - Copyright (C) 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans + 2000-2015 Guus Sliepen 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 @@ -13,65 +16,58 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: net.h,v 1.9.4.49 2002/03/27 15:01:36 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NET_H__ -#define __TINC_NET_H__ +#include -#include -#include -#include -#include - -#include "config.h" +#include "ipv6.h" #ifdef ENABLE_JUMBOGRAMS - #define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */ - #define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ - #define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */ +#define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #else - #define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */ - #define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ - #define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */ +#define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #endif -#define MAXSOCKETS 128 /* Overkill... */ +#define MAXSIZE (MTU + 4 + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */ +#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) /* Enough room for a request with a MAXSIZEd packet or a 8192 bits RSA key */ -#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */ +#define MAXSOCKETS 128 /* Overkill... */ -typedef struct mac_t -{ - unsigned char x[6]; +typedef struct mac_t { + uint8_t x[6]; } mac_t; -typedef struct ipv4_t -{ - unsigned char x[4]; +typedef struct ipv4_t { + uint8_t x[4]; } ipv4_t; -typedef struct ip_mask_t { - ipv4_t address; - ipv4_t mask; -} ip_mask_t; - -typedef struct ipv6_t -{ - unsigned short x[8]; +typedef struct ipv6_t { + uint16_t x[8]; } ipv6_t; -typedef unsigned short port_t; +typedef uint16_t length_t; -typedef short length_t; +#define AF_UNKNOWN 255 -typedef union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_in6 in6; +struct sockaddr_unknown { + uint16_t family; + uint16_t pad1; + uint32_t pad2; + char *address; + char *port; +}; + +typedef union sockaddr_t { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; + struct sockaddr_unknown unknown; +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + struct sockaddr_storage storage; +#endif } sockaddr_t; #ifdef SA_LEN @@ -81,73 +77,85 @@ typedef union { #endif typedef struct vpn_packet_t { - length_t len; /* the actual number of bytes in the `data' field */ - int priority; /* priority or TOS */ - unsigned int seqno; /* 32 bits sequence number (network byte order of course) */ - unsigned char data[MAXSIZE]; + length_t len; /* the actual number of bytes in the `data' field */ + int priority; /* priority or TOS */ + uint32_t seqno; /* 32 bits sequence number (network byte order of course) */ + uint8_t data[MAXSIZE]; } vpn_packet_t; -typedef struct queue_element_t { - void *packet; - struct queue_element_t *prev; - struct queue_element_t *next; -} queue_element_t; - -typedef struct packet_queue_t { - queue_element_t *head; - queue_element_t *tail; -} packet_queue_t; - -typedef struct outgoing_t { - char *name; - int timeout; - struct config_t *cfg; - struct addrinfo *ai; - struct addrinfo *aip; -} outgoing_t; - typedef struct listen_socket_t { - int tcp; - int udp; - sockaddr_t sa; + int tcp; + int udp; + sockaddr_t sa; + int priority; } listen_socket_t; -extern int maxtimeout; +#include "conf.h" +#include "list.h" + +typedef struct outgoing_t { + char *name; + int timeout; + struct config_t *cfg; + struct addrinfo *ai; + struct addrinfo *aip; + struct event *event; +} outgoing_t; + +extern list_t *outgoing_list; + +extern int maxoutbufsize; extern int seconds_till_retry; extern int addressfamily; - -extern char *request_name[]; -extern char *status_text[]; - -#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ +extern unsigned replaywin; +extern bool localdiscovery; extern listen_socket_t listen_socket[MAXSOCKETS]; extern int listen_sockets; extern int keyexpires; extern int keylifetime; -extern int do_prune; -extern int do_purge; +extern int udp_rcvbuf; +extern int udp_sndbuf; +extern bool do_prune; +extern bool do_purge; extern char *myport; extern time_t now; +extern int contradicting_add_edge; +extern int contradicting_del_edge; -extern void retry_outgoing(outgoing_t *); -extern void handle_incoming_vpn_data(int); -extern void finish_connecting(connection_t *); -extern void do_outgoing_connection(connection_t *); -extern int handle_new_meta_connection(int); -extern int setup_listen_socket(sockaddr_t *); -extern int setup_vpn_in_socket(sockaddr_t *); -extern void send_packet(struct node_t *, vpn_packet_t *); -extern void receive_packet(struct node_t *, vpn_packet_t *); -extern void receive_tcppacket(struct connection_t *, char *, int); -extern void broadcast_packet(struct node_t *, vpn_packet_t *); -extern int setup_network_connections(void); -extern void setup_outgoing_connection(struct outgoing_t *); +extern volatile bool running; + +/* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ +#include "connection.h" +#include "node.h" + +extern void retry_outgoing(outgoing_t *outgoing); +extern void handle_incoming_vpn_data(int sock); +extern void finish_connecting(struct connection_t *c); +extern void do_outgoing_connection(struct connection_t *c); +extern bool handle_new_meta_connection(int sock); +extern int setup_listen_socket(const sockaddr_t *sa); +extern int setup_vpn_in_socket(const sockaddr_t *sa); +extern void send_packet(const struct node_t *n, vpn_packet_t *packet); +extern void receive_tcppacket(struct connection_t *c, const char *buffer, length_t len); +extern void broadcast_packet(const struct node_t *, vpn_packet_t *packet); +extern char *get_name(void); +extern bool setup_network(void); +extern void setup_outgoing_connection(struct outgoing_t *outgoing); extern void try_outgoing_connections(void); extern void close_network_connections(void); -extern void main_loop(void); -extern void terminate_connection(connection_t *, int); -extern void flush_queue(struct node_t *); -extern int read_rsa_public_key(struct connection_t *); +extern int main_loop(void); +extern void terminate_connection(struct connection_t *c, bool report); +extern void flush_queue(struct node_t *n); +extern bool read_rsa_public_key(struct connection_t *c); +extern void send_mtu_probe(struct node_t *n); +extern void load_all_subnets(void); +extern void tarpit(int fd); -#endif /* __TINC_NET_H__ */ +#ifndef HAVE_MINGW +#define closesocket(s) close(s) +#else +extern CRITICAL_SECTION mutex; +#endif + +#endif diff --git a/src/net_packet.c b/src/net_packet.c index fd2ae06..938b3b6 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1,7 +1,9 @@ /* net_packet.c -- Handles in- and outgoing VPN packets - Copyright (C) 1998-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen + 2010 Timothy Redaelli + 2010 Brandon Black 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 @@ -13,419 +15,784 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: net_packet.c,v 1.1.2.13 2002/03/27 15:01:37 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#ifdef HAVE_LINUX - #include - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* SunOS really wants sys/socket.h BEFORE net/if.h, - and FreeBSD wants these lines below the rest. */ -#include -#include -#include +#include "system.h" #include +#include #include #include #include -#ifndef HAVE_RAND_PSEUDO_BYTES -#define RAND_pseudo_bytes RAND_bytes +#ifdef HAVE_ZLIB +#include #endif -#include - -#include -#include -#include -#include +#ifdef HAVE_LZO +#include LZO1X_H +#endif +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "meta.h" +#include "device.h" +#include "ethernet.h" +#include "event.h" +#include "graph.h" +#include "logger.h" #include "net.h" #include "netutl.h" -#include "process.h" #include "protocol.h" -#include "subnet.h" -#include "graph.h" #include "process.h" #include "route.h" -#include "device.h" -#include "event.h" - -#include "system.h" +#include "utils.h" +#include "xalloc.h" int keylifetime = 0; int keyexpires = 0; +#ifdef HAVE_LZO +static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; +#endif + +static void send_udppacket(node_t *, vpn_packet_t *); + +unsigned replaywin = 16; +bool localdiscovery = false; #define MAX_SEQNO 1073741824 -/* VPN packet I/O */ +/* mtuprobes == 1..30: initial discovery, send bursts with 1 second interval + mtuprobes == 31: sleep pinginterval seconds + mtuprobes == 32: send 1 burst, sleep pingtimeout second + mtuprobes == 33: no response from other side, restart PMTU discovery process -void receive_udppacket(node_t *n, vpn_packet_t *inpkt) -{ - vpn_packet_t pkt1, pkt2; - vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; - int nextpkt = 0; - vpn_packet_t *outpkt = pkt[0]; - int outlen, outpad; - long int complen = MTU + 12; - EVP_CIPHER_CTX ctx; - char hmac[EVP_MAX_MD_SIZE]; -cp - /* Check the message authentication code */ + Probes are sent in batches of at least three, with random sizes between the + lower and upper boundaries for the MTU thus far discovered. - if(myself->digest && myself->maclength) - { - inpkt->len -= myself->maclength; - HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL); - if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength)) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname); - return; - } - } + After the initial discovery, a fourth packet is added to each batch with a + size larger than the currently known PMTU, to test if the PMTU has increased. - /* Decrypt the packet */ + In case local discovery is enabled, another packet is added to each batch, + which will be broadcast to the local network. - if(myself->cipher) - { - outpkt = pkt[nextpkt++]; +*/ - EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len); - EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); - EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); +void send_mtu_probe(node_t *n) { + vpn_packet_t packet; + int len, i; + int timeout = 1; - outpkt->len = outlen + outpad; - inpkt = outpkt; - } + n->mtuprobes++; + n->mtuevent = NULL; - /* Check the sequence number */ + if(!n->status.reachable || !n->status.validkey) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname); + n->mtuprobes = 0; + return; + } - inpkt->len -= sizeof(inpkt->seqno); - inpkt->seqno = ntohl(inpkt->seqno); + if(n->mtuprobes > 32) { + if(!n->minmtu) { + n->mtuprobes = 31; + timeout = pinginterval; + goto end; + } - if(inpkt->seqno <= n->received_seqno) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno); - return; - } - - n->received_seqno = inpkt->seqno; + ifdebug(TRAFFIC) logger(LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); + n->mtuprobes = 1; + n->minmtu = 0; + n->maxmtu = MTU; + } - if(n->received_seqno > MAX_SEQNO) - keyexpires = 0; + if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { + ifdebug(TRAFFIC) logger(LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); + n->mtuprobes = 31; + } - /* Decompress the packet */ - - if(myself->compression) - { - outpkt = pkt[nextpkt++]; + if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { + if(n->minmtu > n->maxmtu) { + n->minmtu = n->maxmtu; + } else { + n->maxmtu = n->minmtu; + } - if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK) - { - syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname); - return; - } - - outpkt->len = complen; - inpkt = outpkt; - } + n->mtu = n->minmtu; + ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes); + n->mtuprobes = 31; + } - receive_packet(n, inpkt); -cp + if(n->mtuprobes == 31) { + timeout = pinginterval; + goto end; + } else if(n->mtuprobes == 32) { + timeout = pingtimeout; + } + + for(i = 0; i < 4 + localdiscovery; i++) { + if(i == 0) { + if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) { + continue; + } + + len = n->maxmtu + 8; + } else if(n->maxmtu <= n->minmtu) { + len = n->maxmtu; + } else { + len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); + } + + if(len < 64) { + len = 64; + } + + memset(packet.data, 0, 14); + RAND_bytes(packet.data + 14, len - 14); + packet.len = len; + + if(i >= 4 && n->mtuprobes <= 10) { + packet.priority = -1; + } else { + packet.priority = 0; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); + + send_udppacket(n, &packet); + } + +end: + n->mtuevent = new_event(); + n->mtuevent->handler = (event_handler_t)send_mtu_probe; + n->mtuevent->data = n; + n->mtuevent->time = now + timeout; + event_add(n->mtuevent); } -void receive_tcppacket(connection_t *c, char *buffer, int len) -{ - vpn_packet_t outpkt; -cp - outpkt.len = len; - memcpy(outpkt.data, buffer, len); +void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname); - receive_packet(c->node, &outpkt); -cp + if(!packet->data[0]) { + packet->data[0] = 1; + send_udppacket(n, packet); + } else { + if(n->mtuprobes > 30) { + if(len == n->maxmtu + 8) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname); + n->maxmtu = MTU; + n->mtuprobes = 10; + return; + } + + if(n->minmtu) { + n->mtuprobes = 30; + } else { + n->mtuprobes = 1; + } + } + + if(len > n->maxmtu) { + len = n->maxmtu; + } + + if(n->minmtu < len) { + n->minmtu = len; + } + } } -void receive_packet(node_t *n, vpn_packet_t *packet) -{ -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname); +static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { + if(level == 0) { + memcpy(dest, source, len); + return len; + } else if(level == 10) { +#ifdef HAVE_LZO + lzo_uint lzolen = MAXSIZE; + lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); + return lzolen; +#else + return 0; +#endif + } else if(level < 10) { +#ifdef HAVE_ZLIB + unsigned long destlen = MAXSIZE; - route_incoming(n, packet); -cp + if(compress2(dest, &destlen, source, len, level) == Z_OK) { + return destlen; + } else +#endif + return 0; + } else { +#ifdef HAVE_LZO + lzo_uint lzolen = MAXSIZE; + lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem); + return lzolen; +#else + return 0; +#endif + } + + return 0; } -void send_udppacket(node_t *n, vpn_packet_t *inpkt) -{ - vpn_packet_t pkt1, pkt2; - vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; - int nextpkt = 0; - vpn_packet_t *outpkt; - int origlen; - int outlen, outpad; - long int complen = MTU + 12; - EVP_CIPHER_CTX ctx; - vpn_packet_t *copy; - static int priority = 0; - int origpriority; - int sock; -cp - /* Make sure we have a valid key */ +static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { + if(level == 0) { + memcpy(dest, source, len); + return len; + } else if(level > 9) { +#ifdef HAVE_LZO + lzo_uint lzolen = MAXSIZE; - if(!n->status.validkey) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"), - n->name, n->hostname); + if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) { + return lzolen; + } else +#endif + return 0; + } - /* Since packet is on the stack of handle_tap_input(), - we have to make a copy of it first. */ +#ifdef HAVE_ZLIB + else { + unsigned long destlen = MAXSIZE; - copy = xmalloc(sizeof(vpn_packet_t)); - memcpy(copy, inpkt, sizeof(vpn_packet_t)); + if(uncompress(dest, &destlen, source, len) == Z_OK) { + return destlen; + } else { + return 0; + } + } - list_insert_tail(n->queue, copy); - - if(n->queue->count > MAXQUEUELENGTH) - list_delete_head(n->queue); - - if(!n->status.waitingforkey) - send_req_key(n->nexthop->connection, myself, n); - - n->status.waitingforkey = 1; - - return; - } - - origlen = inpkt->len; - origpriority = inpkt->priority; - - /* Compress the packet */ - - if(n->compression) - { - outpkt = pkt[nextpkt++]; - - if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK) - { - syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname); - return; - } - - outpkt->len = complen; - inpkt = outpkt; - } - - /* Add sequence number */ - - inpkt->seqno = htonl(++(n->sent_seqno)); - inpkt->len += sizeof(inpkt->seqno); - - /* Encrypt the packet */ - - if(n->cipher) - { - outpkt = pkt[nextpkt++]; - - EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len); - EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); - EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); - - outpkt->len = outlen + outpad; - inpkt = outpkt; - } - - /* Add the message authentication code */ - - if(n->digest && n->maclength) - { - HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen); - inpkt->len += n->maclength; - } - - /* Determine which socket we have to use */ - - for(sock = 0; sock < listen_sockets; sock++) - if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) - break; - - if(sock >= listen_sockets) - sock = 0; /* If none is available, just use the first and hope for the best. */ - - /* Send the packet */ - -#if defined(SOL_IP) && defined(IP_TOS) - if(priorityinheritance && origpriority != priority && listen_socket[sock].sa.sa.sa_family == AF_INET) - { - priority = origpriority; - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Setting outgoing packet priority to %d"), priority); - if(setsockopt(sock, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ - syslog(LOG_ERR, _("System call `%s' failed: %s"), "setsockopt", strerror(errno)); - } #endif - if((sendto(listen_socket[sock].udp, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) - { - syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"), - n->name, n->hostname, strerror(errno)); - return; - } - - inpkt->len = origlen; -cp + return -1; +} + +/* VPN packet I/O */ + +static void receive_packet(node_t *n, vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Received packet of %d bytes from %s (%s)", + packet->len, n->name, n->hostname); + + route(n, packet); +} + +static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) { + unsigned char hmac[EVP_MAX_MD_SIZE]; + + if(!n->indigest || !n->inmaclength || !n->inkey || inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { + return false; + } + + HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL); + + return !memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength); +} + +static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; + int nextpkt = 0; + vpn_packet_t *outpkt; + int outlen, outpad; + unsigned char hmac[EVP_MAX_MD_SIZE]; + + if(!n->inkey) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", + n->name, n->hostname); + return; + } + + /* Check packet length */ + + if(inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got too short packet from %s (%s)", + n->name, n->hostname); + return; + } + + /* Check the message authentication code */ + + if(n->indigest && n->inmaclength) { + inpkt->len -= n->inmaclength; + HMAC(n->indigest, n->inkey, n->inkeylength, + (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL); + + if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)", + n->name, n->hostname); + return; + } + } + + /* Decrypt the packet */ + + if(n->incipher) { + outpkt = pkt[nextpkt++]; + + if(!EVP_DecryptInit_ex(n->inctx, NULL, NULL, NULL, NULL) + || !EVP_DecryptUpdate(n->inctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_DecryptFinal_ex(n->inctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error decrypting packet from %s (%s): %s", + n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); + return; + } + + outpkt->len = outlen + outpad; + inpkt = outpkt; + } + + /* Check the sequence number */ + + inpkt->len -= sizeof(inpkt->seqno); + inpkt->seqno = ntohl(inpkt->seqno); + + if(replaywin) { + if(inpkt->seqno != n->received_seqno + 1) { + if(inpkt->seqno >= n->received_seqno + replaywin * 8) { + if(n->farfuture++ < replaywin >> 2) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", + n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); + return; + } + + ifdebug(TRAFFIC) logger(LOG_WARNING, "Lost %d packets from %s (%s)", + inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); + memset(n->late, 0, replaywin); + } else if(inpkt->seqno <= n->received_seqno) { + if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", + n->name, n->hostname, inpkt->seqno, n->received_seqno); + return; + } + } else { + for(uint32_t i = n->received_seqno + 1; i < inpkt->seqno; i++) { + n->late[(i / 8) % replaywin] |= 1 << i % 8; + } + } + } + + n->farfuture = 0; + n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); + } + + if(inpkt->seqno > n->received_seqno) { + n->received_seqno = inpkt->seqno; + } + + if(n->received_seqno > MAX_SEQNO) { + keyexpires = 0; + } + + /* Decompress the packet */ + + length_t origlen = inpkt->len; + + if(n->incompression) { + outpkt = pkt[nextpkt++]; + + if(!(outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression))) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while uncompressing packet from %s (%s)", + n->name, n->hostname); + return; + } + + inpkt = outpkt; + + origlen -= MTU / 64 + 20; + } + + inpkt->priority = 0; + + if(!inpkt->data[12] && !inpkt->data[13]) { + mtu_probe_h(n, inpkt, origlen); + } else { + receive_packet(n, inpkt); + } +} + +void receive_tcppacket(connection_t *c, const char *buffer, length_t len) { + vpn_packet_t outpkt; + + if(len > sizeof(outpkt.data)) { + return; + } + + outpkt.len = len; + + if(c->options & OPTION_TCPONLY) { + outpkt.priority = 0; + } else { + outpkt.priority = -1; + } + + memcpy(outpkt.data, buffer, len); + + receive_packet(c->node, &outpkt); +} + +static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; + vpn_packet_t *inpkt = origpkt; + int nextpkt = 0; + vpn_packet_t *outpkt; + int origlen; + int outlen, outpad; + int origpriority; + + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname); + return; + } + + /* Make sure we have a valid key */ + + if(!n->status.validkey) { + ifdebug(TRAFFIC) logger(LOG_INFO, + "No valid key known yet for %s (%s), forwarding via TCP", + n->name, n->hostname); + + if(n->last_req_key + 10 <= now) { + send_req_key(n); + n->last_req_key = now; + } + + send_tcppacket(n->nexthop->connection, origpkt); + + return; + } + + if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { + ifdebug(TRAFFIC) logger(LOG_INFO, + "Packet for %s (%s) larger than minimum MTU, forwarding via %s", + n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); + + if(n != n->nexthop) { + send_packet(n->nexthop, origpkt); + } else { + send_tcppacket(n->nexthop->connection, origpkt); + } + + return; + } + + origlen = inpkt->len; + origpriority = inpkt->priority; + + /* Compress the packet */ + + if(n->outcompression) { + outpkt = pkt[nextpkt++]; + + if(!(outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression))) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while compressing packet to %s (%s)", + n->name, n->hostname); + return; + } + + inpkt = outpkt; + } + + /* Add sequence number */ + + inpkt->seqno = htonl(++(n->sent_seqno)); + inpkt->len += sizeof(inpkt->seqno); + + /* Encrypt the packet */ + + if(n->outcipher) { + outpkt = pkt[nextpkt++]; + + if(!EVP_EncryptInit_ex(n->outctx, NULL, NULL, NULL, NULL) + || !EVP_EncryptUpdate(n->outctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_EncryptFinal_ex(n->outctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while encrypting packet to %s (%s): %s", + n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); + goto end; + } + + outpkt->len = outlen + outpad; + inpkt = outpkt; + } + + /* Add the message authentication code */ + + if(n->outdigest && n->outmaclength) { + HMAC(n->outdigest, n->outkey, n->outkeylength, (unsigned char *) &inpkt->seqno, + inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL); + inpkt->len += n->outmaclength; + } + + /* Determine which socket we have to use */ + + if(n->address.sa.sa_family != listen_socket[n->sock].sa.sa.sa_family) { + for(int sock = 0; sock < listen_sockets; sock++) { + if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) { + n->sock = sock; + break; + } + } + } + + /* Send the packet */ + + struct sockaddr *sa; + socklen_t sl; + int sock; + sockaddr_t broadcast; + + /* Overloaded use of priority field: -1 means local broadcast */ + + if(origpriority == -1 && n->prevedge) { + sock = rand() % listen_sockets; + memset(&broadcast, 0, sizeof(broadcast)); + + if(listen_socket[sock].sa.sa.sa_family == AF_INET6) { + broadcast.in6.sin6_family = AF_INET6; + broadcast.in6.sin6_addr.s6_addr[0x0] = 0xff; + broadcast.in6.sin6_addr.s6_addr[0x1] = 0x02; + broadcast.in6.sin6_addr.s6_addr[0xf] = 0x01; + broadcast.in6.sin6_port = n->prevedge->address.in.sin_port; + broadcast.in6.sin6_scope_id = listen_socket[sock].sa.in6.sin6_scope_id; + } else { + broadcast.in.sin_family = AF_INET; + broadcast.in.sin_addr.s_addr = -1; + broadcast.in.sin_port = n->prevedge->address.in.sin_port; + } + + sa = &broadcast.sa; + sl = SALEN(broadcast.sa); + } else { + if(origpriority == -1) { + origpriority = 0; + } + + sa = &(n->address.sa); + sl = SALEN(n->address.sa); + sock = n->sock; + } + + if(priorityinheritance && origpriority != listen_socket[n->sock].priority) { + listen_socket[n->sock].priority = origpriority; + + switch(listen_socket[n->sock].sa.sa.sa_family) { +#if defined(IP_TOS) + + case AF_INET: + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority); + + if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IP, IP_TOS, (void *)&origpriority, sizeof(origpriority))) { /* SO_PRIORITY doesn't seem to work */ + logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + } + + break; +#endif +#if defined(IPV6_TCLASS) + + case AF_INET6: + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority); + + if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof(origpriority))) { + logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + } + + break; +#endif + + default: + break; + } + } + + if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) { + if(sockmsgsize(sockerrno)) { + if(n->maxmtu >= origlen) { + n->maxmtu = origlen - 1; + } + + if(n->mtu >= origlen) { + n->mtu = origlen - 1; + } + } else { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno)); + } + } + +end: + origpkt->len = origlen; } /* send a packet to the given vpn ip. */ -void send_packet(node_t *n, vpn_packet_t *packet) -{ - node_t *via; -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"), - packet->len, n->name, n->hostname); +void send_packet(const node_t *n, vpn_packet_t *packet) { + node_t *via; - if(n == myself) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_NOTICE, _("Packet is looping back to us!")); - } + if(n == myself) { + if(overwrite_mac) { + memcpy(packet->data, mymac.x, ETH_ALEN); + } - return; - } - - if(!n->status.reachable) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Node %s (%s) is not reachable"), - n->name, n->hostname); - return; - } + devops.write(packet); + return; + } - via = (n->via == myself)?n->nexthop:n->via; + ifdebug(TRAFFIC) logger(LOG_ERR, "Sending packet of %d bytes to %s (%s)", + packet->len, n->name, n->hostname); - if(via != n && debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"), - n->name, via->name, n->via->hostname); + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Node %s (%s) is not reachable", + n->name, n->hostname); + return; + } - if((myself->options | via->options) & OPTION_TCPONLY) - { - if(send_tcppacket(via->connection, packet)) - terminate_connection(via->connection, 1); - } - else - send_udppacket(via, packet); + via = (packet->priority == -1 || n->via == myself) ? n->nexthop : n->via; + + if(via != n) + ifdebug(TRAFFIC) logger(LOG_INFO, "Sending packet to %s via %s (%s)", + n->name, via->name, n->via->hostname); + + if(packet->priority == -1 || ((myself->options | via->options) & OPTION_TCPONLY)) { + if(!send_tcppacket(via->connection, packet)) { + terminate_connection(via->connection, true); + } + } else { + send_udppacket(via, packet); + } } /* Broadcast a packet using the minimum spanning tree */ -void broadcast_packet(node_t *from, vpn_packet_t *packet) -{ - avl_node_t *node; - connection_t *c; -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"), - packet->len, from->name, from->hostname); +void broadcast_packet(const node_t *from, vpn_packet_t *packet) { + avl_node_t *node; + connection_t *c; + node_t *n; - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c->status.active && c->status.mst && c != from->nexthop->connection) - send_packet(c->node, packet); - } -cp + // Always give ourself a copy of the packet. + if(from != myself) { + send_packet(myself, packet); + } + + // In TunnelServer mode, do not forward broadcast packets. + // The MST might not be valid and create loops. + if(tunnelserver || broadcast_mode == BMODE_NONE) { + return; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)", + packet->len, from->name, from->hostname); + + switch(broadcast_mode) { + // In MST mode, broadcast packets travel via the Minimum Spanning Tree. + // This guarantees all nodes receive the broadcast packet, and + // usually distributes the sending of broadcast packets over all nodes. + case BMODE_MST: + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c->status.active && c->status.mst && c != from->nexthop->connection) { + send_packet(c->node, packet); + } + } + + break; + + // In direct mode, we send copies to each node we know of. + // However, this only reaches nodes that can be reached in a single hop. + // We don't have enough information to forward broadcast packets in this case. + case BMODE_DIRECT: + if(from != myself) { + break; + } + + for(node = node_udp_tree->head; node; node = node->next) { + n = node->data; + + if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) { + send_packet(n, packet); + } + } + + break; + + default: + break; + } } -void flush_queue(node_t *n) -{ - list_node_t *node, *next; -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname); +static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { + avl_node_t *node; + edge_t *e; + node_t *n = NULL; + static time_t last_hard_try = 0; - for(node = n->queue->head; node; node = next) - { - next = node->next; - send_udppacket(n, (vpn_packet_t *)node->data); - list_delete_node(n->queue, node); - } -cp + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; + + if(e->to == myself) { + continue; + } + + if(last_hard_try == now && sockaddrcmp_noport(from, &e->address)) { + continue; + } + + if(!try_mac(e->to, pkt)) { + continue; + } + + n = e->to; + break; + } + + last_hard_try = now; + return n; } -void handle_incoming_vpn_data(int sock) -{ - vpn_packet_t pkt; - int x, l = sizeof(x); - char *hostname; - sockaddr_t from; - socklen_t fromlen = sizeof(from); - node_t *n; -cp - if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &x, &l) < 0) - { - syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"), - __FILE__, __LINE__, sock, strerror(errno)); - cp_trace(); - exit(1); - } - if(x) - { - syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x)); - return; - } +void handle_incoming_vpn_data(int sock) { + vpn_packet_t pkt; + char *hostname; + sockaddr_t from; + socklen_t fromlen = sizeof(from); + node_t *n; - if((pkt.len = recvfrom(sock, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 0) - { - syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); - return; - } + ssize_t len = recvfrom(listen_socket[sock].udp, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); - sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ + if(len <= 0 || len > UINT16_MAX) { + if(len >= 0) { + logger(LOG_ERR, "Receiving packet with invalid size"); + } else if(!sockwouldblock(sockerrno)) { + logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno)); + } - n = lookup_node_udp(&from); + return; + } - if(!n) - { - hostname = sockaddr2hostname(&from); - syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname); - free(hostname); - return; - } + pkt.len = len; + sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ - if(n->connection) - n->connection->last_ping_time = now; + n = lookup_node_udp(&from); - receive_udppacket(n, &pkt); -cp + if(!n) { + n = try_harder(&from, &pkt); + + if(n) { + update_node_udp(n, &from); + } else ifdebug(PROTOCOL) { + hostname = sockaddr2hostname(&from); + logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname); + free(hostname); + return; + } else { + return; + } + } + + n->sock = sock; + + receive_udppacket(n, &pkt); } - diff --git a/src/net_setup.c b/src/net_setup.c index b5dc727..f26007b 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -1,7 +1,9 @@ /* net_setup.c -- Setup. - Copyright (C) 1998-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans, + 2000-2017 Guus Sliepen + 2006 Scott Lamb + 2010 Brandon Black 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 @@ -13,552 +15,1114 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: net_setup.c,v 1.1.2.14 2002/04/01 21:28:39 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#ifdef HAVE_LINUX - #include - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* SunOS really wants sys/socket.h BEFORE net/if.h, - and FreeBSD wants these lines below the rest. */ -#include -#include -#include +#include "system.h" #include #include #include +#include +#include +#include -#include -#include -#include -#include - +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "meta.h" +#include "device.h" +#include "event.h" +#include "graph.h" +#include "logger.h" #include "net.h" #include "netutl.h" #include "process.h" #include "protocol.h" -#include "subnet.h" -#include "graph.h" -#include "process.h" +#include "proxy.h" #include "route.h" -#include "device.h" -#include "event.h" - -#include "system.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" char *myport; +devops_t devops; -int read_rsa_public_key(connection_t *c) -{ - FILE *fp; - char *fname; - char *key; -cp - if(!c->rsa_key) - c->rsa_key = RSA_new(); +#ifndef HAVE_RSA_SET0_KEY +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { + BN_free(r->n); + r->n = n; + BN_free(r->e); + r->e = e; + BN_free(r->d); + r->d = d; + return 1; +} +#endif - /* First, check for simple PublicKey statement */ +bool read_rsa_public_key(connection_t *c) { + FILE *fp; + char *pubname; + char *hcfname; + char *key; + BIGNUM *n = NULL; + BIGNUM *e = NULL; - if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) - { - BN_hex2bn(&c->rsa_key->n, key); - BN_hex2bn(&c->rsa_key->e, "FFFF"); - free(key); - return 0; - } + if(!c->rsa_key) { + c->rsa_key = RSA_new(); +// RSA_blinding_on(c->rsa_key, NULL); + } - /* Else, check for PublicKeyFile statement and read it */ + /* First, check for simple PublicKey statement */ - if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) - { - if(is_safe_path(fname)) - { - if((fp = fopen(fname, "r")) == NULL) - { - syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"), - fname, strerror(errno)); - free(fname); - return -1; - } - free(fname); - c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - if(!c->rsa_key) - { - syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"), - fname, strerror(errno)); - return -1; - } - return 0; - } - else - { - free(fname); - return -1; - } - } + if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) { + if((size_t)BN_hex2bn(&n, key) != strlen(key)) { + free(key); + logger(LOG_ERR, "Invalid PublicKey for %s!", c->name); + return false; + } - /* Else, check if a harnessed public key is in the config file */ + free(key); + BN_hex2bn(&e, "FFFF"); - asprintf(&fname, "%s/hosts/%s", confbase, c->name); - if((fp = fopen(fname, "r"))) - { - c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - } + if(!n || !e || RSA_set0_key(c->rsa_key, n, e, NULL) != 1) { + BN_free(e); + BN_free(n); + logger(LOG_ERR, "RSA_set0_key() failed with PublicKey for %s!", c->name); + return false; + } - free(fname); + return true; + } - if(c->rsa_key) - return 0; - else - { - syslog(LOG_ERR, _("No public key for %s specified!"), c->name); - return -1; - } + /* Else, check for PublicKeyFile statement and read it */ + + if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &pubname)) { + fp = fopen(pubname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno)); + free(pubname); + return false; + } + + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) { + free(pubname); + return true; /* Woohoo. */ + } + + /* If it fails, try PEM_read_RSA_PUBKEY. */ + fp = fopen(pubname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno)); + free(pubname); + return false; + } + + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) { +// RSA_blinding_on(c->rsa_key, NULL); + free(pubname); + return true; + } + + logger(LOG_ERR, "Reading RSA public key file `%s' failed: %s", pubname, strerror(errno)); + free(pubname); + return false; + } + + /* Else, check if a harnessed public key is in the config file */ + + xasprintf(&hcfname, "%s/hosts/%s", confbase, c->name); + fp = fopen(hcfname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno)); + free(hcfname); + return false; + } + + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) { + free(hcfname); + return true; + } + + /* Try again with PEM_read_RSA_PUBKEY. */ + + fp = fopen(hcfname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno)); + free(hcfname); + return false; + } + + free(hcfname); + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); +// RSA_blinding_on(c->rsa_key, NULL); + fclose(fp); + + if(c->rsa_key) { + return true; + } + + logger(LOG_ERR, "No public key for %s specified!", c->name); + + return false; } -int read_rsa_private_key(void) -{ - FILE *fp; - char *fname, *key; -cp - if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) - { - myself->connection->rsa_key = RSA_new(); - BN_hex2bn(&myself->connection->rsa_key->d, key); - BN_hex2bn(&myself->connection->rsa_key->e, "FFFF"); - free(key); - return 0; - } +static bool read_rsa_private_key(void) { + FILE *fp; + char *fname, *key, *pubkey; + BIGNUM *n = NULL; + BIGNUM *e = NULL; + BIGNUM *d = NULL; - if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - asprintf(&fname, "%s/rsa_key.priv", confbase); + if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) { + myself->connection->rsa_key = RSA_new(); - if(is_safe_path(fname)) - { - if((fp = fopen(fname, "r")) == NULL) - { - syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"), - fname, strerror(errno)); - free(fname); - return -1; - } - free(fname); - myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - fclose(fp); - if(!myself->connection->rsa_key) - { - syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"), - fname, strerror(errno)); - return -1; - } - return 0; - } +// RSA_blinding_on(myself->connection->rsa_key, NULL); + if((size_t)BN_hex2bn(&d, key) != strlen(key)) { + logger(LOG_ERR, "Invalid PrivateKey for myself!"); + free(key); + return false; + } - free(fname); - return -1; + free(key); + + if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) { + BN_free(d); + logger(LOG_ERR, "PrivateKey used but no PublicKey found!"); + return false; + } + + if((size_t)BN_hex2bn(&n, pubkey) != strlen(pubkey)) { + free(pubkey); + BN_free(d); + logger(LOG_ERR, "Invalid PublicKey for myself!"); + return false; + } + + free(pubkey); + BN_hex2bn(&e, "FFFF"); + + if(!n || !e || !d || RSA_set0_key(myself->connection->rsa_key, n, e, d) != 1) { + BN_free(d); + BN_free(e); + BN_free(n); + logger(LOG_ERR, "RSA_set0_key() failed with PrivateKey for myself!"); + return false; + } + + return true; + } + + if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) { + xasprintf(&fname, "%s/rsa_key.priv", confbase); + } + + fp = fopen(fname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA private key file `%s': %s", + fname, strerror(errno)); + free(fname); + return false; + } + +#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN) + struct stat s; + + if(!fstat(fileno(fp), &s)) { + if(s.st_mode & ~0100700) { + logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname); + } + } else { + logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno)); + } + +#endif + + myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + + if(!myself->connection->rsa_key) { + logger(LOG_ERR, "Reading RSA private key file `%s' failed: %s", + fname, strerror(errno)); + free(fname); + return false; + } + + free(fname); + return true; +} + +/* + Read Subnets from all host config files +*/ +void load_all_subnets(void) { + DIR *dir; + struct dirent *ent; + char *dname; + char *fname; + avl_tree_t *config_tree; + config_t *cfg; + subnet_t *s, *s2; + node_t *n; + + xasprintf(&dname, "%s/hosts", confbase); + dir = opendir(dname); + + if(!dir) { + logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); + free(dname); + return; + } + + while((ent = readdir(dir))) { + if(!check_id(ent->d_name)) { + continue; + } + + n = lookup_node(ent->d_name); +#ifdef _DIRENT_HAVE_D_TYPE + //if(ent->d_type != DT_REG) + // continue; +#endif + + xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name); + init_configuration(&config_tree); + read_config_options(config_tree, ent->d_name); + read_config_file(config_tree, fname); + free(fname); + + if(!n) { + n = new_node(); + n->name = xstrdup(ent->d_name); + node_add(n); + } + + for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { + if(!get_config_subnet(cfg, &s)) { + continue; + } + + if((s2 = lookup_subnet(n, s))) { + s2->expires = -1; + } else { + subnet_add(n, s); + } + } + + exit_configuration(&config_tree); + } + + closedir(dir); +} + +char *get_name(void) { + char *name = NULL; + + get_config_string(lookup_config(config_tree, "Name"), &name); + + if(!name) { + return NULL; + } + + if(*name == '$') { + char *envname = getenv(name + 1); + char hostname[32] = ""; + + if(!envname) { + if(strcmp(name + 1, "HOST")) { + fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1); + free(name); + return false; + } + + if(gethostname(hostname, sizeof(hostname)) || !*hostname) { + fprintf(stderr, "Could not get hostname: %s\n", strerror(errno)); + free(name); + return false; + } + + hostname[31] = 0; + envname = hostname; + } + + free(name); + name = xstrdup(envname); + + for(char *c = name; *c; c++) + if(!isalnum(*c)) { + *c = '_'; + } + } + + if(!check_id(name)) { + logger(LOG_ERR, "Invalid name for myself!"); + free(name); + return false; + } + + return name; } /* Configure node_t myself and set up the local sockets (listen only) */ -int setup_myself(void) -{ - config_t *cfg; - subnet_t *subnet; - char *name, *hostname, *mode, *afname, *cipher, *digest; - struct addrinfo hint, *ai, *aip; - int choice, err; -cp - myself = new_node(); - myself->connection = new_connection(); - init_configuration(&myself->connection->config_tree); +static bool setup_myself(void) { + config_t *cfg; + subnet_t *subnet; + char *name, *hostname, *mode, *afname, *cipher, *digest, *type; + char *fname = NULL; + char *address = NULL; + char *proxy = NULL; + char *space; + char *envp[5] = {0}; + struct addrinfo *ai, *aip, hint = {0}; + bool choice; + int i, err; + int replaywin_int; + bool port_specified = false; - asprintf(&myself->hostname, _("MYSELF")); - asprintf(&myself->connection->hostname, _("MYSELF")); + myself = new_node(); + myself->connection = new_connection(); - myself->connection->options = 0; - myself->connection->protocol_version = PROT_CURRENT; + myself->hostname = xstrdup("MYSELF"); + myself->connection->hostname = xstrdup("MYSELF"); - if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */ - { - syslog(LOG_ERR, _("Name for tinc daemon required!")); - return -1; - } + myself->connection->options = 0; + myself->connection->protocol_version = PROT_CURRENT; - if(check_id(name)) - { - syslog(LOG_ERR, _("Invalid name for myself!")); - free(name); - return -1; - } - - myself->name = name; - myself->connection->name = xstrdup(name); - -cp - if(read_rsa_private_key()) - return -1; - - if(read_connection_config(myself->connection)) - { - syslog(LOG_ERR, _("Cannot open host configuration file for myself!")); - return -1; - } - - if(read_rsa_public_key(myself->connection)) - return -1; -cp - - if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) - asprintf(&myport, "655"); - -/* Read in all the subnets specified in the host configuration file */ - - cfg = lookup_config(myself->connection->config_tree, "Subnet"); - - while(cfg) - { - if(!get_config_subnet(cfg, &subnet)) - return -1; - - subnet_add(myself, subnet); - - cfg = lookup_config_next(myself->connection->config_tree, cfg); - } - -cp - /* Check some options */ - - if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice)) - if(choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice)) - if(choice) - myself->options |= OPTION_TCPONLY; - - if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice)) - if(choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice)) - if(choice) - myself->options |= OPTION_TCPONLY; - - if(myself->options & OPTION_TCPONLY) - myself->options |= OPTION_INDIRECT; - - if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) - { - if(!strcasecmp(mode, "router")) - routing_mode = RMODE_ROUTER; - else if (!strcasecmp(mode, "switch")) - routing_mode = RMODE_SWITCH; - else if (!strcasecmp(mode, "hub")) - routing_mode = RMODE_HUB; - else - { - syslog(LOG_ERR, _("Invalid routing mode!")); - return -1; - } - free(mode); - } - else - routing_mode = RMODE_ROUTER; - - get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); -#if !defined(SOL_IP) || !defined(IP_TOS) - if(priorityinheritance) - syslog(LOG_WARNING, _("PriorityInheritance not supported on this platform")); -#endif - - if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) - macexpire= 600; - - if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout)) - { - if(maxtimeout <= 0) - { - syslog(LOG_ERR, _("Bogus maximum timeout!")); - return -1; - } - } - else - maxtimeout = 900; - - if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) - { - if(!strcasecmp(afname, "IPv4")) - addressfamily = AF_INET; - else if (!strcasecmp(afname, "IPv6")) - addressfamily = AF_INET6; - else if (!strcasecmp(afname, "any")) - addressfamily = AF_UNSPEC; - else - { - syslog(LOG_ERR, _("Invalid address family!")); - return -1; - } - free(afname); - } - else - addressfamily = AF_INET; - - get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); -cp - /* Generate packet encryption key */ - - if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) - { - if(!strcasecmp(cipher, "none")) - { - myself->cipher = NULL; - } - else - { - if(!(myself->cipher = EVP_get_cipherbyname(cipher))) - { - syslog(LOG_ERR, _("Unrecognized cipher type!")); - return -1; - } - } - } - else - myself->cipher = EVP_bf_cbc(); - - if(myself->cipher) - myself->keylength = myself->cipher->key_len + myself->cipher->iv_len; - else - myself->keylength = 1; - - myself->connection->outcipher = EVP_bf_ofb(); - - myself->key = (char *)xmalloc(myself->keylength); - RAND_pseudo_bytes(myself->key, myself->keylength); - - if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) - keylifetime = 3600; - - keyexpires = now + keylifetime; - - /* Check if we want to use message authentication codes... */ - - if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest)) - { - if(!strcasecmp(digest, "none")) - { - myself->digest = NULL; - } - else - { - if(!(myself->digest = EVP_get_digestbyname(digest))) - { - syslog(LOG_ERR, _("Unrecognized digest type!")); - return -1; - } - } - } - else - myself->digest = EVP_sha1(); - - myself->connection->outdigest = EVP_sha1(); - - if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength)) - { - if(myself->digest) - { - if(myself->maclength > myself->digest->md_size) - { - syslog(LOG_ERR, _("MAC length exceeds size of digest!")); - return -1; - } - else if (myself->maclength < 0) - { - syslog(LOG_ERR, _("Bogus MAC length!")); - return -1; - } - } - } - else - myself->maclength = 4; - - myself->connection->outmaclength = 0; - - /* Compression */ - - if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression)) - { - if(myself->compression < 0 || myself->compression > 9) - { - syslog(LOG_ERR, _("Bogus compression level!")); - return -1; - } - } - else - myself->compression = 0; - - myself->connection->outcompression = 0; -cp - /* Done */ - - myself->nexthop = myself; - myself->via = myself; - myself->status.active = 1; - myself->status.reachable = 1; - node_add(myself); - - graph(); - -cp - /* Open sockets */ - - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = addressfamily; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - hint.ai_flags = AI_PASSIVE; - - if((err = getaddrinfo(NULL, myport, &hint, &ai)) || !ai) - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(err)); - return -1; - } - - for(aip = ai; aip; aip = aip->ai_next) - { - if((listen_socket[listen_sockets].tcp = setup_listen_socket((sockaddr_t *)aip->ai_addr)) < 0) - continue; - - if((listen_socket[listen_sockets].udp = setup_vpn_in_socket((sockaddr_t *)aip->ai_addr)) < 0) - continue; - - if(debug_lvl >= DEBUG_CONNECTIONS) - { - hostname = sockaddr2hostname((sockaddr_t *)aip->ai_addr); - syslog(LOG_NOTICE, _("Listening on %s"), hostname); - free(hostname); + if(!(name = get_name())) { + logger(LOG_ERR, "Name for tinc daemon required!"); + return false; } - listen_socket[listen_sockets].sa.sa = *aip->ai_addr; - listen_sockets++; - } + /* Read tinc.conf and our own host config file */ - freeaddrinfo(ai); + myself->name = name; + myself->connection->name = xstrdup(name); + xasprintf(&fname, "%s/hosts/%s", confbase, name); + read_config_options(config_tree, name); + read_config_file(config_tree, fname); + free(fname); - if(listen_sockets) - syslog(LOG_NOTICE, _("Ready")); - else - { - syslog(LOG_ERR, _("Unable to create any listening socket!")); - return -1; - } -cp - return 0; + if(!read_rsa_private_key()) { + return false; + } + + if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) { + myport = xstrdup("655"); + } else { + port_specified = true; + } + + /* Ensure myport is numeric */ + + if(!atoi(myport)) { + struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); + sockaddr_t sa; + + if(!ai || !ai->ai_addr) { + return false; + } + + free(myport); + memcpy(&sa, ai->ai_addr, ai->ai_addrlen); + sockaddr2str(&sa, NULL, &myport); + } + + if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) { + if((space = strchr(proxy, ' '))) { + *space++ = 0; + } + + if(!strcasecmp(proxy, "none")) { + proxytype = PROXY_NONE; + } else if(!strcasecmp(proxy, "socks4")) { + proxytype = PROXY_SOCKS4; + } else if(!strcasecmp(proxy, "socks4a")) { + proxytype = PROXY_SOCKS4A; + } else if(!strcasecmp(proxy, "socks5")) { + proxytype = PROXY_SOCKS5; + } else if(!strcasecmp(proxy, "http")) { + proxytype = PROXY_HTTP; + } else if(!strcasecmp(proxy, "exec")) { + proxytype = PROXY_EXEC; + } else { + logger(LOG_ERR, "Unknown proxy type %s!", proxy); + free(proxy); + return false; + } + + switch(proxytype) { + case PROXY_NONE: + default: + break; + + case PROXY_EXEC: + if(!space || !*space) { + logger(LOG_ERR, "Argument expected for proxy type exec!"); + free(proxy); + return false; + } + + proxyhost = xstrdup(space); + break; + + case PROXY_SOCKS4: + case PROXY_SOCKS4A: + case PROXY_SOCKS5: + case PROXY_HTTP: + proxyhost = space; + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxyport = space; + } + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxyuser = space; + } + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxypass = space; + } + + if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { + logger(LOG_ERR, "Host and port argument expected for proxy!"); + free(proxy); + return false; + } + + proxyhost = xstrdup(proxyhost); + proxyport = xstrdup(proxyport); + + if(proxyuser && *proxyuser) { + proxyuser = xstrdup(proxyuser); + } + + if(proxypass && *proxypass) { + proxypass = xstrdup(proxypass); + } + + break; + } + + free(proxy); + } + + /* Read in all the subnets specified in the host configuration file */ + + cfg = lookup_config(config_tree, "Subnet"); + + while(cfg) { + if(!get_config_subnet(cfg, &subnet)) { + return false; + } + + subnet_add(myself, subnet); + + cfg = lookup_config_next(config_tree, cfg); + } + + /* Check some options */ + + if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) { + myself->options |= OPTION_INDIRECT; + } + + if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) { + myself->options |= OPTION_TCPONLY; + } + + if(myself->options & OPTION_TCPONLY) { + myself->options |= OPTION_INDIRECT; + } + + get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); + get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets); + get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver); + get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); + strictsubnets |= tunnelserver; + + if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) { + if(!strcasecmp(mode, "router")) { + routing_mode = RMODE_ROUTER; + } else if(!strcasecmp(mode, "switch")) { + routing_mode = RMODE_SWITCH; + } else if(!strcasecmp(mode, "hub")) { + routing_mode = RMODE_HUB; + } else { + logger(LOG_ERR, "Invalid routing mode!"); + free(mode); + return false; + } + + free(mode); + } + + if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) { + if(!strcasecmp(mode, "off")) { + forwarding_mode = FMODE_OFF; + } else if(!strcasecmp(mode, "internal")) { + forwarding_mode = FMODE_INTERNAL; + } else if(!strcasecmp(mode, "kernel")) { + forwarding_mode = FMODE_KERNEL; + } else { + logger(LOG_ERR, "Invalid forwarding mode!"); + free(mode); + return false; + } + + free(mode); + } + + choice = !(myself->options & OPTION_TCPONLY); + get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice); + + if(choice) { + myself->options |= OPTION_PMTU_DISCOVERY; + } + + choice = true; + get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice); + + if(choice) { + myself->options |= OPTION_CLAMP_MSS; + } + + get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); + get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl); + + if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) { + if(!strcasecmp(mode, "no")) { + broadcast_mode = BMODE_NONE; + } else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst")) { + broadcast_mode = BMODE_MST; + } else if(!strcasecmp(mode, "direct")) { + broadcast_mode = BMODE_DIRECT; + } else { + logger(LOG_ERR, "Invalid broadcast mode!"); + free(mode); + return false; + } + + free(mode); + } + +#if !defined(SOL_IP) || !defined(IP_TOS) + + if(priorityinheritance) { + logger(LOG_WARNING, "%s not supported on this platform for IPv4 connection", "PriorityInheritance"); + } + +#endif + +#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS) + + if(priorityinheritance) { + logger(LOG_WARNING, "%s not supported on this platform for IPv6 connection", "PriorityInheritance"); + } + +#endif + + if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) { + macexpire = 600; + } + + if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) { + if(maxtimeout <= 0) { + logger(LOG_ERR, "Bogus maximum timeout!"); + return false; + } + } else { + maxtimeout = 900; + } + + if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) { + if(mintimeout < 0) { + logger(LOG_ERR, "Bogus minimum timeout!"); + return false; + } + + if(mintimeout > maxtimeout) { + logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout); + mintimeout = maxtimeout; + } + } else { + mintimeout = 0; + } + + if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) { + if(udp_rcvbuf <= 0) { + logger(LOG_ERR, "UDPRcvBuf cannot be negative!"); + return false; + } + } + + if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) { + if(udp_sndbuf <= 0) { + logger(LOG_ERR, "UDPSndBuf cannot be negative!"); + return false; + } + } + + if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) { + if(replaywin_int < 0) { + logger(LOG_ERR, "ReplayWindow cannot be negative!"); + return false; + } + + replaywin = (unsigned)replaywin_int; + } + + if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { + if(!strcasecmp(afname, "IPv4")) { + addressfamily = AF_INET; + } else if(!strcasecmp(afname, "IPv6")) { + addressfamily = AF_INET6; + } else if(!strcasecmp(afname, "any")) { + addressfamily = AF_UNSPEC; + } else { + logger(LOG_ERR, "Invalid address family!"); + free(afname); + return false; + } + + free(afname); + } + + get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); + + /* Generate packet encryption key */ + + if(get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) { + if(!strcasecmp(cipher, "none")) { + myself->incipher = NULL; + } else { + myself->incipher = EVP_get_cipherbyname(cipher); + + if(!myself->incipher) { + logger(LOG_ERR, "Unrecognized cipher type!"); + free(cipher); + return false; + } + } + + free(cipher); + } else { + myself->incipher = EVP_aes_256_cbc(); + } + + if(myself->incipher) { + myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher); + } else { + myself->inkeylength = 1; + } + + /* We need to use a stream mode for the meta protocol. Use AES for this, + but try to match the key size with the one from the cipher selected + by Cipher. + + If Cipher is set to none, still use a low level of encryption for the + meta protocol. + */ + + int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0; + + if(keylen <= 16) { + myself->connection->outcipher = EVP_aes_128_cfb(); + } else if(keylen <= 24) { + myself->connection->outcipher = EVP_aes_192_cfb(); + } else { + myself->connection->outcipher = EVP_aes_256_cfb(); + } + + if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) { + keylifetime = 3600; + } + + keyexpires = now + keylifetime; + + /* Check if we want to use message authentication codes... */ + + if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) { + if(!strcasecmp(digest, "none")) { + myself->indigest = NULL; + } else { + myself->indigest = EVP_get_digestbyname(digest); + + if(!myself->indigest) { + logger(LOG_ERR, "Unrecognized digest type!"); + free(digest); + return false; + } + } + + free(digest); + } else { + myself->indigest = EVP_sha256(); + } + + myself->connection->outdigest = EVP_sha256(); + + if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) { + if(myself->indigest) { + if(myself->inmaclength > EVP_MD_size(myself->indigest)) { + logger(LOG_ERR, "MAC length exceeds size of digest!"); + return false; + } else if(myself->inmaclength < 0) { + logger(LOG_ERR, "Bogus MAC length!"); + return false; + } + } + } else { + myself->inmaclength = 4; + } + + myself->connection->outmaclength = 0; + + /* Compression */ + + if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { + if(myself->incompression < 0 || myself->incompression > 11) { + logger(LOG_ERR, "Bogus compression level!"); + return false; + } + } else { + myself->incompression = 0; + } + + myself->connection->outcompression = 0; + + /* Done */ + + myself->nexthop = myself; + myself->via = myself; + myself->status.reachable = true; + node_add(myself); + + graph(); + + if(strictsubnets) { + load_all_subnets(); + } + + /* Open device */ + + devops = os_devops; + + if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { + if(!strcasecmp(type, "dummy")) { + devops = dummy_devops; + } else if(!strcasecmp(type, "raw_socket")) { + devops = raw_socket_devops; + } else if(!strcasecmp(type, "multicast")) { + devops = multicast_devops; + } + +#ifdef ENABLE_UML + else if(!strcasecmp(type, "uml")) { + devops = uml_devops; + } + +#endif +#ifdef ENABLE_VDE + else if(!strcasecmp(type, "vde")) { + devops = vde_devops; + } + +#endif + free(type); + } + + if(!devops.setup()) { + return false; + } + + /* Run tinc-up script to further initialize the tap interface */ + xasprintf(&envp[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); + +#ifdef HAVE_MINGW + Sleep(1000); +#endif +#ifdef HAVE_CYGWIN + sleep(1); +#endif + execute_script("tinc-up", envp); + + for(i = 0; i < 4; i++) { + free(envp[i]); + } + + /* Run subnet-up scripts for our own subnets */ + + subnet_update(myself, NULL, true); + + /* Open sockets */ + + if(!do_detach && getenv("LISTEN_FDS")) { + sockaddr_t sa; + socklen_t salen; + + listen_sockets = atoi(getenv("LISTEN_FDS")); +#ifdef HAVE_UNSETENV + unsetenv("LISTEN_FDS"); +#endif + + if(listen_sockets > MAXSOCKETS) { + logger(LOG_ERR, "Too many listening sockets"); + return false; + } + + for(i = 0; i < listen_sockets; i++) { + salen = sizeof(sa); + + if(getsockname(i + 3, &sa.sa, &salen) < 0) { + logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno)); + return false; + } + + listen_socket[i].tcp = i + 3; + +#ifdef FD_CLOEXEC + fcntl(i + 3, F_SETFD, FD_CLOEXEC); +#endif + + listen_socket[i].udp = setup_vpn_in_socket(&sa); + + if(listen_socket[i].udp < 0) { + return false; + } + + ifdebug(CONNECTIONS) { + hostname = sockaddr2hostname(&sa); + logger(LOG_NOTICE, "Listening on %s", hostname); + free(hostname); + } + + memcpy(&listen_socket[i].sa, &sa, salen); + } + } else { + listen_sockets = 0; + cfg = lookup_config(config_tree, "BindToAddress"); + + do { + get_config_string(cfg, &address); + + if(cfg) { + cfg = lookup_config_next(config_tree, cfg); + } + + char *port = myport; + + if(address) { + char *space = strchr(address, ' '); + + if(space) { + *space++ = 0; + port = space; + } + + if(!strcmp(address, "*")) { + *address = 0; + } + } + + hint.ai_family = addressfamily; + hint.ai_socktype = SOCK_STREAM; + hint.ai_protocol = IPPROTO_TCP; + hint.ai_flags = AI_PASSIVE; + +#if HAVE_DECL_RES_INIT + // ensure glibc reloads /etc/resolv.conf. + res_init(); +#endif + err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); + free(address); + + if(err || !ai) { + logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", + gai_strerror(err)); + return false; + } + + for(aip = ai; aip; aip = aip->ai_next) { + if(listen_sockets >= MAXSOCKETS) { + logger(LOG_ERR, "Too many listening sockets"); + return false; + } + + listen_socket[listen_sockets].tcp = + setup_listen_socket((sockaddr_t *) aip->ai_addr); + + if(listen_socket[listen_sockets].tcp < 0) { + continue; + } + + listen_socket[listen_sockets].udp = + setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); + + if(listen_socket[listen_sockets].udp < 0) { + continue; + } + + ifdebug(CONNECTIONS) { + hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); + logger(LOG_NOTICE, "Listening on %s", hostname); + free(hostname); + } + + memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen); + listen_sockets++; + } + + freeaddrinfo(ai); + } while(cfg); + } + + if(!listen_sockets) { + logger(LOG_ERR, "Unable to create any listening socket!"); + return false; + } + + /* If no Port option was specified, set myport to the port used by the first listening socket. */ + + if(!port_specified) { + sockaddr_t sa; + socklen_t salen = sizeof(sa); + + if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) { + free(myport); + sockaddr2str(&sa, NULL, &myport); + + if(!myport) { + myport = xstrdup("655"); + } + } + } + + /* Done. */ + + logger(LOG_NOTICE, "Ready"); + return true; } /* - setup all initial network connections + initialize network */ -int setup_network_connections(void) -{ -cp - now = time(NULL); +bool setup_network(void) { + now = time(NULL); - init_connections(); - init_subnets(); - init_nodes(); - init_edges(); - init_events(); - init_requests(); + init_events(); + init_connections(); + init_subnets(); + init_nodes(); + init_edges(); + init_requests(); - if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) - { - if(pingtimeout < 1) - { - pingtimeout = 86400; - } - } - else - pingtimeout = 60; + if(get_config_int(lookup_config(config_tree, "PingInterval"), &pinginterval)) { + if(pinginterval < 1) { + pinginterval = 86400; + } + } else { + pinginterval = 60; + } - if(setup_device() < 0) - return -1; + if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) { + pingtimeout = 5; + } - /* Run tinc-up script to further initialize the tap interface */ - execute_script("tinc-up"); + if(pingtimeout < 1 || pingtimeout > pinginterval) { + pingtimeout = pinginterval; + } - if(setup_myself() < 0) - return -1; + if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) { + maxoutbufsize = 10 * MTU; + } - try_outgoing_connections(); -cp - return 0; + if(!setup_myself()) { + return false; + } + + return true; } /* close all open network connections */ -void close_network_connections(void) -{ - avl_node_t *node, *next; - connection_t *c; - int i; -cp - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; - if(c->outgoing) - free(c->outgoing->name), free(c->outgoing), c->outgoing = NULL; - terminate_connection(c, 0); - } +void close_network_connections(void) { + avl_node_t *node, *next; + connection_t *c; + char *envp[5] = {0}; + int i; - if(myself && myself->connection) - terminate_connection(myself->connection, 0); + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + c->outgoing = NULL; + terminate_connection(c, false); + } - for(i = 0; i < listen_sockets; i++) - { - close(listen_socket[i].tcp); - close(listen_socket[i].udp); - } + for(list_node_t *node = outgoing_list->head; node; node = node->next) { + outgoing_t *outgoing = node->data; - exit_requests(); - exit_events(); - exit_edges(); - exit_subnets(); - exit_nodes(); - exit_connections(); + if(outgoing->event) { + event_del(outgoing->event); + } + } - execute_script("tinc-down"); + list_delete_list(outgoing_list); - close_device(); -cp - return; + if(myself && myself->connection) { + subnet_update(myself, NULL, false); + terminate_connection(myself->connection, false); + free_connection(myself->connection); + } + + for(i = 0; i < listen_sockets; i++) { + close(listen_socket[i].tcp); + close(listen_socket[i].udp); + } + + xasprintf(&envp[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); + + exit_requests(); + exit_edges(); + exit_subnets(); + exit_nodes(); + exit_connections(); + exit_events(); + + execute_script("tinc-down", envp); + + if(myport) { + free(myport); + } + + for(i = 0; i < 4; i++) { + free(envp[i]); + } + + devops.close(); + + return; } diff --git a/src/net_socket.c b/src/net_socket.c index 73e5fb6..6195c16 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -1,7 +1,9 @@ /* net_socket.c -- Handle various kinds of sockets. - Copyright (C) 1998-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans, + 2000-2017 Guus Sliepen + 2006 Scott Lamb + 2009 Florian Forster 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 @@ -13,472 +15,719 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: net_socket.c,v 1.1.2.11 2002/03/27 14:02:36 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#ifdef HAVE_LINUX - #include - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* SunOS really wants sys/socket.h BEFORE net/if.h, - and FreeBSD wants these lines below the rest. */ -#include -#include -#include - -#include -#include -#include -#include - -#include "conf.h" -#include "connection.h" -#include "meta.h" -#include "net.h" -#include "netutl.h" -#include "process.h" -#include "protocol.h" -#include "subnet.h" -#include "graph.h" -#include "process.h" -#include "route.h" -#include "device.h" -#include "event.h" - #include "system.h" -int addressfamily = AF_INET; +#include "avl_tree.h" +#include "conf.h" +#include "connection.h" +#include "event.h" +#include "logger.h" +#include "meta.h" +#include "net.h" +#include "netutl.h" +#include "protocol.h" +#include "proxy.h" +#include "utils.h" +#include "xalloc.h" + +/* Needed on Mac OS/X */ +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + +int addressfamily = AF_UNSPEC; +int mintimeout = 0; int maxtimeout = 900; int seconds_till_retry = 5; +int udp_rcvbuf = 0; +int udp_sndbuf = 0; listen_socket_t listen_socket[MAXSOCKETS]; -int listen_sockets = 0; +int listen_sockets; +list_t *outgoing_list = NULL; /* Setup sockets */ -int setup_listen_socket(sockaddr_t *sa) -{ - int nfd, flags; - char *addrstr; - int option; -#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - char *interface; - struct ifreq ifr; +static void configure_tcp(connection_t *c) { + int option; + +#ifdef O_NONBLOCK + int flags = fcntl(c->socket, F_GETFL); + + if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) { + logger(LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno)); + } + +#elif defined(WIN32) + unsigned long arg = 1; + + if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) { + logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno)); + } + #endif -cp - if((nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0) - { - syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno)); - return -1; - } - - flags = fcntl(nfd, F_GETFL); - if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); - return -1; - } - - /* Optimize TCP settings */ - - option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); #if defined(SOL_TCP) && defined(TCP_NODELAY) - setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); + option = 1; + setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof(option)); #endif -#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY) - option = IPTOS_LOWDELAY; - setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option)); +#if defined(IP_TOS) && defined(IPTOS_LOWDELAY) + option = IPTOS_LOWDELAY; + setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof(option)); #endif - if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface)) - { +#if defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY) + option = IPTOS_LOWDELAY; + setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option)); +#endif +} + +static bool bind_to_interface(int sd) { + char *iface; + #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) - { - close(nfd); - syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno)); - return -1; + struct ifreq ifr; + int status; +#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */ + + if(!get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) { + return true; } + +#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + free(iface); + + status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); + + if(status) { + logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno)); + return false; + } + +#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */ + logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface"); +#endif + + return true; +} + +int setup_listen_socket(const sockaddr_t *sa) { + int nfd; + char *addrstr; + int option; + char *iface; + + nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + + if(nfd < 0) { + ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno)); + return -1; + } + +#ifdef FD_CLOEXEC + fcntl(nfd, F_SETFD, FD_CLOEXEC); +#endif + + /* Optimize TCP settings */ + + option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); + +#if defined(IPV6_V6ONLY) + + if(sa->sa.sa_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + #else - syslog(LOG_WARNING, _("BindToDevice not supported on this platform")); +#warning IPV6_V6ONLY not defined #endif - } - if(bind(nfd, &sa->sa, SALEN(sa->sa))) - { - close(nfd); - addrstr = sockaddr2hostname(sa); - syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno)); - free(addrstr); - return -1; - } + if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) { +#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) + struct ifreq ifr; - if(listen(nfd, 3)) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); - return -1; - } -cp - return nfd; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + free(iface); + + if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) { + closesocket(nfd); + logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(sockerrno)); + return -1; + } + +#else + logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface"); +#endif + } + + if(bind(nfd, &sa->sa, SALEN(sa->sa))) { + closesocket(nfd); + addrstr = sockaddr2hostname(sa); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); + free(addrstr); + return -1; + } + + if(listen(nfd, 3)) { + closesocket(nfd); + logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); + return -1; + } + + return nfd; } -int setup_vpn_in_socket(sockaddr_t *sa) -{ - int nfd, flags; - char *addrstr; - int option; -#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - char *interface; - struct ifreq ifr; +int setup_vpn_in_socket(const sockaddr_t *sa) { + int nfd; + char *addrstr; + int option; + + nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + + if(nfd < 0) { + logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno)); + return -1; + } + +#ifdef FD_CLOEXEC + fcntl(nfd, F_SETFD, FD_CLOEXEC); #endif -cp - if((nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno)); - return -1; - } - flags = fcntl(nfd, F_GETFL); - if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); - return -1; - } - - option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); - -#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface)) - { - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) +#ifdef O_NONBLOCK { - close(nfd); - syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno)); - return -1; + int flags = fcntl(nfd, F_GETFL); + + if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + closesocket(nfd); + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", + strerror(errno)); + return -1; + } + } +#elif defined(WIN32) + { + unsigned long arg = 1; + + if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { + closesocket(nfd); + logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); + return -1; + } } - } #endif - if(bind(nfd, &sa->sa, SALEN(sa->sa))) - { - close(nfd); - addrstr = sockaddr2hostname(sa); - syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno)); - free(addrstr); - return -1; - } -cp - return nfd; -} + option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); + setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option)); -void retry_outgoing(outgoing_t *outgoing) -{ - event_t *event; -cp - outgoing->timeout += 5; - if(outgoing->timeout > maxtimeout) - outgoing->timeout = maxtimeout; + if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) { + logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno)); + } - event = new_event(); - event->handler = (event_handler_t)setup_outgoing_connection; - event->time = now + outgoing->timeout; - event->data = outgoing; - event_add(event); + if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) { + logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno)); + } - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout); -cp -} +#if defined(IPV6_V6ONLY) -int setup_outgoing_socket(connection_t *c) -{ - int option; -cp - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname); + if(sa->sa.sa_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } - c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - - if(c->socket == -1) - { - syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno)); - return -1; - } - - /* Optimize TCP settings */ - -#ifdef HAVE_LINUX - option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); - - option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); #endif - /* Connect */ +#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) +#define IP_DONTFRAGMENT IP_DONTFRAG +#endif - if(connect(c->socket, &c->address.sa, SALEN(c->address.sa)) == -1) - { - close(c->socket); - syslog(LOG_ERR, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(errno)); - return -1; - } +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); -cp - return 0; + if(myself->options & OPTION_PMTU_DISCOVERY) { + option = IP_PMTUDISC_DO; + setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); + } + +#elif defined(IP_DONTFRAGMENT) + + if(myself->options & OPTION_PMTU_DISCOVERY) { + option = 1; + setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); + } + +#endif + +#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + + if(myself->options & OPTION_PMTU_DISCOVERY) { + option = IPV6_PMTUDISC_DO; + setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); + } + +#elif defined(IPV6_DONTFRAG) + + if(myself->options & OPTION_PMTU_DISCOVERY) { + option = 1; + setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); + } + +#endif + + if(!bind_to_interface(nfd)) { + closesocket(nfd); + return -1; + } + + if(bind(nfd, &sa->sa, SALEN(sa->sa))) { + closesocket(nfd); + addrstr = sockaddr2hostname(sa); + logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno)); + free(addrstr); + return -1; + } + + return nfd; +} /* int setup_vpn_in_socket */ + +void retry_outgoing(outgoing_t *outgoing) { + outgoing->timeout += 5; + + if(outgoing->timeout < mintimeout) { + outgoing->timeout = mintimeout; + } + + if(outgoing->timeout > maxtimeout) { + outgoing->timeout = maxtimeout; + } + + if(outgoing->event) { + event_del(outgoing->event); + } + + outgoing->event = new_event(); + outgoing->event->handler = (event_handler_t) setup_outgoing_connection; + outgoing->event->time = now + outgoing->timeout; + outgoing->event->data = outgoing; + event_add(outgoing->event); + + ifdebug(CONNECTIONS) logger(LOG_NOTICE, + "Trying to re-establish outgoing connection in %d seconds", + outgoing->timeout); } +void finish_connecting(connection_t *c) { + ifdebug(CONNECTIONS) logger(LOG_INFO, "Connected to %s (%s)", c->name, c->hostname); -void finish_connecting(connection_t *c) -{ -cp - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); + c->last_ping_time = now; - c->last_ping_time = now; - - send_id(c); -cp + send_id(c); } -void do_outgoing_connection(connection_t *c) -{ - char *address, *port; - int option, result, flags; -cp +static void do_outgoing_pipe(connection_t *c, char *command) { +#ifndef HAVE_MINGW + int fd[2]; + + if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { + logger(LOG_ERR, "Could not create socketpair: %s\n", strerror(errno)); + return; + } + + if(fork()) { + c->socket = fd[0]; + close(fd[1]); + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Using proxy %s", command); + return; + } + + close(0); + close(1); + close(fd[0]); + dup2(fd[1], 0); + dup2(fd[1], 1); + close(fd[1]); + + // Other filedescriptors should be closed automatically by CLOEXEC + + char *host = NULL; + char *port = NULL; + + sockaddr2str(&c->address, &host, &port); + setenv("REMOTEADDRESS", host, true); + setenv("REMOTEPORT", port, true); + setenv("NODE", c->name, true); + setenv("NAME", myself->name, true); + + if(netname) { + setenv("NETNAME", netname, true); + } + + int result = system(command); + + if(result < 0) { + logger(LOG_ERR, "Could not execute %s: %s\n", command, strerror(errno)); + } else if(result) { + logger(LOG_ERR, "%s exited with non-zero status %d", command, result); + } + + exit(result); +#else + logger(LOG_ERR, "Proxy type exec not supported on this platform!"); + return; +#endif +} + +static bool is_valid_host_port(const char *host, const char *port) { + for(const char *p = host; *p; p++) + if(!isalnum(*p) && *p != '-' && *p != '.') { + return false; + } + + for(const char *p = port; *p; p++) + if(!isalnum(*p)) { + return false; + } + + return true; +} + +void do_outgoing_connection(connection_t *c) { + struct addrinfo *proxyai = NULL; + int result; + + if(!c->outgoing) { + logger(LOG_ERR, "do_outgoing_connection() for %s called without c->outgoing", c->name); + abort(); + } + begin: - if(!c->outgoing->ai) - { - if(!c->outgoing->cfg) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("Could not set up a meta connection to %s"), c->name); - c->status.remove = 1; - retry_outgoing(c->outgoing); - return; - } - get_config_string(c->outgoing->cfg, &address); + if(!c->outgoing->ai) { + if(!c->outgoing->cfg) { + ifdebug(CONNECTIONS) logger(LOG_ERR, "Could not set up a meta connection to %s", + c->name); + c->status.remove = true; + retry_outgoing(c->outgoing); + c->outgoing = NULL; + return; + } - if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) - asprintf(&port, "655"); + char *address, *port, *space; - c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - free(address); - free(port); + get_config_string(c->outgoing->cfg, &address); - c->outgoing->aip = c->outgoing->ai; - c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); - } + space = strchr(address, ' '); - if(!c->outgoing->aip) - { - freeaddrinfo(c->outgoing->ai); - c->outgoing->ai = NULL; - goto begin; - } + if(space) { + port = xstrdup(space + 1); + *space = 0; + } else { + if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) { + port = xstrdup("655"); + } + } - memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); - c->outgoing->aip = c->outgoing->aip->ai_next; + c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - if(c->hostname) - free(c->hostname); + // If we cannot resolve the address, maybe we are using a proxy that can? + if(!c->outgoing->ai && proxytype != PROXY_NONE && is_valid_host_port(address, port)) { + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_UNKNOWN; + c->address.unknown.address = address; + c->address.unknown.port = port; + } else { + free(address); + free(port); + } - c->hostname = sockaddr2hostname(&c->address); + c->outgoing->aip = c->outgoing->ai; + c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname); - - c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - - if(c->socket == -1) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno)); - - goto begin; - } - - /* Optimize TCP settings */ - -#ifdef HAVE_LINUX - option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); - - option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); -#endif - - /* Non-blocking */ - - flags = fcntl(c->socket, F_GETFL); - - if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) - { - syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno)); - } - - /* Connect */ - - result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); - - if(result == -1) - { - if(errno == EINPROGRESS) - { - c->status.connecting = 1; - return; + if(!c->outgoing->ai && proxytype != PROXY_NONE) { + goto connect; + } } - close(c->socket); + if(!c->outgoing->aip) { + if(c->outgoing->ai) { + freeaddrinfo(c->outgoing->ai); + } - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); + c->outgoing->ai = NULL; + goto begin; + } - goto begin; - } + memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); + c->outgoing->aip = c->outgoing->aip->ai_next; - finish_connecting(c); - return; -cp +connect: + + if(c->hostname) { + free(c->hostname); + } + + c->hostname = sockaddr2hostname(&c->address); + + ifdebug(CONNECTIONS) logger(LOG_INFO, "Trying to connect to %s (%s)", c->name, + c->hostname); + + if(!proxytype) { + c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + } else if(proxytype == PROXY_EXEC) { + c->status.proxy_passed = true; + do_outgoing_pipe(c, proxyhost); + } else { + proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM); + + if(!proxyai) { + goto begin; + } + + ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport); + c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP); + } + + if(c->socket == -1) { + ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno)); + goto begin; + } + + if(proxytype != PROXY_EXEC) { + configure_tcp(c); + } + +#ifdef FD_CLOEXEC + fcntl(c->socket, F_SETFD, FD_CLOEXEC); +#endif + + if(proxytype != PROXY_EXEC) { +#if defined(IPV6_V6ONLY) + int option = 1; + + if(c->address.sa.sa_family == AF_INET6) { + setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + +#endif + + bind_to_interface(c->socket); + + int b = -1; + + for(int i = 0; i < listen_sockets; i++) { + if(listen_socket[i].sa.sa.sa_family == c->address.sa.sa_family) { + if(b == -1) { + b = i; + } else { + b = -1; + break; + } + } + } + + if(b != -1) { + sockaddr_t sa = listen_socket[b].sa; + + if(sa.sa.sa_family == AF_INET) { + sa.in.sin_port = 0; + } else if(sa.sa.sa_family == AF_INET6) { + sa.in6.sin6_port = 0; + } + + if(bind(c->socket, &sa.sa, SALEN(sa.sa))) { + char *addrstr = sockaddr2hostname(&sa); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); + free(addrstr); + } + } + } + + /* Connect */ + + if(!proxytype) { + result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); + } else if(proxytype == PROXY_EXEC) { + result = 0; + } else { + result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen); + freeaddrinfo(proxyai); + } + + now = time(NULL); + + if(result == -1) { + if(sockinprogress(sockerrno)) { + c->last_ping_time = now; + c->status.connecting = true; + return; + } + + closesocket(c->socket); + + ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno)); + + goto begin; + } + + finish_connecting(c); + + return; } -void setup_outgoing_connection(outgoing_t *outgoing) -{ - connection_t *c; - node_t *n; -cp - n = lookup_node(outgoing->name); - - if(n) - if(n->connection) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Already connected to %s"), outgoing->name); - n->connection->outgoing = outgoing; - return; - } +void setup_outgoing_connection(outgoing_t *outgoing) { + connection_t *c; + node_t *n; - c = new_connection(); - c->name = xstrdup(outgoing->name); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; - c->outcompression = myself->connection->outcompression; + outgoing->event = NULL; - init_configuration(&c->config_tree); - read_connection_config(c); - - outgoing->cfg = lookup_config(c->config_tree, "Address"); - - if(!outgoing->cfg) - { - syslog(LOG_ERR, _("No address specified for %s"), c->name); - free_connection(c); - free(outgoing->name); - free(outgoing); - return; - } - - c->outgoing = outgoing; - c->last_ping_time = now; + n = lookup_node(outgoing->name); - connection_add(c); + if(n) + if(n->connection) { + ifdebug(CONNECTIONS) logger(LOG_INFO, "Already connected to %s", outgoing->name); - do_outgoing_connection(c); + n->connection->outgoing = outgoing; + return; + } + + c = new_connection(); + c->name = xstrdup(outgoing->name); + c->outcipher = myself->connection->outcipher; + c->outdigest = myself->connection->outdigest; + c->outmaclength = myself->connection->outmaclength; + c->outcompression = myself->connection->outcompression; + + init_configuration(&c->config_tree); + + if(!read_connection_config(c)) { + free_connection(c); + outgoing->timeout = maxtimeout; + retry_outgoing(outgoing); + return; + } + + outgoing->cfg = lookup_config(c->config_tree, "Address"); + + if(!outgoing->cfg) { + logger(LOG_ERR, "No address specified for %s", c->name); + free_connection(c); + outgoing->timeout = maxtimeout; + retry_outgoing(outgoing); + return; + } + + c->outgoing = outgoing; + c->last_ping_time = now; + + connection_add(c); + + do_outgoing_connection(c); } /* accept a new tcp connect and create a new connection */ -int handle_new_meta_connection(int sock) -{ - connection_t *c; - sockaddr_t sa; - int fd, len = sizeof(sa); -cp - if((fd = accept(sock, &sa.sa, &len)) < 0) - { - syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno)); - return -1; - } +bool handle_new_meta_connection(int sock) { + static const int max_accept_burst = 10; + static int last_accept_burst; + static int last_accept_time; + connection_t *c; + sockaddr_t sa; + int fd; + socklen_t len = sizeof(sa); - sockaddrunmap(&sa); + fd = accept(sock, &sa.sa, &len); - c = new_connection(); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; - c->outcompression = myself->connection->outcompression; + if(fd < 0) { + logger(LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); + return false; + } - c->address = sa; - c->hostname = sockaddr2hostname(&sa); - c->socket = fd; - c->last_ping_time = now; + if(last_accept_time == now) { + last_accept_burst++; - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection from %s"), c->hostname); + if(last_accept_burst >= max_accept_burst) { + if(last_accept_burst == max_accept_burst) { + ifdebug(CONNECTIONS) logger(LOG_WARNING, "Throttling incoming connections"); + } - connection_add(c); + tarpit(fd); + return false; + } + } else { + last_accept_burst = 0; + last_accept_time = now; + } - c->allow_request = ID; - send_id(c); -cp - return 0; + sockaddrunmap(&sa); + + c = new_connection(); + c->name = xstrdup(""); + c->outcipher = myself->connection->outcipher; + c->outdigest = myself->connection->outdigest; + c->outmaclength = myself->connection->outmaclength; + c->outcompression = myself->connection->outcompression; + + c->address = sa; + c->hostname = sockaddr2hostname(&sa); + c->socket = fd; + c->last_ping_time = now; + + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection from %s", c->hostname); + + configure_tcp(c); + + connection_add(c); + + c->allow_request = ID; + + return true; } -void try_outgoing_connections(void) -{ - static config_t *cfg = NULL; - char *name; - outgoing_t *outgoing; -cp - for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) - { - get_config_string(cfg, &name); +static void free_outgoing(outgoing_t *outgoing) { + if(outgoing->ai) { + freeaddrinfo(outgoing->ai); + } - if(check_id(name)) - { - syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line); - free(name); - continue; - } + if(outgoing->name) { + free(outgoing->name); + } - outgoing = xmalloc_and_zero(sizeof(*outgoing)); - outgoing->name = name; - setup_outgoing_connection(outgoing); - } + free(outgoing); +} + +void try_outgoing_connections(void) { + static config_t *cfg = NULL; + char *name; + outgoing_t *outgoing; + + outgoing_list = list_alloc((list_action_t)free_outgoing); + + for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) { + get_config_string(cfg, &name); + + if(!check_id(name)) { + logger(LOG_ERR, + "Invalid name for outgoing connection in %s line %d", + cfg->file, cfg->line); + free(name); + continue; + } + + outgoing = xmalloc_and_zero(sizeof(*outgoing)); + outgoing->name = name; + list_insert_tail(outgoing_list, outgoing); + setup_outgoing_connection(outgoing); + } } diff --git a/src/netutl.c b/src/netutl.c index 20d3809..abe3d87 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -1,7 +1,7 @@ /* netutl.c -- some supporting network utility code - Copyright (C) 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans + 2000-2016 Guus Sliepen 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 @@ -13,234 +13,335 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: netutl.c,v 1.12.4.34 2002/04/05 09:11:38 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "errno.h" -#include "conf.h" -#include "net.h" -#include "netutl.h" - #include "system.h" -int hostnames = 0; +#include "net.h" +#include "netutl.h" +#include "logger.h" +#include "utils.h" +#include "xalloc.h" + +bool hostnames = false; /* Turn a string into a struct addrinfo. Return NULL on failure. */ -struct addrinfo *str2addrinfo(char *address, char *service, int socktype) -{ - struct addrinfo hint, *ai; - int err; -cp - memset(&hint, 0, sizeof(hint)); +struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) { + struct addrinfo *ai = NULL, hint = {0}; + int err; - hint.ai_family = addressfamily; - hint.ai_socktype = socktype; + hint.ai_family = addressfamily; + hint.ai_socktype = socktype; - if((err = getaddrinfo(address, service, &hint, &ai))) - { - if(debug_lvl >= DEBUG_ERROR) - syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err)); - cp_trace(); - return NULL; - } - -cp - return ai; -} - -sockaddr_t str2sockaddr(char *address, char *port) -{ - struct addrinfo hint, *ai; - sockaddr_t result; - int err; -cp - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = AF_UNSPEC; - hint.ai_flags = AI_NUMERICHOST; - hint.ai_socktype = SOCK_STREAM; - - if((err = getaddrinfo(address, port, &hint, &ai) || !ai)) - { - syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err)); - cp_trace(); - raise(SIGFPE); - exit(0); - } - - result = *(sockaddr_t *)ai->ai_addr; - freeaddrinfo(ai); -cp - return result; -} - -void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr) -{ - char address[NI_MAXHOST]; - char port[NI_MAXSERV]; - char *scopeid; - int err; -cp - if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV))) - { - syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err)); - cp_trace(); - raise(SIGFPE); - exit(0); - } - -#ifdef HAVE_LINUX - if((scopeid = strchr(address, '%'))) - *scopeid = '\0'; /* Descope. */ +#if HAVE_DECL_RES_INIT + // ensure glibc reloads /etc/resolv.conf. + res_init(); #endif + err = getaddrinfo(address, service, &hint, &ai); - *addrstr = xstrdup(address); - *portstr = xstrdup(port); -cp + if(err) { + logger(LOG_WARNING, "Error looking up %s port %s: %s", address, + service, gai_strerror(err)); + return NULL; + } + + return ai; } -char *sockaddr2hostname(sockaddr_t *sa) -{ - char *str; - char address[NI_MAXHOST] = "unknown"; - char port[NI_MAXSERV] = "unknown"; - int err; -cp - if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV)))) - { - syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err)); - } +sockaddr_t str2sockaddr(const char *address, const char *port) { + struct addrinfo *ai = NULL, hint = {0}; + sockaddr_t result; + int err; - asprintf(&str, _("%s port %s"), address, port); -cp - return str; + hint.ai_family = AF_UNSPEC; + hint.ai_flags = AI_NUMERICHOST; + hint.ai_socktype = SOCK_STREAM; + + err = getaddrinfo(address, port, &hint, &ai); + + if(err || !ai) { + ifdebug(SCARY_THINGS) + logger(LOG_DEBUG, "Unknown type address %s port %s", address, port); + result.sa.sa_family = AF_UNKNOWN; + result.unknown.address = xstrdup(address); + result.unknown.port = xstrdup(port); + return result; + } + + memcpy(&result, ai->ai_addr, ai->ai_addrlen); + freeaddrinfo(ai); + + return result; } -int sockaddrcmp(sockaddr_t *a, sockaddr_t *b) -{ - int result; -cp - result = a->sa.sa_family - b->sa.sa_family; - - if(result) - return result; - - switch(a->sa.sa_family) - { - case AF_UNSPEC: - return 0; - case AF_INET: - result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); - if(result) - return result; - return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port)); - case AF_INET6: - result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); - if(result) - return result; - return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port)); - default: - syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family); - cp_trace(); - raise(SIGFPE); - exit(0); - } -cp +void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) { + char address[NI_MAXHOST]; + char port[NI_MAXSERV]; + char *scopeid; + int err; + + if(sa->sa.sa_family == AF_UNKNOWN) { + if(addrstr) { + *addrstr = xstrdup(sa->unknown.address); + } + + if(portstr) { + *portstr = xstrdup(sa->unknown.port); + } + + return; + } + + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + if(err) { + logger(LOG_ERR, "Error while translating addresses: %s", + gai_strerror(err)); + abort(); + } + + scopeid = strchr(address, '%'); + + if(scopeid) { + *scopeid = '\0'; /* Descope. */ + } + + if(addrstr) { + *addrstr = xstrdup(address); + } + + if(portstr) { + *portstr = xstrdup(port); + } } -void sockaddrunmap(sockaddr_t *sa) -{ - if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr)) - { - sa->in.sin_addr.s_addr = ((uint32_t *)&sa->in6.sin6_addr)[3]; - sa->in.sin_family = AF_INET; - } +char *sockaddr2hostname(const sockaddr_t *sa) { + char *str; + char address[NI_MAXHOST] = "unknown"; + char port[NI_MAXSERV] = "unknown"; + int err; + + if(sa->sa.sa_family == AF_UNKNOWN) { + xasprintf(&str, "%s port %s", sa->unknown.address, sa->unknown.port); + return str; + } + + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), + hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); + + if(err) { + logger(LOG_ERR, "Error while looking up hostname: %s", + gai_strerror(err)); + } + + xasprintf(&str, "%s port %s", address, port); + + return str; +} + +int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) { + int result; + + result = a->sa.sa_family - b->sa.sa_family; + + if(result) { + return result; + } + + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; + + case AF_UNKNOWN: + return strcmp(a->unknown.address, b->unknown.address); + + case AF_INET: + return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); + + case AF_INET6: + return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + + default: + logger(LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); + } +} + +int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { + int result; + + result = a->sa.sa_family - b->sa.sa_family; + + if(result) { + return result; + } + + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; + + case AF_UNKNOWN: + result = strcmp(a->unknown.address, b->unknown.address); + + if(result) { + return result; + } + + return strcmp(a->unknown.port, b->unknown.port); + + case AF_INET: + result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); + + if(result) { + return result; + } + + return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port)); + + case AF_INET6: + result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + + if(result) { + return result; + } + + return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port)); + + default: + logger(LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); + } +} + +void sockaddrcpy(sockaddr_t *a, const sockaddr_t *b) { + if(b->sa.sa_family != AF_UNKNOWN) { + *a = *b; + } else { + a->unknown.family = AF_UNKNOWN; + a->unknown.address = xstrdup(b->unknown.address); + a->unknown.port = xstrdup(b->unknown.port); + } +} + +void sockaddrfree(sockaddr_t *a) { + if(a->sa.sa_family == AF_UNKNOWN) { + free(a->unknown.address); + free(a->unknown.port); + } +} + +void sockaddrunmap(sockaddr_t *sa) { + if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr)) { + sa->in.sin_addr.s_addr = ((uint32_t *) & sa->in6.sin6_addr)[3]; + sa->in.sin_family = AF_INET; + } +} + +void sockaddr_setport(sockaddr_t *sa, const char *port) { + uint16_t portnum = htons(atoi(port)); + + if(!portnum) { + return; + } + + switch(sa->sa.sa_family) { + case AF_INET: + sa->in.sin_port = portnum; + break; + + case AF_INET6: + sa->in6.sin6_port = portnum; + break; + + case AF_UNKNOWN: + free(sa->unknown.port); + sa->unknown.port = xstrdup(port); + + default: + return; + } } /* Subnet mask handling */ -int maskcmp(char *a, char *b, int masklen, int len) -{ - int i, m, result; -cp - for(m = masklen, i = 0; m >= 8; m -= 8, i++) - if((result = a[i] - b[i])) - return result; +int maskcmp(const void *va, const void *vb, int masklen) { + int i, m, result; + const char *a = va; + const char *b = vb; - if(m) - return (a[i] & (0x100 - (1 << (8 - m)))) - (b[i] & (0x100 - (1 << (8 - m)))); + for(m = masklen, i = 0; m >= 8; m -= 8, i++) { + result = a[i] - b[i]; - return 0; + if(result) { + return result; + } + } + + if(m) + return (a[i] & (0x100 - (1 << (8 - m)))) - + (b[i] & (0x100 - (1 << (8 - m)))); + + return 0; } -void mask(char *a, int masklen, int len) -{ - int i; -cp - i = masklen / 8; - masklen %= 8; - - if(masklen) - a[i++] &= (0x100 - (1 << masklen)); - - for(; i < len; i++) - a[i] = 0; +void mask(void *va, int masklen, int len) { + int i; + char *a = va; + + i = masklen / 8; + masklen %= 8; + + if(masklen) { + a[i++] &= (0x100 - (1 << (8 - masklen))); + } + + for(; i < len; i++) { + a[i] = 0; + } } -void maskcpy(char *a, char *b, int masklen, int len) -{ - int i, m; -cp - for(m = masklen, i = 0; m >= 8; m -= 8, i++) - a[i] = b[i]; +void maskcpy(void *va, const void *vb, int masklen, int len) { + int i, m; + char *a = va; + const char *b = vb; - if(m) - { - a[i] = b[i] & (0x100 - (1 << m)); - i++; - } + for(m = masklen, i = 0; m >= 8; m -= 8, i++) { + a[i] = b[i]; + } - for(; i < len; i++) - a[i] = 0; + if(m) { + a[i] = b[i] & (0x100 - (1 << (8 - m))); + i++; + } + + for(; i < len; i++) { + a[i] = 0; + } } -int maskcheck(char *a, int masklen, int len) -{ - int i; -cp - i = masklen / 8; - masklen %= 8; - - if(masklen) - if(a[i++] & (char)~(0x100 - (1 << masklen))) - return -1; - - for(; i < len; i++) - if(a[i] != 0) - return -1; +bool maskcheck(const void *va, int masklen, int len) { + int i; + const char *a = va; - return 0; + i = masklen / 8; + masklen %= 8; + + if(masklen && a[i++] & (0xff >> masklen)) { + return false; + } + + for(; i < len; i++) + if(a[i] != 0) { + return false; + } + + return true; } diff --git a/src/netutl.h b/src/netutl.h index 654d7ad..cc3ccab 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -1,7 +1,10 @@ +#ifndef TINC_NETUTL_H +#define TINC_NETUTL_H + /* netutl.h -- header file for netutl.c - Copyright (C) 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans + 2000-2016 Guus Sliepen 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 @@ -13,34 +16,28 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: netutl.h,v 1.2.4.11 2002/03/17 15:59:29 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NETUTL_H__ -#define __TINC_NETUTL_H__ - -#include -#include -#include - #include "net.h" -extern int hostnames; +extern bool hostnames; -extern char *hostlookup(unsigned long); -extern struct addrinfo *str2addrinfo(char *, char *, int); -extern sockaddr_t str2sockaddr(char *, char *); -extern void sockaddr2str(sockaddr_t *, char **, char **); -extern char *sockaddr2hostname(sockaddr_t *); -extern int sockaddrcmp(sockaddr_t *, sockaddr_t *); -extern void sockaddrunmap(sockaddr_t *); -extern int maskcmp(char *, char *, int, int); -extern void maskcpy(char *, char *, int, int); -extern void mask(char *, int, int); -extern int maskcheck(char *, int, int); +extern struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype); +extern sockaddr_t str2sockaddr(const char *address, const char *port); +extern void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr); +extern char *sockaddr2hostname(const sockaddr_t *sa); +extern int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b); +extern int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b); +extern void sockaddrunmap(sockaddr_t *sa); +extern void sockaddrfree(sockaddr_t *sa); +extern void sockaddrcpy(sockaddr_t *dest, const sockaddr_t *src); +extern void sockaddr_setport(sockaddr_t *sa, const char *port); +extern int maskcmp(const void *a, const void *b, int masklen); +extern void maskcpy(void *dest, const void *src, int masklen, int len); +extern void mask(void *mask, int masklen, int len); +extern bool maskcheck(const void *mask, int masklen, int len); -#endif /* __TINC_NETUTL_H__ */ +#endif diff --git a/src/node.c b/src/node.c index e4581cc..03be21c 100644 --- a/src/node.c +++ b/src/node.c @@ -1,7 +1,7 @@ /* node.c -- node tree management - Copyright (C) 2001-2002 Guus Sliepen , - 2001-2002 Ivo Timmermans + Copyright (C) 2001-2016 Guus Sliepen , + 2001-2005 Ivo Timmermans 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 @@ -13,161 +13,187 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: node.c,v 1.1.2.11 2002/03/22 13:31:18 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include - -#include -#include "node.h" -#include "netutl.h" -#include "net.h" -#include -#include - #include "system.h" -avl_tree_t *node_tree; /* Known nodes, sorted by name */ -avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */ +#include "avl_tree.h" +#include "logger.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "utils.h" +#include "xalloc.h" + +avl_tree_t *node_tree; /* Known nodes, sorted by name */ +avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */ node_t *myself; -int node_compare(node_t *a, node_t *b) -{ - return strcmp(a->name, b->name); +static int node_compare(const node_t *a, const node_t *b) { + return strcmp(a->name, b->name); } -int node_udp_compare(node_t *a, node_t *b) -{ - int result; -cp - result = sockaddrcmp(&a->address, &b->address); - - if(result) - return result; - - return (a->name && b->name)?strcmp(a->name, b->name):0; +static int node_udp_compare(const node_t *a, const node_t *b) { + return sockaddrcmp(&a->address, &b->address); } -void init_nodes(void) -{ -cp - node_tree = avl_alloc_tree((avl_compare_t)node_compare, NULL); - node_udp_tree = avl_alloc_tree((avl_compare_t)node_udp_compare, NULL); -cp +void init_nodes(void) { + node_tree = avl_alloc_tree((avl_compare_t) node_compare, (avl_action_t) free_node); + node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL); } -void exit_nodes(void) -{ -cp - avl_delete_tree(node_tree); - avl_delete_tree(node_udp_tree); -cp +void exit_nodes(void) { + avl_delete_tree(node_udp_tree); + avl_delete_tree(node_tree); } -node_t *new_node(void) -{ - node_t *n = (node_t *)xmalloc_and_zero(sizeof(*n)); -cp - n->subnet_tree = new_subnet_tree(); - n->edge_tree = new_edge_tree(); - n->queue = list_alloc((list_action_t)free); -cp - return n; +node_t *new_node(void) { + node_t *n = xmalloc_and_zero(sizeof(*n)); + + if(replaywin) { + n->late = xmalloc_and_zero(replaywin); + } + + n->subnet_tree = new_subnet_tree(); + n->edge_tree = new_edge_tree(); + n->inctx = EVP_CIPHER_CTX_new(); + n->outctx = EVP_CIPHER_CTX_new(); + + if(!n->inctx || !n->outctx) { + abort(); + } + + n->mtu = MTU; + n->maxmtu = MTU; + + return n; } -void free_node(node_t *n) -{ -cp - if(n->queue) - list_delete_list(n->queue); - if(n->name) - free(n->name); - if(n->hostname) - free(n->hostname); - if(n->key) - free(n->key); - if(n->subnet_tree) - free_subnet_tree(n->subnet_tree); - if(n->edge_tree) - free_edge_tree(n->edge_tree); - free(n); -cp +void free_node(node_t *n) { + if(n->inkey) { + free(n->inkey); + } + + if(n->outkey) { + free(n->outkey); + } + + if(n->subnet_tree) { + free_subnet_tree(n->subnet_tree); + } + + if(n->edge_tree) { + free_edge_tree(n->edge_tree); + } + + sockaddrfree(&n->address); + + EVP_CIPHER_CTX_free(n->outctx); + EVP_CIPHER_CTX_free(n->inctx); + + if(n->mtuevent) { + event_del(n->mtuevent); + } + + if(n->hostname) { + free(n->hostname); + } + + if(n->name) { + free(n->name); + } + + if(n->late) { + free(n->late); + } + + free(n); } -void node_add(node_t *n) -{ -cp - avl_insert(node_tree, n); - avl_insert(node_udp_tree, n); -cp +void node_add(node_t *n) { + avl_insert(node_tree, n); } -void node_del(node_t *n) -{ - avl_node_t *node, *next; - edge_t *e; - subnet_t *s; -cp - for(node = n->subnet_tree->head; node; node = next) - { - next = node->next; - s = (subnet_t *)node->data; - subnet_del(n, s); - } +void node_del(node_t *n) { + avl_node_t *node, *next; + edge_t *e; + subnet_t *s; - for(node = n->subnet_tree->head; node; node = next) - { - next = node->next; - e = (edge_t *)node->data; - edge_del(e); - } -cp - avl_delete(node_tree, n); - avl_delete(node_udp_tree, n); -cp + for(node = n->subnet_tree->head; node; node = next) { + next = node->next; + s = node->data; + subnet_del(n, s); + } + + for(node = n->edge_tree->head; node; node = next) { + next = node->next; + e = node->data; + edge_del(e); + } + + avl_delete(node_udp_tree, n); + avl_delete(node_tree, n); } -node_t *lookup_node(char *name) -{ - node_t n; -cp - n.name = name; - return avl_search(node_tree, &n); +node_t *lookup_node(char *name) { + node_t n = {0}; + + n.name = name; + + return avl_search(node_tree, &n); } -node_t *lookup_node_udp(sockaddr_t *sa) -{ - node_t n; -cp - n.address = *sa; - n.name = NULL; +node_t *lookup_node_udp(const sockaddr_t *sa) { + node_t n = {0}; - return avl_search(node_udp_tree, &n); + n.address = *sa; + n.name = NULL; + + return avl_search(node_udp_tree, &n); } -void dump_nodes(void) -{ - avl_node_t *node; - node_t *n; -cp - syslog(LOG_DEBUG, _("Nodes:")); +void update_node_udp(node_t *n, const sockaddr_t *sa) { + if(n == myself) { + logger(LOG_WARNING, "Trying to update UDP address of myself!"); + return; + } - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"), - n->name, n->hostname, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options, - n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-"); - } - - syslog(LOG_DEBUG, _("End of nodes.")); -cp + avl_delete(node_udp_tree, n); + + if(n->hostname) { + free(n->hostname); + } + + if(sa) { + n->address = *sa; + n->hostname = sockaddr2hostname(&n->address); + avl_insert(node_udp_tree, n); + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); + } else { + memset(&n->address, 0, sizeof(n->address)); + n->hostname = NULL; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name); + } +} + +void dump_nodes(void) { + avl_node_t *node; + node_t *n; + + logger(LOG_DEBUG, "Nodes:"); + + for(node = node_tree->head; node; node = node->next) { + n = node->data; + logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s pmtu %d (min %d max %d)", + n->name, n->hostname, n->outcipher ? EVP_CIPHER_nid(n->outcipher) : 0, + n->outdigest ? EVP_MD_type(n->outdigest) : 0, n->outmaclength, n->outcompression, + n->options, bitfield_to_int(&n->status, sizeof(n->status)), n->nexthop ? n->nexthop->name : "-", + n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu); + } + + logger(LOG_DEBUG, "End of nodes."); } diff --git a/src/node.h b/src/node.h index 98147d3..b360fe5 100644 --- a/src/node.h +++ b/src/node.h @@ -1,7 +1,10 @@ +#ifndef TINC_NODE_H +#define TINC_NODE_H + /* node.h -- header for node.c - Copyright (C) 2001-2002 Guus Sliepen , - 2001-2002 Ivo Timmermans + Copyright (C) 2001-2016 Guus Sliepen , + 2001-2005 Ivo Timmermans 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 @@ -13,62 +16,76 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: node.h,v 1.1.2.13 2002/03/19 22:48:25 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NODE_H__ -#define __TINC_NODE_H__ - -#include - -#include "subnet.h" +#include "avl_tree.h" #include "connection.h" +#include "event.h" +#include "subnet.h" typedef struct node_status_t { - int active:1; /* 1 if active.. */ - int validkey:1; /* 1 if we currently have a valid key for him */ - int waitingforkey:1; /* 1 if we already sent out a request */ - int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ - int reachable:1; /* 1 if this node is reachable in the graph */ - int indirect:1; /* 1 if this node is not directly reachable by us */ - int unused:26; + unsigned int unused_active: 1; /* 1 if active (not used for nodes) */ + unsigned int validkey: 1; /* 1 if we currently have a valid key for him */ + unsigned int unused_waitingforkey: 1; /* 1 if we already sent out a request */ + unsigned int visited: 1; /* 1 if this node has been visited by one of the graph algorithms */ + unsigned int reachable: 1; /* 1 if this node is reachable in the graph */ + unsigned int indirect: 1; /* 1 if this node is not directly reachable by us */ + unsigned int unused: 26; } node_status_t; typedef struct node_t { - char *name; /* name of this node */ - long int options; /* options turned on for this node */ + char *name; /* name of this node */ + uint32_t options; /* options turned on for this node */ - sockaddr_t address; /* his real (internet) ip to send UDP packets to */ - char *hostname; /* the hostname of its real ip */ + int sock; /* Socket to use for outgoing UDP packets */ + sockaddr_t address; /* his real (internet) ip to send UDP packets to */ + char *hostname; /* the hostname of its real ip */ - struct node_status_t status; + node_status_t status; + time_t last_req_key; - const EVP_CIPHER *cipher; /* Cipher type for UDP packets */ - char *key; /* Cipher key and iv */ - int keylength; /* Cipher key and iv length*/ + const EVP_CIPHER *incipher; /* Cipher type for UDP packets received from him */ + char *inkey; /* Cipher key and iv */ + int inkeylength; /* Cipher key and iv length */ + EVP_CIPHER_CTX *inctx; /* Cipher context */ - const EVP_MD *digest; /* Digest type for MAC */ - int maclength; /* Length of MAC */ + const EVP_CIPHER *outcipher; /* Cipher type for UDP packets sent to him*/ + char *outkey; /* Cipher key and iv */ + int outkeylength; /* Cipher key and iv length */ + EVP_CIPHER_CTX *outctx; /* Cipher context */ - int compression; /* Compressionlevel, 0 = no compression */ + const EVP_MD *indigest; /* Digest type for MAC of packets received from him */ + int inmaclength; /* Length of MAC */ - list_t *queue; /* Queue for packets awaiting to be encrypted */ + const EVP_MD *outdigest; /* Digest type for MAC of packets sent to him*/ + int outmaclength; /* Length of MAC */ - struct node_t *nexthop; /* nearest node from us to him */ - struct node_t *via; /* next hop for UDP packets */ - - avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */ + int incompression; /* Compressionlevel, 0 = no compression */ + int outcompression; /* Compressionlevel, 0 = no compression */ - avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ + struct node_t *nexthop; /* nearest node from us to him */ + struct edge_t *prevedge; /* nearest node from him to us */ + struct node_t *via; /* next hop for UDP packets */ - struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ + avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */ - unsigned int sent_seqno; /* Sequence number last sent to this node */ - unsigned int received_seqno; /* Sequence number last received from this node */ + avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ + + struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ + + uint32_t sent_seqno; /* Sequence number last sent to this node */ + uint32_t received_seqno; /* Sequence number last received from this node */ + uint32_t farfuture; /* Packets in a row that have arrived from the far future */ + unsigned char *late; /* Bitfield marking late packets */ + + length_t mtu; /* Maximum size of packets to send to this node */ + length_t minmtu; /* Probed minimum MTU */ + length_t maxmtu; /* Probed maximum MTU */ + int mtuprobes; /* Number of probes */ + event_t *mtuevent; /* Probe event */ } node_t; extern struct node_t *myself; @@ -77,12 +94,13 @@ extern avl_tree_t *node_udp_tree; extern void init_nodes(void); extern void exit_nodes(void); -extern node_t *new_node(void); -extern void free_node(node_t *); -extern void node_add(node_t *); -extern void node_del(node_t *); -extern node_t *lookup_node(char *); -extern node_t *lookup_node_udp(sockaddr_t *); +extern node_t *new_node(void) __attribute__((__malloc__)); +extern void free_node(node_t *n); +extern void node_add(node_t *n); +extern void node_del(node_t *n); +extern node_t *lookup_node(char *name); +extern node_t *lookup_node_udp(const sockaddr_t *sa); +extern void update_node_udp(node_t *n, const sockaddr_t *sa); extern void dump_nodes(void); -#endif /* __TINC_NODE_H__ */ +#endif diff --git a/src/openbsd/device.c b/src/openbsd/device.c deleted file mode 100644 index 3d7099f..0000000 --- a/src/openbsd/device.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - device.c -- Interaction with OpenBSD tun device - Copyright (C) 2001-2002 Ivo Timmermans , - 2001-2002 Guus Sliepen - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.c,v 1.1.2.8 2002/03/27 16:00:38 guus Exp $ -*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "conf.h" -#include "net.h" -#include "subnet.h" - -#include "system.h" - -#define DEFAULT_DEVICE "/dev/tun0" - -#define DEVICE_TYPE_ETHERTAP 0 -#define DEVICE_TYPE_TUNTAP 1 - -int device_fd = -1; -int device_type; -char *device; -char *interface; -char *device_info; - -int device_total_in = 0; -int device_total_out = 0; - -extern subnet_t mymac; - -/* - open the local ethertap device -*/ -int setup_device(void) -{ - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("OpenBSD tun device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; -} - -void close_device(void) -{ -cp - close(device_fd); -cp -} - -int read_packet(vpn_packet_t *packet) -{ - int lenin; - u_int32_t type; - struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, MTU - 14}}; -cp - - if((lenin = readv(device_fd, vector, 2)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - - switch(ntohl(type)) - { - case AF_INET: - packet->data[12] = 0x8; - packet->data[13] = 0x0; - break; - case AF_INET6: - packet->data[12] = 0x86; - packet->data[13] = 0xDD; - break; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Unknown address family %d while reading packet from %s %s"), ntohl(type), device_info, device); - return -1; - } - - packet->len = lenin + 10; - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } - - return 0; -cp -} - -int write_packet(vpn_packet_t *packet) -{ - u_int32_t type; - struct iovec vector[2]; - int af; -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - af = (packet->data[12] << 8) + packet->data[13]; - - switch(af) - { - case 0x800: - type = htonl(AF_INET); - break; - case 0x86DD: - type = htonl(AF_INET6); - break; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Unknown address family %d while writing packet to %s %s"), af, device_info, device); - return -1; - } - - vector[0].iov_base = &type; - vector[0].iov_len = sizeof(type); - vector[1].iov_base = packet->data + 14; - vector[1].iov_len = packet->len - 14; - - if(writev(device_fd, vector, 2) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} - -void dump_device_stats(void) -{ -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} diff --git a/src/pidfile.c b/src/pidfile.c new file mode 100644 index 0000000..dd17267 --- /dev/null +++ b/src/pidfile.c @@ -0,0 +1,142 @@ +/* + pidfile.c - interact with pidfiles + Copyright (c) 1995 Martin Schulze + + This file is part of the sysklogd package, a kernel and system log daemon. + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* left unaltered for tinc -- Ivo Timmermans */ +/* + * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze + * First version (v0.2) released + */ + +#include "system.h" + +#include "pidfile.h" + +#ifndef HAVE_MINGW +/* read_pid + * + * Reads the specified pidfile and returns the read pid. + * 0 is returned if either there's no pidfile, it's empty + * or no pid can be read. + */ +pid_t read_pid(const char *pidfile) { + FILE *f; + long pid; + + if(!(f = fopen(pidfile, "r"))) { + return 0; + } + + if(fscanf(f, "%20ld", &pid) != 1) { + pid = 0; + } + + fclose(f); + return (pid_t)pid; +} + +/* check_pid + * + * Reads the pid using read_pid and looks up the pid in the process + * table (using /proc) to determine if the process already exists. If + * so the pid is returned, otherwise 0. + */ +pid_t check_pid(const char *pidfile) { + pid_t pid = read_pid(pidfile); + + /* Amazing ! _I_ am already holding the pid file... */ + if((!pid) || (pid == getpid())) { + return 0; + } + + /* + * The 'standard' method of doing this is to try and do a 'fake' kill + * of the process. If an ESRCH error is returned the process cannot + * be found -- GW + */ + /* But... errno is usually changed only on error.. */ + errno = 0; + + if(kill(pid, 0) && errno == ESRCH) { + return 0; + } + + return pid; +} + +/* write_pid + * + * Writes the pid to the specified file. If that fails 0 is + * returned, otherwise the pid. + */ +pid_t write_pid(const char *pidfile) { + FILE *f; + int fd; + pid_t pid; + + if((fd = open(pidfile, O_RDWR | O_CREAT, 0644)) == -1) { + return 0; + } + + if((f = fdopen(fd, "r+")) == NULL) { + close(fd); + return 0; + } + +#ifdef HAVE_FLOCK + + if(flock(fd, LOCK_EX | LOCK_NB) == -1) { + fclose(f); + return 0; + } + +#endif + + pid = getpid(); + + if(!fprintf(f, "%ld\n", (long)pid)) { + fclose(f); + return 0; + } + + fflush(f); + +#ifdef HAVE_FLOCK + + if(flock(fd, LOCK_UN) == -1) { + fclose(f); + return 0; + } + +#endif + fclose(f); + + return pid; +} + +/* remove_pid + * + * Remove the the specified file. The result from unlink(2) + * is returned + */ +int remove_pid(const char *pidfile) { + return unlink(pidfile); +} +#endif diff --git a/lib/pidfile.h b/src/pidfile.h similarity index 76% rename from lib/pidfile.h rename to src/pidfile.h index 19d19c1..7d71cc2 100644 --- a/lib/pidfile.h +++ b/src/pidfile.h @@ -1,3 +1,6 @@ +#ifndef TINC_PIDFILE_H +#define TINC_PIDFILE_H + /* pidfile.h - interact with pidfiles Copyright (c) 1995 Martin Schulze @@ -14,18 +17,19 @@ 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, USA. + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifndef HAVE_MINGW /* read_pid * * Reads the specified pidfile and returns the read pid. * 0 is returned if either there's no pidfile, it's empty * or no pid can be read. */ -int read_pid (char *pidfile); +extern pid_t read_pid(const char *pidfile); /* check_pid * @@ -33,18 +37,21 @@ int read_pid (char *pidfile); * table (using /proc) to determine if the process already exists. If * so 1 is returned, otherwise 0. */ -int check_pid (char *pidfile); +extern pid_t check_pid(const char *pidfile); /* write_pid * * Writes the pid to the specified file. If that fails 0 is * returned, otherwise the pid. */ -int write_pid (char *pidfile); +extern pid_t write_pid(const char *pidfile); /* remove_pid * * Remove the the specified file. The result from unlink(2) * is returned */ -int remove_pid (char *pidfile); +extern int remove_pid(const char *pidfile); +#endif + +#endif diff --git a/src/process.c b/src/process.c index bdd81e3..13d1007 100644 --- a/src/process.c +++ b/src/process.c @@ -1,7 +1,7 @@ /* process.c -- process management functions - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2015 Guus Sliepen 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 @@ -13,308 +13,489 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: process.c,v 1.1.2.39 2002/03/26 12:00:38 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conf.h" -#include "process.h" -#include "subnet.h" -#include "device.h" -#include "connection.h" -#include "device.h" - #include "system.h" +#include "conf.h" +#include "connection.h" +#include "device.h" +#include "edge.h" +#include "logger.h" +#include "net.h" +#include "node.h" +#include "pidfile.h" +#include "process.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" + /* If zero, don't detach from the terminal. */ -int do_detach = 1; +bool do_detach = true; +bool sighup = false; +bool sigalrm = false; extern char *identname; extern char *pidfilename; extern char **g_argv; +extern bool use_logfile; -sigset_t emptysigset; - -static int saved_debug_lvl = 0; - -extern int sighup; -extern int sigalrm; -extern int do_purge; - -void memory_full(int size) -{ - syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size); - cp_trace(); - exit(1); -} +#ifndef HAVE_MINGW +static sigset_t emptysigset; +#endif /* Some functions the less gifted operating systems might lack... */ -#ifndef HAVE_FCLOSEALL -int fcloseall(void) -{ - fflush(stdin); - fflush(stdout); - fflush(stderr); - fclose(stdin); - fclose(stdout); - fclose(stderr); - return 0; +#ifdef HAVE_MINGW +extern char *identname; +extern char *program_name; +extern char **g_argv; + +static SC_HANDLE manager = NULL; +static SC_HANDLE service = NULL; +static SERVICE_STATUS status = {0}; +static SERVICE_STATUS_HANDLE statushandle = 0; + +bool install_service(void) { + char command[4096] = "\""; + char **argp; + bool space; + SERVICE_DESCRIPTION description = {"Virtual Private Network daemon"}; + + manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if(!manager) { + logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError())); + return false; + } + + if(!strchr(program_name, '\\')) { + GetCurrentDirectory(sizeof(command) - 1, command + 1); + strncat(command, "\\", sizeof(command) - strlen(command)); + } + + strncat(command, program_name, sizeof(command) - strlen(command)); + + strncat(command, "\"", sizeof(command) - strlen(command)); + + for(argp = g_argv + 1; *argp; argp++) { + space = strchr(*argp, ' '); + strncat(command, " ", sizeof(command) - strlen(command)); + + if(space) { + strncat(command, "\"", sizeof(command) - strlen(command)); + } + + strncat(command, *argp, sizeof(command) - strlen(command)); + + if(space) { + strncat(command, "\"", sizeof(command) - strlen(command)); + } + } + + service = CreateService(manager, identname, identname, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, + command, NULL, NULL, NULL, NULL, NULL); + + if(!service) { + DWORD lasterror = GetLastError(); + logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror)); + + if(lasterror != ERROR_SERVICE_EXISTS) { + return false; + } + } + + if(service) { + ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description); + logger(LOG_INFO, "%s service installed", identname); + } else { + service = OpenService(manager, identname, SERVICE_ALL_ACCESS); + } + + if(!StartService(service, 0, NULL)) { + logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError())); + } else { + logger(LOG_INFO, "%s service started", identname); + } + + return true; +} + +bool remove_service(void) { + manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if(!manager) { + logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError())); + return false; + } + + service = OpenService(manager, identname, SERVICE_ALL_ACCESS); + + if(!service) { + logger(LOG_ERR, "Could not open %s service: %s", identname, winerror(GetLastError())); + return false; + } + + if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) { + logger(LOG_ERR, "Could not stop %s service: %s", identname, winerror(GetLastError())); + } else { + logger(LOG_INFO, "%s service stopped", identname); + } + + if(!DeleteService(service)) { + logger(LOG_ERR, "Could not remove %s service: %s", identname, winerror(GetLastError())); + return false; + } + + logger(LOG_INFO, "%s service removed", identname); + + return true; +} + +DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) { + switch(request) { + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus(statushandle, &status); + return NO_ERROR; + + case SERVICE_CONTROL_STOP: + logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_STOP"); + break; + + case SERVICE_CONTROL_SHUTDOWN: + logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN"); + break; + + default: + logger(LOG_WARNING, "Got unexpected request %d", (int)request); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if(running) { + running = false; + status.dwWaitHint = 30000; + status.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(statushandle, &status); + return NO_ERROR; + } else { + status.dwWaitHint = 0; + status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(statushandle, &status); + exit(1); + } + +} + +VOID WINAPI run_service(DWORD argc, LPTSTR *argv) { + extern int main2(int argc, char **argv); + + status.dwServiceType = SERVICE_WIN32; + status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + status.dwWin32ExitCode = 0; + status.dwServiceSpecificExitCode = 0; + status.dwCheckPoint = 0; + + statushandle = RegisterServiceCtrlHandlerEx(identname, controlhandler, NULL); + + if(!statushandle) { + logger(LOG_ERR, "System call `%s' failed: %s", "RegisterServiceCtrlHandlerEx", winerror(GetLastError())); + } else { + status.dwWaitHint = 30000; + status.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(statushandle, &status); + + status.dwWaitHint = 0; + status.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(statushandle, &status); + + main2(argc, argv); + + status.dwWaitHint = 0; + status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(statushandle, &status); + } + + return; +} + +bool init_service(void) { + SERVICE_TABLE_ENTRY services[] = { + {identname, run_service}, + {NULL, NULL} + }; + + if(!StartServiceCtrlDispatcher(services)) { + if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { + return false; + } else { + logger(LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError())); + } + } + + return true; +} +#endif + +#ifndef HAVE_MINGW +/* + check for an existing tinc for this net, and write pid to pidfile +*/ +static bool write_pidfile(void) { + pid_t pid; + + pid = check_pid(pidfilename); + + if(pid) { + if(netname) + fprintf(stderr, "A tincd is already running for net `%s' with pid %ld.\n", + netname, (long)pid); + else { + fprintf(stderr, "A tincd is already running with pid %ld.\n", (long)pid); + } + + return false; + } + + /* if it's locked, write-protected, or whatever */ + if(!write_pid(pidfilename)) { + fprintf(stderr, "Couldn't write pid file %s: %s\n", pidfilename, strerror(errno)); + return false; + } + + return true; } #endif -/* - Close network connections, and terminate neatly -*/ -void cleanup_and_exit(int c) -{ -cp - close_network_connections(); - - if(debug_lvl > DEBUG_NOTHING) - dump_device_stats(); - - syslog(LOG_NOTICE, _("Terminating")); - - closelog(); - exit(c); -} - -/* - check for an existing tinc for this net, and write pid to pidfile -*/ -int write_pidfile(void) -{ - int pid; -cp - if((pid = check_pid(pidfilename))) - { - if(netname) - fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"), - netname, pid); - else - fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid); - return 1; - } - - /* if it's locked, write-protected, or whatever */ - if(!write_pid(pidfilename)) - return 1; -cp - return 0; -} - /* kill older tincd for this net */ -int kill_other(int signal) -{ - int pid; -cp - if(!(pid = read_pid(pidfilename))) - { - if(netname) - fprintf(stderr, _("No other tincd is running for net `%s'.\n"), netname); - else - fprintf(stderr, _("No other tincd is running.\n")); - return 1; - } +bool kill_other(int signal) { +#ifndef HAVE_MINGW + pid_t pid; - errno = 0; /* No error, sometimes errno is only changed on error */ - /* ESRCH is returned when no process with that pid is found */ - if(kill(pid, signal) && errno == ESRCH) - { - if(netname) - fprintf(stderr, _("The tincd for net `%s' is no longer running. "), netname); - else - fprintf(stderr, _("The tincd is no longer running. ")); + pid = read_pid(pidfilename); - fprintf(stderr, _("Removing stale lock file.\n")); - remove_pid(pidfilename); - } -cp - return 0; + if(!pid) { + if(netname) + fprintf(stderr, "No other tincd is running for net `%s'.\n", + netname); + else { + fprintf(stderr, "No other tincd is running.\n"); + } + + return false; + } + + errno = 0; /* No error, sometimes errno is only changed on error */ + + /* ESRCH is returned when no process with that pid is found */ + if(kill(pid, signal) && errno == ESRCH) { + if(netname) + fprintf(stderr, "The tincd for net `%s' is no longer running. ", + netname); + else { + fprintf(stderr, "The tincd is no longer running. "); + } + + fprintf(stderr, "Removing stale lock file.\n"); + remove_pid(pidfilename); + } + + return true; +#else + return remove_service(); +#endif } /* Detach from current terminal, write pidfile, kill parent */ -int detach(void) -{ -cp - setup_signals(); +bool detach(void) { + setup_signals(); - /* First check if we can open a fresh new pidfile */ - - if(write_pidfile()) - return -1; + /* First check if we can open a fresh new pidfile */ - /* If we succeeded in doing that, detach */ +#ifndef HAVE_MINGW - closelog(); - - if(do_detach) - { - if(daemon(0, 0) < 0) - { - fprintf(stderr, _("Couldn't detach from terminal: %s"), strerror(errno)); - return -1; + if(!write_pidfile()) { + return false; } - /* Now UPDATE the pid in the pidfile, because we changed it... */ - - if(!write_pid(pidfilename)) - return -1; - } - - openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); + /* If we succeeded in doing that, detach */ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), - VERSION, __DATE__, __TIME__, debug_lvl); - else - syslog(LOG_NOTICE, _("tincd %s starting"), VERSION); - - xalloc_fail_func = memory_full; -cp - return 0; -} - -/* - Execute the program name, with sane environment. All output will be - redirected to syslog. -*/ -void _execute_script(const char *scriptname) __attribute__ ((noreturn)); -void _execute_script(const char *scriptname) -{ - char *s; -cp -#ifdef HAVE_UNSETENV - unsetenv("NETNAME"); - unsetenv("DEVICE"); - unsetenv("INTERFACE"); + closelogger(); #endif - if(netname) - { - asprintf(&s, "NETNAME=%s", netname); - putenv(s); /* Don't free s! see man 3 putenv */ - } + if(do_detach) { +#ifndef HAVE_MINGW - if(device) - { - asprintf(&s, "DEVICE=%s", device); - putenv(s); /* Don't free s! see man 3 putenv */ - } + if(daemon(0, 0)) { + fprintf(stderr, "Couldn't detach from terminal: %s", + strerror(errno)); + return false; + } - if(interface) - { - asprintf(&s, "INTERFACE=%s", interface); - putenv(s); /* Don't free s! see man 3 putenv */ - } + /* Now UPDATE the pid in the pidfile, because we changed it... */ - chdir("/"); - - /* Close all file descriptors */ - closelog(); /* <- this means we cannot use syslog() here anymore! */ - fcloseall(); + if(!write_pid(pidfilename)) { + fprintf(stderr, "Could not write pid file %s: %s\n", pidfilename, strerror(errno)); + return false; + } - execl(scriptname, NULL); - /* No return on success */ - - if(errno != ENOENT) /* Ignore if the file does not exist */ - exit(1); /* Some error while trying execl(). */ - else - exit(0); +#else + + if(!statushandle) { + exit(install_service()); + } + +#endif + } + + openlogger(identname, use_logfile ? LOGMODE_FILE : (do_detach ? LOGMODE_SYSLOG : LOGMODE_STDERR)); + + logger(LOG_NOTICE, "tincd %s starting, debug level %d", + VERSION, debug_level); + + return true; } -/* - Fork and execute the program pointed to by name. -*/ -int execute_script(const char *name) -{ - pid_t pid; - int status; - struct stat s; - char *scriptname; -cp - asprintf(&scriptname, "%s/%s", confbase, name); +#ifdef HAVE_PUTENV +void unputenv(char *p) { + char *e = strchr(p, '='); - /* First check if there is a script */ + if(!e) { + return; + } - if(stat(scriptname, &s)) - return 0; + int len = e - p; +#ifndef HAVE_UNSETENV +#ifdef HAVE_MINGW + // Windows requires putenv("FOO=") to unset %FOO% + len++; +#endif +#endif + char var[len + 1]; + memcpy(var, p, len); + var[len] = 0; +#ifdef HAVE_UNSETENV + unsetenv(var); +#else + // We must keep what we putenv() around in memory. + // To do this without memory leaks, keep things in a list and reuse if possible. + static list_t list = {}; - if((pid = fork()) < 0) - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno)); - return -1; - } + for(list_node_t *node = list.head; node; node = node->next) { + char *data = node->data; - if(pid) - { - if(debug_lvl >= DEBUG_STATUS) - syslog(LOG_INFO, _("Executing script %s"), name); + if(!strcmp(data, var)) { + putenv(data); + return; + } + } - free(scriptname); + char *data = xstrdup(var); + list_insert_tail(&list, data); + putenv(data); +#endif +} +#else +void putenv(const char *p) {} +void unputenv(const char *p) {} +#endif - if(waitpid(pid, &status, 0) == pid) - { - if(WIFEXITED(status)) /* Child exited by itself */ - { - if(WEXITSTATUS(status)) - { - syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"), pid, name, WEXITSTATUS(status)); - return -1; - } - else - return 0; - } - else if(WIFSIGNALED(status)) /* Child was killed by a signal */ - { - syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), - pid, name, WTERMSIG(status), strsignal(WTERMSIG(status))); - return -1; - } - else /* Something strange happened */ - { - syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid, name); - return -1; - } - } - else - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno)); - return -1; - } - } -cp - /* Child here */ +bool execute_script(const char *name, char **envp) { +#ifdef HAVE_SYSTEM + char *scriptname; + char *interpreter = NULL; + config_t *cfg_interpreter; + int status, len, i; - _execute_script(scriptname); + cfg_interpreter = lookup_config(config_tree, "ScriptsInterpreter"); +#ifndef HAVE_MINGW + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); +#else + + if(cfg_interpreter) { + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); + } else { + len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); + } + +#endif + + if(len < 0) { + return false; + } + + scriptname[len - 1] = '\0'; + + /* First check if there is a script */ + if(access(scriptname + 1, F_OK)) { + free(scriptname); + return true; + } + + // Custom scripts interpreter + if(get_config_string(cfg_interpreter, &interpreter)) { + // Force custom scripts interpreter allowing execution of scripts on android without execution flag (such as on /sdcard) + free(scriptname); + len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name); + free(interpreter); + + if(len < 0) { + return false; + } + } + + ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name); + + /* Set environment */ + + for(i = 0; envp[i]; i++) { + putenv(envp[i]); + } + + scriptname[len - 1] = '\"'; + status = system(scriptname); + + free(scriptname); + + /* Unset environment */ + + for(i = 0; envp[i]; i++) { + unputenv(envp[i]); + } + + if(status != -1) { +#ifdef WEXITSTATUS + + if(WIFEXITED(status)) { /* Child exited by itself */ + if(WEXITSTATUS(status)) { + logger(LOG_ERR, "Script %s exited with non-zero status %d", + name, WEXITSTATUS(status)); + return false; + } + } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */ + logger(LOG_ERR, "Script %s was killed by signal %d (%s)", + name, WTERMSIG(status), strsignal(WTERMSIG(status))); + return false; + } else { /* Something strange happened */ + logger(LOG_ERR, "Script %s terminated abnormally", name); + return false; + } + +#endif + } else { + logger(LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); + return false; + } + +#endif + return true; } @@ -322,186 +503,176 @@ cp Signal handlers. */ -RETSIGTYPE -sigterm_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got TERM signal")); +#ifndef HAVE_MINGW +static RETSIGTYPE sigterm_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "TERM"); - cleanup_and_exit(0); + if(running) { + running = false; + } else { + exit(1); + } } -RETSIGTYPE -sigquit_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got QUIT signal")); - cleanup_and_exit(0); +static RETSIGTYPE sigquit_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "QUIT"); + + if(running) { + running = false; + } else { + exit(1); + } } -RETSIGTYPE -fatal_signal_square(int a) -{ - syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, strsignal(a)); - cp_trace(); - exit(1); +static RETSIGTYPE fatal_signal_square(int a) { + logger(LOG_ERR, "Got another fatal signal %d (%s): not restarting.", a, + strsignal(a)); + exit(1); } -RETSIGTYPE -fatal_signal_handler(int a) -{ - struct sigaction act; - syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a)); - cp_trace(); +static RETSIGTYPE fatal_signal_handler(int a) { + struct sigaction act; + logger(LOG_ERR, "Got fatal signal %d (%s)", a, strsignal(a)); - if(do_detach) - { - syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds...")); + if(do_detach) { + logger(LOG_NOTICE, "Trying to re-execute in 5 seconds..."); - act.sa_handler = fatal_signal_square; - act.sa_mask = emptysigset; - act.sa_flags = 0; - sigaction(SIGSEGV, &act, NULL); + act.sa_handler = fatal_signal_square; + act.sa_mask = emptysigset; + act.sa_flags = 0; + sigaction(SIGSEGV, &act, NULL); - close_network_connections(); - sleep(5); - remove_pid(pidfilename); - execvp(g_argv[0], g_argv); - } - else - { - syslog(LOG_NOTICE, _("Not restarting.")); - exit(1); - } + close_network_connections(); + sleep(5); + remove_pid(pidfilename); + execvp(g_argv[0], g_argv); + } else { + logger(LOG_NOTICE, "Not restarting."); + exit(1); + } } -RETSIGTYPE -sighup_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got HUP signal")); - sighup = 1; +static RETSIGTYPE sighup_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "HUP"); + sighup = true; } -RETSIGTYPE -sigint_handler(int a) -{ - if(saved_debug_lvl) - { - syslog(LOG_NOTICE, _("Reverting to old debug level (%d)"), - saved_debug_lvl); - debug_lvl = saved_debug_lvl; - saved_debug_lvl = 0; - } - else - { - syslog(LOG_NOTICE, _("Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d."), - debug_lvl); - saved_debug_lvl = debug_lvl; - debug_lvl = 5; - } +static RETSIGTYPE sigint_handler(int a) { + (void)a; + static int saved_debug_level = -1; + + logger(LOG_NOTICE, "Got %s signal", "INT"); + + if(saved_debug_level != -1) { + logger(LOG_NOTICE, "Reverting to old debug level (%d)", + saved_debug_level); + debug_level = saved_debug_level; + saved_debug_level = -1; + } else { + logger(LOG_NOTICE, + "Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d.", + debug_level); + saved_debug_level = debug_level; + debug_level = 5; + } } -RETSIGTYPE -sigalrm_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got ALRM signal")); - sigalrm = 1; +static RETSIGTYPE sigalrm_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "ALRM"); + sigalrm = true; } -RETSIGTYPE -sigusr1_handler(int a) -{ - dump_connections(); +static RETSIGTYPE sigusr1_handler(int a) { + (void)a; + dump_connections(); } -RETSIGTYPE -sigusr2_handler(int a) -{ - dump_device_stats(); - dump_nodes(); - dump_edges(); - dump_subnets(); +static RETSIGTYPE sigusr2_handler(int a) { + (void)a; + devops.dump_stats(); + dump_nodes(); + dump_edges(); + dump_subnets(); } -RETSIGTYPE -sigwinch_handler(int a) -{ - extern int do_purge; - do_purge = 1; +static RETSIGTYPE sigwinch_handler(int a) { + (void)a; + do_purge = true; } -RETSIGTYPE -unexpected_signal_handler(int a) -{ - syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); - cp_trace(); +static RETSIGTYPE unexpected_signal_handler(int a) { + (void)a; + logger(LOG_WARNING, "Got unexpected signal %d (%s)", a, strsignal(a)); } -RETSIGTYPE -ignore_signal_handler(int a) -{ - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a)); - cp_trace(); - } +static RETSIGTYPE ignore_signal_handler(int a) { + (void)a; + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignored signal %d (%s)", a, strsignal(a)); } -struct { - int signal; - void (*handler)(int); +static struct { + int signal; + void (*handler)(int); } sighandlers[] = { - { SIGHUP, sighup_handler }, - { SIGTERM, sigterm_handler }, - { SIGQUIT, sigquit_handler }, - { SIGSEGV, fatal_signal_handler }, - { SIGBUS, fatal_signal_handler }, - { SIGILL, fatal_signal_handler }, - { SIGPIPE, ignore_signal_handler }, - { SIGINT, sigint_handler }, - { SIGUSR1, sigusr1_handler }, - { SIGUSR2, sigusr2_handler }, - { SIGCHLD, ignore_signal_handler }, - { SIGALRM, sigalrm_handler }, - { SIGWINCH, sigwinch_handler }, - { 0, NULL } + {SIGHUP, sighup_handler}, + {SIGTERM, sigterm_handler}, + {SIGQUIT, sigquit_handler}, + {SIGSEGV, fatal_signal_handler}, + {SIGBUS, fatal_signal_handler}, + {SIGILL, fatal_signal_handler}, + {SIGPIPE, ignore_signal_handler}, + {SIGINT, sigint_handler}, + {SIGUSR1, sigusr1_handler}, + {SIGUSR2, sigusr2_handler}, + {SIGCHLD, ignore_signal_handler}, + {SIGALRM, sigalrm_handler}, + {SIGWINCH, sigwinch_handler}, + {SIGABRT, SIG_DFL}, + {0, NULL} }; +#endif -void -setup_signals(void) -{ - int i; - struct sigaction act; +void setup_signals(void) { +#ifndef HAVE_MINGW + int i; + struct sigaction act; - sigemptyset(&emptysigset); - act.sa_handler = NULL; - act.sa_mask = emptysigset; - act.sa_flags = 0; + sigemptyset(&emptysigset); + act.sa_handler = NULL; + act.sa_mask = emptysigset; + act.sa_flags = 0; - /* Set a default signal handler for every signal, errors will be - ignored. */ - for(i = 0; i < NSIG; i++) - { - if(!do_detach) - act.sa_handler = SIG_DFL; - else - act.sa_handler = unexpected_signal_handler; - sigaction(i, &act, NULL); - } + /* Set a default signal handler for every signal, errors will be + ignored. */ + for(i = 1; i < NSIG; i++) { + if(!do_detach) { + act.sa_handler = SIG_DFL; + } else { + act.sa_handler = unexpected_signal_handler; + } - /* If we didn't detach, allow coredumps */ - if(!do_detach) - sighandlers[3].handler = SIG_DFL; + sigaction(i, &act, NULL); + } - /* Then, for each known signal that we want to catch, assign a - handler to the signal, with error checking this time. */ - for(i = 0; sighandlers[i].signal; i++) - { - act.sa_handler = sighandlers[i].handler; - if(sigaction(sighandlers[i].signal, &act, NULL) < 0) - fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %s\n"), - sighandlers[i].signal, strsignal(sighandlers[i].signal), strerror(errno)); - } + /* If we didn't detach, allow coredumps */ + if(!do_detach) { + sighandlers[3].handler = SIG_DFL; + } + + /* Then, for each known signal that we want to catch, assign a + handler to the signal, with error checking this time. */ + for(i = 0; sighandlers[i].signal; i++) { + act.sa_handler = sighandlers[i].handler; + + if(sigaction(sighandlers[i].signal, &act, NULL) < 0) + fprintf(stderr, "Installing signal handler for signal %d (%s) failed: %s\n", + sighandlers[i].signal, strsignal(sighandlers[i].signal), + strerror(errno)); + } + +#endif } diff --git a/src/process.h b/src/process.h index 1289d2d..e775ac3 100644 --- a/src/process.h +++ b/src/process.h @@ -1,7 +1,10 @@ +#ifndef TINC_PROCESS_H +#define TINC_PROCESS_H + /* process.h -- header file for process.c - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2006 Guus Sliepen 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 @@ -13,24 +16,22 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: process.h,v 1.1.2.10 2002/02/10 21:57:54 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_PROCESS_H__ -#define __TINC_PROCESS_H__ - -#include "config.h" - -extern int do_detach; +extern bool do_detach; +extern bool sighup; +extern bool sigalrm; extern void setup_signals(void); -extern int execute_script(const char *); -extern int detach(void); -extern int kill_other(int); -extern void cleanup_and_exit(int); +extern bool execute_script(const char *name, char **envp); +extern bool detach(void); +extern bool kill_other(int signal); -#endif /* __TINC_PROCESS_H__ */ +#ifdef HAVE_MINGW +extern bool init_service(void); +#endif + +#endif diff --git a/src/protocol.c b/src/protocol.c index 9b2ec91..4f74d3b 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,7 +1,7 @@ /* protocol.c -- handle the meta-protocol, basic functions - Copyright (C) 1999-2001 Ivo Timmermans , - 2000,2001 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen 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 @@ -13,232 +13,219 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol.c,v 1.28.4.128 2002/03/27 15:26:43 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "conf.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" - #include "system.h" -avl_tree_t *past_request_tree; +#include "conf.h" +#include "connection.h" +#include "logger.h" +#include "meta.h" +#include "protocol.h" +#include "utils.h" +#include "xalloc.h" -int check_id(char *id) -{ - int i; +bool tunnelserver = false; +bool strictsubnets = false; - for (i = 0; i < strlen(id); i++) - if(!isalnum(id[i]) && id[i] != '_') - return -1; - - return 0; +/* Jumptable for the request handlers */ + +static bool (*request_handlers[])(connection_t *) = { + id_h, metakey_h, challenge_h, chal_reply_h, ack_h, + NULL, NULL, NULL, + ping_h, pong_h, + add_subnet_h, del_subnet_h, + add_edge_h, del_edge_h, + key_changed_h, req_key_h, ans_key_h, tcppacket_h, +}; + +/* Request names */ + +static char (*request_name[]) = { + "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", + "STATUS", "ERROR", "TERMREQ", + "PING", "PONG", + "ADD_SUBNET", "DEL_SUBNET", + "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", +}; + +static avl_tree_t *past_request_tree; + +bool check_id(const char *id) { + for(; *id; id++) + if(!isalnum(*id) && *id != '_') { + return false; + } + + return true; } /* Generic request routines - takes care of logging and error detection as well */ -int send_request(connection_t *c, const char *format, ...) -{ - va_list args; - char buffer[MAXBUFSIZE]; - int len, request; +bool send_request(connection_t *c, const char *format, ...) { + va_list args; + char buffer[MAXBUFSIZE]; + int len, request = 0; -cp - /* Use vsnprintf instead of vasprintf: faster, no memory - fragmentation, cleanup is automatic, and there is a limit on the - input buffer anyway */ + /* Use vsnprintf instead of vxasprintf: faster, no memory + fragmentation, cleanup is automatic, and there is a limit on the + input buffer anyway */ - va_start(args, format); - len = vsnprintf(buffer, MAXBUFSIZE, format, args); - va_end(args); + va_start(args, format); + len = vsnprintf(buffer, sizeof(buffer), format, args); + buffer[sizeof(buffer) - 1] = 0; + va_end(args); - if(len < 0 || len > MAXBUFSIZE-1) - { - syslog(LOG_ERR, _("Output buffer overflow while sending request to %s (%s)"), c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_PROTOCOL) - { - sscanf(buffer, "%d", &request); - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], c->name, c->hostname, buffer); - else - syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], c->name, c->hostname); - } - - buffer[len++] = '\n'; -cp - return send_meta(c, buffer, len); -} - -int receive_request(connection_t *c) -{ - int request; -cp - if(sscanf(c->buffer, "%d", &request) == 1) - { - if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL)) - { - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"), - c->name, c->hostname, c->buffer); - else - syslog(LOG_ERR, _("Unknown request from %s (%s)"), - c->name, c->hostname); - - return -1; - } - else - { - if(debug_lvl >= DEBUG_PROTOCOL) - { - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"), - request_name[request], c->name, c->hostname, c->buffer); - else - syslog(LOG_DEBUG, _("Got %s from %s (%s)"), - request_name[request], c->name, c->hostname); - } + if(len < 0 || (size_t)len > sizeof(buffer) - 1) { + logger(LOG_ERR, "Output buffer overflow while sending request to %s (%s)", + c->name, c->hostname); + return false; } - if((c->allow_request != ALL) && (c->allow_request != request)) - { - syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, c->hostname); - return -1; - } + ifdebug(PROTOCOL) { + sscanf(buffer, "%d", &request); + ifdebug(META) + logger(LOG_DEBUG, "Sending %s to %s (%s): %s", + request_name[request], c->name, c->hostname, buffer); + else + logger(LOG_DEBUG, "Sending %s to %s (%s)", request_name[request], + c->name, c->hostname); + } - if(request_handlers[request](c)) - /* Something went wrong. Probably scriptkiddies. Terminate. */ - { - syslog(LOG_ERR, _("Error while processing %s from %s (%s)"), - request_name[request], c->name, c->hostname); - return -1; - } - } - else - { - syslog(LOG_ERR, _("Bogus data received from %s (%s)"), - c->name, c->hostname); - return -1; - } -cp - return 0; + buffer[len++] = '\n'; + + if(c == everyone) { + broadcast_meta(NULL, buffer, len); + return true; + } else { + return send_meta(c, buffer, len); + } } -int past_request_compare(past_request_t *a, past_request_t *b) -{ -cp - return strcmp(a->request, b->request); +void forward_request(connection_t *from) { + int request; + + ifdebug(PROTOCOL) { + sscanf(from->buffer, "%d", &request); + ifdebug(META) + logger(LOG_DEBUG, "Forwarding %s from %s (%s): %s", + request_name[request], from->name, from->hostname, + from->buffer); + else + logger(LOG_DEBUG, "Forwarding %s from %s (%s)", + request_name[request], from->name, from->hostname); + } + + from->buffer[from->reqlen - 1] = '\n'; + + broadcast_meta(from, from->buffer, from->reqlen); } -void free_past_request(past_request_t *r) -{ -cp - if(r->request) - free(r->request); - free(r); -cp +bool receive_request(connection_t *c) { + int request; + + if(sscanf(c->buffer, "%d", &request) == 1) { + if((request < 0) || (request >= LAST) || !request_handlers[request]) { + ifdebug(META) + logger(LOG_DEBUG, "Unknown request from %s (%s): %s", + c->name, c->hostname, c->buffer); + else + logger(LOG_ERR, "Unknown request from %s (%s)", + c->name, c->hostname); + + return false; + } else { + ifdebug(PROTOCOL) { + ifdebug(META) + logger(LOG_DEBUG, "Got %s from %s (%s): %s", + request_name[request], c->name, c->hostname, + c->buffer); + else + logger(LOG_DEBUG, "Got %s from %s (%s)", + request_name[request], c->name, c->hostname); + } + } + + if((c->allow_request != ALL) && (c->allow_request != request)) { + logger(LOG_ERR, "Unauthorized request from %s (%s)", c->name, + c->hostname); + return false; + } + + if(!request_handlers[request](c)) { + /* Something went wrong. Probably scriptkiddies. Terminate. */ + + logger(LOG_ERR, "Error while processing %s from %s (%s)", + request_name[request], c->name, c->hostname); + return false; + } + } else { + logger(LOG_ERR, "Bogus data received from %s (%s)", + c->name, c->hostname); + return false; + } + + return true; } -void init_requests(void) -{ -cp - past_request_tree = avl_alloc_tree((avl_compare_t)past_request_compare, (avl_action_t)free_past_request); -cp +static int past_request_compare(const past_request_t *a, const past_request_t *b) { + return strcmp(a->request, b->request); } -void exit_requests(void) -{ -cp - avl_delete_tree(past_request_tree); -cp +static void free_past_request(past_request_t *r) { + if(r->request) { + free(r->request); + } + + free(r); } -int seen_request(char *request) -{ - past_request_t p, *new; -cp - p.request = request; - - if(avl_search(past_request_tree, &p)) - { - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, _("Already seen request")); - return 1; - } - else - { - new = (past_request_t *)xmalloc(sizeof(*new)); - new->request = xstrdup(request); - new->firstseen = now; - avl_insert(past_request_tree, new); - return 0; - } -cp +void init_requests(void) { + past_request_tree = avl_alloc_tree((avl_compare_t) past_request_compare, (avl_action_t) free_past_request); } -void age_past_requests(void) -{ - avl_node_t *node, *next; - past_request_t *p; - int left = 0, deleted = 0; -cp - for(node = past_request_tree->head; node; node = next) - { - next = node->next; - p = (past_request_t *)node->data; - if(p->firstseen + pingtimeout < now) - avl_delete_node(past_request_tree, node), deleted++; - else - left++; - } - - if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted) - syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"), deleted, left); -cp +void exit_requests(void) { + avl_delete_tree(past_request_tree); } -/* Jumptable for the request handlers */ +bool seen_request(char *request) { + past_request_t *new, p = {0}; -int (*request_handlers[])(connection_t*) = { - id_h, metakey_h, challenge_h, chal_reply_h, ack_h, - status_h, error_h, termreq_h, - ping_h, pong_h, - add_subnet_h, del_subnet_h, - add_edge_h, del_edge_h, - key_changed_h, req_key_h, ans_key_h, - tcppacket_h, -}; + p.request = request; -/* Request names */ + if(avl_search(past_request_tree, &p)) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Already seen request"); + return true; + } else { + new = xmalloc(sizeof(*new)); + new->request = xstrdup(request); + new->firstseen = now; + avl_insert(past_request_tree, new); + return false; + } +} -char (*request_name[]) = { - "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", - "STATUS", "ERROR", "TERMREQ", - "PING", "PONG", - "ADD_SUBNET", "DEL_SUBNET", - "ADD_EDGE", "DEL_EDGE", - "KEY_CHANGED", "REQ_KEY", "ANS_KEY", - "PACKET", -}; +void age_past_requests(void) { + avl_node_t *node, *next; + past_request_t *p; + int left = 0, deleted = 0; + + for(node = past_request_tree->head; node; node = next) { + next = node->next; + p = node->data; + + if(p->firstseen + pinginterval <= now) { + avl_delete_node(past_request_tree, node), deleted++; + } else { + left++; + } + } + + if(left || deleted) + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Aging past requests: deleted %d, left %d", + deleted, left); +} diff --git a/src/protocol.h b/src/protocol.h index a4e480a..a055f28 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,7 +1,10 @@ +#ifndef TINC_PROTOCOL_H +#define TINC_PROTOCOL_H + /* protocol.h -- header for protocol.c - Copyright (C) 1999-2001 Ivo Timmermans , - 2000,2001 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2015 Guus Sliepen 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 @@ -13,108 +16,105 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol.h,v 1.5.4.29 2002/03/22 11:43:48 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_PROTOCOL_H__ -#define __TINC_PROTOCOL_H__ - -#include "net.h" -#include "node.h" -#include "subnet.h" - /* Protocol version. Different versions are incompatible, incompatible version have different protocols. */ -#define PROT_CURRENT 14 +#define PROT_CURRENT 17 + +/* Silly Windows */ + +#ifdef ERROR +#undef ERROR +#endif /* Request numbers */ -enum { - ALL = -1, /* Guardian for allow_request */ - ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, - STATUS, ERROR, TERMREQ, - PING, PONG, -// ADD_NODE, DEL_NODE, - ADD_SUBNET, DEL_SUBNET, - ADD_EDGE, DEL_EDGE, - KEY_CHANGED, REQ_KEY, ANS_KEY, - PACKET, - LAST /* Guardian for the highest request number */ -}; +typedef enum request_t { + PROXY = -2, + ALL = -1, /* Guardian for allow_request */ + ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, + STATUS, ERROR, TERMREQ, + PING, PONG, + ADD_SUBNET, DEL_SUBNET, + ADD_EDGE, DEL_EDGE, + KEY_CHANGED, REQ_KEY, ANS_KEY, + PACKET, + LAST /* Guardian for the highest request number */ +} request_t; typedef struct past_request_t { - char *request; - time_t firstseen; + char *request; + time_t firstseen; } past_request_t; -/* Maximum size of strings in a request */ +extern bool tunnelserver; +extern bool strictsubnets; -#define MAX_STRING_SIZE 2048 +/* Maximum size of strings in a request. + * scanf terminates %2048s with a NUL character, + * but the NUL character can be written after the 2048th non-NUL character. + */ + +#define MAX_STRING_SIZE 2049 #define MAX_STRING "%2048s" +#include "edge.h" +#include "net.h" +#include "node.h" +#include "subnet.h" + /* Basic functions */ -extern int send_request(connection_t*, const char*, ...); -extern int receive_request(connection_t *); -extern int check_id(char *); +extern bool send_request(struct connection_t *c, const char *format, ...) __attribute__((__format__(printf, 2, 3))); +extern void forward_request(struct connection_t *c); +extern bool receive_request(struct connection_t *c); +extern bool check_id(const char *name); extern void init_requests(void); extern void exit_requests(void); -extern int seen_request(char *); +extern bool seen_request(char *request); extern void age_past_requests(void); /* Requests */ -extern int send_id(connection_t *); -extern int send_metakey(connection_t *); -extern int send_challenge(connection_t *); -extern int send_chal_reply(connection_t *); -extern int send_ack(connection_t *); -extern int send_status(connection_t *, int, char *); -extern int send_error(connection_t *, int, char *); -extern int send_termreq(connection_t *); -extern int send_ping(connection_t *); -extern int send_pong(connection_t *); -// extern int send_add_node(connection_t *, node_t *); -// extern int send_del_node(connection_t *, node_t *); -extern int send_add_subnet(connection_t *, subnet_t *); -extern int send_del_subnet(connection_t *, subnet_t *); -extern int send_add_edge(connection_t *, edge_t *); -extern int send_del_edge(connection_t *, edge_t *); -extern int send_key_changed(connection_t *, node_t *); -extern int send_req_key(connection_t *, node_t *, node_t *); -extern int send_ans_key(connection_t *, node_t *, node_t *); -extern int send_tcppacket(connection_t *, vpn_packet_t *); +extern bool send_id(struct connection_t *c); +extern bool send_metakey(struct connection_t *c); +extern bool send_challenge(struct connection_t *c); +extern bool send_chal_reply(struct connection_t *c); +extern bool send_ack(struct connection_t *c); +extern bool send_ping(struct connection_t *c); +extern bool send_pong(struct connection_t *c); +extern bool send_add_subnet(struct connection_t *c, const struct subnet_t *subnet); +extern bool send_del_subnet(struct connection_t *c, const struct subnet_t *subnet); +extern bool send_add_edge(struct connection_t *c, const struct edge_t *e); +extern bool send_del_edge(struct connection_t *c, const struct edge_t *e); +extern void send_key_changed(void); +extern bool send_req_key(struct node_t *n); +extern bool send_ans_key(struct node_t *n); +extern bool send_tcppacket(struct connection_t *c, const struct vpn_packet_t *packet); /* Request handlers */ -extern int (*request_handlers[])(connection_t *); +extern bool id_h(struct connection_t *c); +extern bool metakey_h(struct connection_t *c); +extern bool challenge_h(struct connection_t *c); +extern bool chal_reply_h(struct connection_t *c); +extern bool ack_h(struct connection_t *c); +extern bool ping_h(struct connection_t *c); +extern bool pong_h(struct connection_t *c); +extern bool add_subnet_h(struct connection_t *c); +extern bool del_subnet_h(struct connection_t *c); +extern bool add_edge_h(struct connection_t *c); +extern bool del_edge_h(struct connection_t *c); +extern bool key_changed_h(struct connection_t *c); +extern bool req_key_h(struct connection_t *c); +extern bool ans_key_h(struct connection_t *c); +extern bool tcppacket_h(struct connection_t *c); -extern int id_h(connection_t *); -extern int metakey_h(connection_t *); -extern int challenge_h(connection_t *); -extern int chal_reply_h(connection_t *); -extern int ack_h(connection_t *); -extern int status_h(connection_t *); -extern int error_h(connection_t *); -extern int termreq_h(connection_t *); -extern int ping_h(connection_t *); -extern int pong_h(connection_t *); -// extern int add_node_h(connection_t *); -// extern int del_node_h(connection_t *); -extern int add_subnet_h(connection_t *); -extern int del_subnet_h(connection_t *); -extern int add_edge_h(connection_t *); -extern int del_edge_h(connection_t *); -extern int key_changed_h(connection_t *); -extern int req_key_h(connection_t *); -extern int ans_key_h(connection_t *); -extern int tcppacket_h(connection_t *); - -#endif /* __TINC_PROTOCOL_H__ */ +#endif diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 074b7d1..15807c3 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -1,7 +1,7 @@ /* protocol_auth.c -- handle the meta-protocol, authentication - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen 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 @@ -13,593 +13,674 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol_auth.c,v 1.1.4.8 2002/03/27 15:26:44 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#ifndef HAVE_RAND_PSEUDO_BYTES -#define RAND_pseudo_bytes RAND_bytes -#endif - -#include "conf.h" -#include "net.h" -#include "netutl.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" -#include "node.h" -#include "edge.h" -#include "graph.h" - #include "system.h" -int send_id(connection_t *c) -{ -cp - return send_request(c, "%d %s %d", ID, myself->connection->name, myself->connection->protocol_version); -} +#include +#include +#include +#include -int id_h(connection_t *c) -{ - char name[MAX_STRING_SIZE]; - int bla; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING" %d", name, &c->protocol_version) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name, c->hostname); - return -1; - } +#include "avl_tree.h" +#include "conf.h" +#include "connection.h" +#include "edge.h" +#include "graph.h" +#include "logger.h" +#include "meta.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "protocol.h" +#include "proxy.h" +#include "utils.h" +#include "xalloc.h" - /* Check if identity is a valid name */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ID", c->name, c->hostname, "invalid name"); - return -1; - } - - /* If we set c->name in advance, make sure we are connected to the right host */ - - if(c->name) - { - if(strcmp(c->name, name)) - { - syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, c->name); - return -1; - } - } - else - c->name = xstrdup(name); - - /* Check if version matches */ - - if(c->protocol_version != myself->connection->protocol_version) - { - syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"), - c->name, c->hostname, c->protocol_version); - return -1; - } - - if(bypass_security) - { - if(!c->config_tree) - init_configuration(&c->config_tree); - c->allow_request = ACK; - return send_ack(c); - } - - if(!c->config_tree) - { - init_configuration(&c->config_tree); - - if((bla = read_connection_config(c))) - { - syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, c->name); - return -1; - } - } - - if(read_rsa_public_key(c)) - { - return -1; - } - - /* Check some options */ - - if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &bla) && bla) || myself->options & OPTION_INDIRECT) - c->options |= OPTION_INDIRECT; - - if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &bla) && bla) || myself->options & OPTION_TCPONLY) - c->options |= OPTION_TCPONLY | OPTION_INDIRECT; - - c->allow_request = METAKEY; -cp - return send_metakey(c); -} - -int send_metakey(connection_t *c) -{ - char buffer[MAX_STRING_SIZE]; - int len, x; -cp - len = RSA_size(c->rsa_key); - - /* Allocate buffers for the meta key */ - - if(!c->outkey) - c->outkey = xmalloc(len); - - if(!c->outctx) - c->outctx = xmalloc(sizeof(*c->outctx)); -cp - /* Copy random data to the buffer */ - - RAND_bytes(c->outkey, len); - - /* The message we send must be smaller than the modulus of the RSA key. - By definition, for a key of k bits, the following formula holds: - - 2^(k-1) <= modulus < 2^(k) - - Where ^ means "to the power of", not "xor". - This means that to be sure, we must choose our message < 2^(k-1). - This can be done by setting the most significant bit to zero. - */ - - c->outkey[0] &= 0x7F; - - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(c->outkey, buffer, len); - buffer[len*2] = '\0'; - syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer); - } - - /* Encrypt the random data - - We do not use one of the PKCS padding schemes here. - This is allowed, because we encrypt a totally random string - with a length equal to that of the modulus of the RSA key. - */ - - if(RSA_public_encrypt(len, c->outkey, buffer, c->rsa_key, RSA_NO_PADDING) != len) - { - syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname); - return -1; - } -cp - /* Convert the encrypted random data to a hexadecimal formatted string */ - - bin2hex(buffer, buffer, len); - buffer[len*2] = '\0'; - - /* Send the meta key */ - - x = send_request(c, "%d %d %d %d %d %s", METAKEY, - c->outcipher?c->outcipher->nid:0, c->outdigest?c->outdigest->type:0, - c->outmaclength, c->outcompression, buffer); - - /* Further outgoing requests are encrypted with the key we just generated */ - - if(c->outcipher) - { - EVP_EncryptInit(c->outctx, c->outcipher, - c->outkey + len - c->outcipher->key_len, - c->outkey + len - c->outcipher->key_len - c->outcipher->iv_len); - - c->status.encryptout = 1; - } -cp - return x; -} - -int metakey_h(connection_t *c) -{ - char buffer[MAX_STRING_SIZE]; - int cipher, digest, maclength, compression; - int len; -cp - if(sscanf(c->buffer, "%*d %d %d %d %d "MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name, c->hostname); - return -1; - } -cp - len = RSA_size(myself->connection->rsa_key); - - /* Check if the length of the meta key is all right */ - - if(strlen(buffer) != len*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong keylength"); - return -1; - } - - /* Allocate buffers for the meta key */ -cp - if(!c->inkey) - c->inkey = xmalloc(len); - - if(!c->inctx) - c->inctx = xmalloc(sizeof(*c->inctx)); - - /* Convert the challenge from hexadecimal back to binary */ -cp - hex2bin(buffer,buffer,len); - - /* Decrypt the meta key */ -cp - if(RSA_private_decrypt(len, buffer, c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */ - { - syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(c->inkey, buffer, len); - buffer[len*2] = '\0'; - syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer); - } - - /* All incoming requests will now be encrypted. */ -cp - /* Check and lookup cipher and digest algorithms */ - - if(cipher) - { - c->incipher = EVP_get_cipherbynid(cipher); - if(!c->incipher) - { - syslog(LOG_ERR, _("%s (%s) uses unknown cipher!"), c->name, c->hostname); - return -1; +bool send_id(connection_t *c) { + if(proxytype && c->outgoing && !c->status.proxy_passed) { + return send_proxyrequest(c); } - EVP_DecryptInit(c->inctx, c->incipher, - c->inkey + len - c->incipher->key_len, - c->inkey + len - c->incipher->key_len - c->incipher->iv_len); + return send_request(c, "%d %s %d", ID, myself->connection->name, + myself->connection->protocol_version); +} - c->status.decryptin = 1; - } - else - { - c->incipher = NULL; - } +bool id_h(connection_t *c) { + char name[MAX_STRING_SIZE]; - c->inmaclength = maclength; - - if(digest) - { - c->indigest = EVP_get_digestbynid(digest); - if(!c->indigest) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), c->name, c->hostname); - return -1; + if(sscanf(c->buffer, "%*d " MAX_STRING " %d", name, &c->protocol_version) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name, + c->hostname); + return false; } - - if(c->inmaclength > c->indigest->md_size || c->inmaclength < 0) - { - syslog(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, c->hostname); - return -1; + + /* Check if identity is a valid name */ + + if(!check_id(name) || !strcmp(name, myself->name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name, + c->hostname, "invalid name"); + return false; } - } - else - { - c->indigest = NULL; - } - c->incompression = compression; + /* If this is an outgoing connection, make sure we are connected to the right host */ - c->allow_request = CHALLENGE; -cp - return send_challenge(c); + if(c->outgoing) { + if(strcmp(c->name, name)) { + logger(LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name, + c->name); + return false; + } + } else { + if(c->name) { + free(c->name); + } + + c->name = xstrdup(name); + } + + /* Check if version matches */ + + if(c->protocol_version != myself->connection->protocol_version) { + logger(LOG_ERR, "Peer %s (%s) uses incompatible version %d", + c->name, c->hostname, c->protocol_version); + return false; + } + + if(bypass_security) { + if(!c->config_tree) { + init_configuration(&c->config_tree); + } + + c->allow_request = ACK; + + if(!c->outgoing) { + send_id(c); + } + + return send_ack(c); + } + + if(!c->config_tree) { + init_configuration(&c->config_tree); + + if(!read_connection_config(c)) { + logger(LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, + c->name); + return false; + } + } + + if(!read_rsa_public_key(c)) { + return false; + } + + c->allow_request = METAKEY; + + if(!c->outgoing) { + send_id(c); + } + + return send_metakey(c); } -int send_challenge(connection_t *c) -{ - char buffer[MAX_STRING_SIZE]; - int len, x; -cp - /* CHECKME: what is most reasonable value for len? */ +static uint64_t byte_budget(const EVP_CIPHER *cipher) { + /* Hopefully some failsafe way to calculate the maximum amount of bytes to + send/receive with a given cipher before we might run into birthday paradox + attacks. Because we might use different modes, the block size of the mode + might be 1 byte. In that case, use the IV length. Ensure the whole thing + is limited to what can be represented with a 64 bits integer. + */ - len = RSA_size(c->rsa_key); - - /* Allocate buffers for the challenge */ - - if(!c->hischallenge) - c->hischallenge = xmalloc(len); -cp - /* Copy random data to the buffer */ - - RAND_bytes(c->hischallenge, len); - -cp - /* Convert to hex */ - - bin2hex(c->hischallenge, buffer, len); - buffer[len*2] = '\0'; - -cp - /* Send the challenge */ - - x = send_request(c, "%d %s", CHALLENGE, buffer); -cp - return x; + int ivlen = EVP_CIPHER_iv_length(cipher); + int blklen = EVP_CIPHER_block_size(cipher); + int len = blklen > 1 ? blklen : ivlen > 1 ? ivlen : 8; + int bits = len * 4 - 1; + return bits < 64 ? UINT64_C(1) << bits : UINT64_MAX; } -int challenge_h(connection_t *c) -{ - char buffer[MAX_STRING_SIZE]; - int len; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name, c->hostname); - return -1; - } +bool send_metakey(connection_t *c) { + bool x; - len = RSA_size(myself->connection->rsa_key); + int len = RSA_size(c->rsa_key); - /* Check if the length of the challenge is all right */ + /* Allocate buffers for the meta key */ - if(strlen(buffer) != len*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong challenge length"); - return -1; - } + char buffer[2 * len + 1]; - /* Allocate buffers for the challenge */ + c->outkey = xrealloc(c->outkey, len); - if(!c->mychallenge) - c->mychallenge = xmalloc(len); + if(!c->outctx) { + c->outctx = EVP_CIPHER_CTX_new(); - /* Convert the challenge from hexadecimal back to binary */ + if(!c->outctx) { + abort(); + } + } - hex2bin(buffer,c->mychallenge,len); + /* Copy random data to the buffer */ - c->allow_request = CHAL_REPLY; + if(1 != RAND_bytes((unsigned char *)c->outkey, len)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate meta key (%s)", ERR_error_string(err, NULL)); + return false; + } - /* Rest is done by send_chal_reply() */ -cp - return send_chal_reply(c); + + /* The message we send must be smaller than the modulus of the RSA key. + By definition, for a key of k bits, the following formula holds: + + 2^(k-1) <= modulus < 2^(k) + + Where ^ means "to the power of", not "xor". + This means that to be sure, we must choose our message < 2^(k-1). + This can be done by setting the most significant bit to zero. + */ + + c->outkey[0] &= 0x7F; + + ifdebug(SCARY_THINGS) { + bin2hex(c->outkey, buffer, len); + buffer[len * 2] = '\0'; + logger(LOG_DEBUG, "Generated random meta key (unencrypted): %s", + buffer); + } + + /* Encrypt the random data + + We do not use one of the PKCS padding schemes here. + This is allowed, because we encrypt a totally random string + with a length equal to that of the modulus of the RSA key. + */ + + if(RSA_public_encrypt(len, (unsigned char *)c->outkey, (unsigned char *)buffer, c->rsa_key, RSA_NO_PADDING) != len) { + logger(LOG_ERR, "Error during encryption of meta key for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + /* Convert the encrypted random data to a hexadecimal formatted string */ + + bin2hex(buffer, buffer, len); + buffer[len * 2] = '\0'; + + /* Send the meta key */ + + x = send_request(c, "%d %d %d %d %d %s", METAKEY, + c->outcipher ? EVP_CIPHER_nid(c->outcipher) : 0, + c->outdigest ? EVP_MD_type(c->outdigest) : 0, c->outmaclength, + c->outcompression, buffer); + + /* Further outgoing requests are encrypted with the key we just generated */ + + if(c->outcipher) { + if(!EVP_EncryptInit(c->outctx, c->outcipher, + (unsigned char *)c->outkey + len - EVP_CIPHER_key_length(c->outcipher), + (unsigned char *)c->outkey + len - EVP_CIPHER_key_length(c->outcipher) - + EVP_CIPHER_iv_length(c->outcipher))) { + logger(LOG_ERR, "Error during initialisation of cipher for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + c->outbudget = byte_budget(c->outcipher); + c->status.encryptout = true; + } + + return x; } -int send_chal_reply(connection_t *c) -{ - char hash[EVP_MAX_MD_SIZE*2+1]; - EVP_MD_CTX ctx; -cp - /* Calculate the hash from the challenge we received */ +bool metakey_h(connection_t *c) { + char buffer[MAX_STRING_SIZE]; + int cipher, digest, maclength, compression; + int len; - EVP_DigestInit(&ctx, c->indigest); - EVP_DigestUpdate(&ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)); - EVP_DigestFinal(&ctx, hash, NULL); + if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, + c->hostname); + return false; + } - /* Convert the hash to a hexadecimal formatted string */ + len = RSA_size(myself->connection->rsa_key); - bin2hex(hash,hash,c->indigest->md_size); - hash[c->indigest->md_size*2] = '\0'; + /* Check if the length of the meta key is all right */ - /* Send the reply */ + if(strlen(buffer) != (size_t)len * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength"); + return false; + } -cp - return send_request(c, "%d %s", CHAL_REPLY, hash); + /* Allocate buffers for the meta key */ + + c->inkey = xrealloc(c->inkey, len); + + if(!c->inctx) { + c->inctx = EVP_CIPHER_CTX_new(); + + if(!c->inctx) { + abort(); + } + } + + /* Convert the challenge from hexadecimal back to binary */ + + if(!hex2bin(buffer, buffer, len)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key"); + return false; + } + + /* Decrypt the meta key */ + + if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */ + logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + ifdebug(SCARY_THINGS) { + bin2hex(c->inkey, buffer, len); + buffer[len * 2] = '\0'; + logger(LOG_DEBUG, "Received random meta key (unencrypted): %s", buffer); + } + + /* All incoming requests will now be encrypted. */ + + /* Check and lookup cipher and digest algorithms */ + + if(cipher) { + c->incipher = EVP_get_cipherbynid(cipher); + + if(!c->incipher) { + logger(LOG_ERR, "%s (%s) uses unknown cipher!", c->name, c->hostname); + return false; + } + + if(!EVP_DecryptInit(c->inctx, c->incipher, + (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher), + (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher) - + EVP_CIPHER_iv_length(c->incipher))) { + logger(LOG_ERR, "Error during initialisation of cipher from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + c->inbudget = byte_budget(c->incipher); + c->status.decryptin = true; + } else { + logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname); + return false; + } + + c->inmaclength = maclength; + + if(digest) { + c->indigest = EVP_get_digestbynid(digest); + + if(!c->indigest) { + logger(LOG_ERR, "Node %s (%s) uses unknown digest!", c->name, c->hostname); + return false; + } + + if(c->inmaclength > EVP_MD_size(c->indigest) || c->inmaclength < 0) { + logger(LOG_ERR, "%s (%s) uses bogus MAC length!", c->name, c->hostname); + return false; + } + } else { + logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname); + return false; + } + + c->incompression = compression; + + c->allow_request = CHALLENGE; + + return send_challenge(c); } -int chal_reply_h(connection_t *c) -{ - char hishash[MAX_STRING_SIZE]; - char myhash[EVP_MAX_MD_SIZE]; - EVP_MD_CTX ctx; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING, hishash) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name, c->hostname); - return -1; - } +bool send_challenge(connection_t *c) { + /* CHECKME: what is most reasonable value for len? */ - /* Check if the length of the hash is all right */ + int len = RSA_size(c->rsa_key); - if(strlen(hishash) != c->outdigest->md_size*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply length")); - return -1; - } + /* Allocate buffers for the challenge */ - /* Convert the hash to binary format */ + char buffer[2 * len + 1]; - hex2bin(hishash, hishash, c->outdigest->md_size); + c->hischallenge = xrealloc(c->hischallenge, len); - /* Calculate the hash from the challenge we sent */ + /* Copy random data to the buffer */ - EVP_DigestInit(&ctx, c->outdigest); - EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key)); - EVP_DigestFinal(&ctx, myhash, NULL); + if(1 != RAND_bytes((unsigned char *)c->hischallenge, len)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate challenge (%s)", ERR_error_string(err, NULL)); + return false; // Do not send predictable challenges, let connection attempt fail. + } - /* Verify the incoming hash with the calculated hash */ + /* Convert to hex */ - if(memcmp(hishash, myhash, c->outdigest->md_size)) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply")); - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(myhash, hishash, SHA_DIGEST_LENGTH); - hishash[SHA_DIGEST_LENGTH*2] = '\0'; - syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash); - } - return -1; - } + bin2hex(c->hischallenge, buffer, len); + buffer[len * 2] = '\0'; - /* Identity has now been positively verified. - Send an acknowledgement with the rest of the information needed. - */ + /* Send the challenge */ - c->allow_request = ACK; -cp - return send_ack(c); + return send_request(c, "%d %s", CHALLENGE, buffer); } -int send_ack(connection_t *c) -{ - /* ACK message contains rest of the information the other end needs - to create node_t and edge_t structures. */ +bool challenge_h(connection_t *c) { + char buffer[MAX_STRING_SIZE]; + int len; - int x; - char *address, *port; - struct timeval now; -cp - /* Estimate weight */ - - gettimeofday(&now, NULL); - c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000; - sockaddr2str(&c->address, &address, &port); - x = send_request(c, "%d %s %s %d %lx", ACK, myport, address, c->estimated_weight, c->options); - free(address); - free(port); -cp - return x; + if(sscanf(c->buffer, "%*d " MAX_STRING, buffer) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "CHALLENGE", c->name, + c->hostname); + return false; + } + + len = RSA_size(myself->connection->rsa_key); + + /* Check if the length of the challenge is all right */ + + if(strlen(buffer) != (size_t)len * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge length"); + return false; + } + + /* Allocate buffers for the challenge */ + + c->mychallenge = xrealloc(c->mychallenge, len); + + /* Convert the challenge from hexadecimal back to binary */ + + if(!hex2bin(buffer, c->mychallenge, len)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHALLENGE", c->name, c->hostname, "invalid challenge"); + return false; + } + + c->allow_request = CHAL_REPLY; + + /* Rest is done by send_chal_reply() */ + + if(c->outgoing) { + return send_chal_reply(c); + } else { + return true; + } } -void send_everything(connection_t *c) -{ - avl_node_t *node, *node2; - node_t *n; - subnet_t *s; - edge_t *e; +bool send_chal_reply(connection_t *c) { + char hash[EVP_MAX_MD_SIZE * 2 + 1]; + EVP_MD_CTX *ctx; - /* Send all known subnets */ - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; + /* Calculate the hash from the challenge we received */ - for(node2 = n->subnet_tree->head; node2; node2 = node2->next) - { - s = (subnet_t *)node2->data; - send_add_subnet(c, s); - } - } + ctx = EVP_MD_CTX_create(); - /* Send all known edges */ + if(!ctx) { + abort(); + } - for(node = edge_tree->head; node; node = node->next) - { - e = (edge_t *)node->data; + if(!EVP_DigestInit(ctx, c->indigest) + || !EVP_DigestUpdate(ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)) + || !EVP_DigestFinal(ctx, (unsigned char *)hash, NULL)) { + EVP_MD_CTX_destroy(ctx); + logger(LOG_ERR, "Error during calculation of response for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } - if(e == c->edge) - continue; + EVP_MD_CTX_destroy(ctx); - send_add_edge(c, e); - } + /* Convert the hash to a hexadecimal formatted string */ + + bin2hex(hash, hash, EVP_MD_size(c->indigest)); + hash[EVP_MD_size(c->indigest) * 2] = '\0'; + + /* Send the reply */ + + return send_request(c, "%d %s", CHAL_REPLY, hash); } -int ack_h(connection_t *c) -{ - char myaddress[MAX_STRING_SIZE]; - char hisport[MAX_STRING_SIZE]; - char *hisaddress, *dummy; - int weight; - long int options; - node_t *n; - connection_t *other; - avl_node_t *node; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %d %lx", hisport, myaddress, &weight, &options) != 4) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname); - return -1; - } +bool chal_reply_h(connection_t *c) { + char hishash[MAX_STRING_SIZE]; + char myhash[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *ctx; - /* Check if we already have a node_t for him */ + if(sscanf(c->buffer, "%*d " MAX_STRING, hishash) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name, + c->hostname); + return false; + } - n = lookup_node(c->name); - - if(!n) - { - n = new_node(); - n->name = xstrdup(c->name); - node_add(n); - } - else - { - if(n->connection) - { - /* Oh dear, we already have a connection to this node. */ - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), n->name, n->hostname); - terminate_connection(n->connection, 0); - } - - /* FIXME: check if information in existing node matches that of the other end of this connection */ - } - - n->connection = c; - c->node = n; - c->options |= options; + /* Check if the length of the hash is all right */ - /* Create an edge_t for this connection */ + if(strlen(hishash) != (size_t)EVP_MD_size(c->outdigest) * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge reply length"); + return false; + } - c->edge = new_edge(); -cp - c->edge->from.node = myself; - c->edge->from.udpaddress = str2sockaddr(myaddress, myport); - c->edge->to.node = n; - sockaddr2str(&c->address, &hisaddress, &dummy); - c->edge->to.udpaddress = str2sockaddr(hisaddress, hisport); - free(hisaddress); - free(dummy); - c->edge->weight = (weight + c->estimated_weight) / 2; - c->edge->connection = c; - c->edge->options = c->options; -cp - edge_add(c->edge); + /* Convert the hash to binary format */ - /* Activate this connection */ + if(!hex2bin(hishash, hishash, EVP_MD_size(c->outdigest))) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash"); + return false; + } - c->allow_request = ALL; - c->status.active = 1; + /* Calculate the hash from the challenge we sent */ - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname); + ctx = EVP_MD_CTX_create(); -cp - /* Send him everything we know */ + if(!ctx) { + abort(); + } - send_everything(c); + if(!EVP_DigestInit(ctx, c->outdigest) + || !EVP_DigestUpdate(ctx, c->hischallenge, RSA_size(c->rsa_key)) + || !EVP_DigestFinal(ctx, (unsigned char *)myhash, NULL)) { + EVP_MD_CTX_destroy(ctx); + logger(LOG_ERR, "Error during calculation of response from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } - /* Notify others of this connection */ + EVP_MD_CTX_destroy(ctx); - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; + /* Verify the incoming hash with the calculated hash */ - if(other->status.active && other != c) - send_add_edge(other, c->edge); - } + if(memcmp(hishash, myhash, EVP_MD_size(c->outdigest))) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge reply"); - /* Run MST and SSSP algorithms */ - - graph(); -cp - return 0; + ifdebug(SCARY_THINGS) { + bin2hex(myhash, hishash, SHA_DIGEST_LENGTH); + hishash[SHA_DIGEST_LENGTH * 2] = '\0'; + logger(LOG_DEBUG, "Expected challenge reply: %s", hishash); + } + + return false; + } + + /* Identity has now been positively verified. + Send an acknowledgement with the rest of the information needed. + */ + + c->allow_request = ACK; + + if(!c->outgoing) { + send_chal_reply(c); + } + + return send_ack(c); +} + +bool send_ack(connection_t *c) { + /* ACK message contains rest of the information the other end needs + to create node_t and edge_t structures. */ + + struct timeval now; + bool choice; + + /* Estimate weight */ + + gettimeofday(&now, NULL); + c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000; + + /* Check some options */ + + if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT) { + c->options |= OPTION_INDIRECT; + } + + if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY) { + c->options |= OPTION_TCPONLY | OPTION_INDIRECT; + } + + if(myself->options & OPTION_PMTU_DISCOVERY && !(c->options & OPTION_TCPONLY)) { + c->options |= OPTION_PMTU_DISCOVERY; + } + + choice = myself->options & OPTION_CLAMP_MSS; + get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice); + + if(choice) { + c->options |= OPTION_CLAMP_MSS; + } + + get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight); + + return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options); +} + +static void send_everything(connection_t *c) { + avl_node_t *node, *node2; + node_t *n; + subnet_t *s; + edge_t *e; + + /* Send all known subnets and edges */ + + if(tunnelserver) { + for(node = myself->subnet_tree->head; node; node = node->next) { + s = node->data; + send_add_subnet(c, s); + } + + return; + } + + for(node = node_tree->head; node; node = node->next) { + n = node->data; + + for(node2 = n->subnet_tree->head; node2; node2 = node2->next) { + s = node2->data; + send_add_subnet(c, s); + } + + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = node2->data; + send_add_edge(c, e); + } + } +} + +bool ack_h(connection_t *c) { + char hisport[MAX_STRING_SIZE]; + int weight, mtu; + uint32_t options; + node_t *n; + bool choice; + + if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, + c->hostname); + return false; + } + + /* Check if we already have a node_t for him */ + + n = lookup_node(c->name); + + if(!n) { + n = new_node(); + n->name = xstrdup(c->name); + node_add(n); + } else { + if(n->connection) { + /* Oh dear, we already have a connection to this node. */ + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", + n->name, n->hostname); + terminate_connection(n->connection, false); + /* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */ + graph(); + } + } + + n->connection = c; + c->node = n; + + if(!(c->options & options & OPTION_PMTU_DISCOVERY)) { + c->options &= ~OPTION_PMTU_DISCOVERY; + options &= ~OPTION_PMTU_DISCOVERY; + } + + c->options |= options; + + if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) { + n->mtu = mtu; + } + + if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) { + n->mtu = mtu; + } + + if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) { + if(choice) { + c->options |= OPTION_CLAMP_MSS; + } else { + c->options &= ~OPTION_CLAMP_MSS; + } + } + + /* Activate this connection */ + + c->allow_request = ALL; + c->status.active = true; + + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection with %s (%s) activated", c->name, + c->hostname); + + /* Send him everything we know */ + + send_everything(c); + + /* Create an edge_t for this connection */ + + c->edge = new_edge(); + c->edge->from = myself; + c->edge->to = n; + sockaddrcpy(&c->edge->address, &c->address); + sockaddr_setport(&c->edge->address, hisport); + c->edge->weight = (weight + c->estimated_weight) / 2; + c->edge->connection = c; + c->edge->options = c->options; + + edge_add(c->edge); + + /* Notify everyone of the new edge */ + + if(tunnelserver) { + send_add_edge(c, c->edge); + } else { + send_add_edge(everyone, c->edge); + } + + /* Run MST and SSSP algorithms */ + + graph(); + + return true; } diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 0d3218e..a1cf640 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -1,7 +1,8 @@ /* protocol_edge.c -- handle the meta-protocol, edges - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen + 2009 Michael Tokarev 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 @@ -13,286 +14,271 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol_edge.c,v 1.1.4.7 2002/03/27 15:26:44 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conf.h" -#include "net.h" -#include "netutl.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" -#include "node.h" -#include "edge.h" -#include "graph.h" - #include "system.h" -int send_add_edge(connection_t *c, edge_t *e) -{ - int x; - char *from_udpaddress, *from_udpport; - char *to_udpaddress, *to_udpport; -cp - sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport); - sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport); - x = send_request(c, "%d %lx %s %s %s %s %s %s %lx %d", ADD_EDGE, random(), - e->from.node->name, from_udpaddress, from_udpport, - e->to.node->name, to_udpaddress, to_udpport, - e->options, e->weight); - free(from_udpaddress); - free(from_udpport); - free(to_udpaddress); - free(to_udpport); -cp - return x; +#include "avl_tree.h" +#include "conf.h" +#include "connection.h" +#include "edge.h" +#include "graph.h" +#include "logger.h" +#include "meta.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "protocol.h" +#include "utils.h" +#include "xalloc.h" + +bool send_add_edge(connection_t *c, const edge_t *e) { + bool x; + char *address, *port; + + sockaddr2str(&e->address, &address, &port); + + x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(), + e->from->name, e->to->name, address, port, + e->options, e->weight); + free(address); + free(port); + + return x; } -int add_edge_h(connection_t *c) -{ - connection_t *other; - edge_t *e; - node_t *from, *to; - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - char from_address[MAX_STRING_SIZE]; - char from_udpport[MAX_STRING_SIZE]; - char to_address[MAX_STRING_SIZE]; - char to_udpport[MAX_STRING_SIZE]; - sockaddr_t from_udpaddress; - sockaddr_t to_udpaddress; - long int options; - int weight; - avl_node_t *node; -cp - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d", - from_name, from_address, from_udpport, - to_name, to_address, to_udpport, - &options, &weight) != 8) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname); - return -1; - } +bool add_edge_h(connection_t *c) { + edge_t *e; + node_t *from, *to; + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + char to_address[MAX_STRING_SIZE]; + char to_port[MAX_STRING_SIZE]; + sockaddr_t address; + uint32_t options; + int weight; - /* Check if names are valid */ + if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", + from_name, to_name, to_address, to_port, &options, &weight) != 6) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, + c->hostname); + return false; + } - if(check_id(from_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } + /* Check if names are valid */ - if(check_id(to_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } + if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, + c->hostname, "invalid name"); + return false; + } - if(seen_request(c->buffer)) - return 0; + if(seen_request(c->buffer)) { + return true; + } - /* Lookup nodes */ + /* Lookup nodes */ - from = lookup_node(from_name); - - if(!from) - { - from = new_node(); - from->name = xstrdup(from_name); - node_add(from); - } + from = lookup_node(from_name); + to = lookup_node(to_name); - to = lookup_node(to_name); - - if(!to) - { - to = new_node(); - to->name = xstrdup(to_name); - node_add(to); - } + if(tunnelserver && + from != myself && from != c->node && + to != myself && to != c->node) { + /* ignore indirect edge registrations for tunnelserver */ + ifdebug(PROTOCOL) logger(LOG_WARNING, + "Ignoring indirect %s from %s (%s)", + "ADD_EDGE", c->name, c->hostname); + return true; + } - /* Convert addresses */ - - from_udpaddress = str2sockaddr(from_address, from_udpport); - to_udpaddress = str2sockaddr(to_address, to_udpport); + if(!from) { + from = new_node(); + from->name = xstrdup(from_name); + node_add(from); + } - /* Check if edge already exists */ - - e = lookup_edge(from, to); - - if(e) - { - if(e->weight != weight || e->options != options - || ((e->from.node == from) && (sockaddrcmp(&e->from.udpaddress, &from_udpaddress)|| sockaddrcmp(&e->to.udpaddress, &to_udpaddress))) - || ((e->from.node == to) && (sockaddrcmp(&e->from.udpaddress, &to_udpaddress) || sockaddrcmp(&e->to.udpaddress, &from_udpaddress))) - ) - { - if(from == myself || to == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not match existing entry"), "ADD_EDGE", c->name, c->hostname); - send_add_edge(c, e); - return 0; - } - else - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) which does not match existing entry"), "ADD_EDGE", c->name, c->hostname); - edge_del(e); - } - } - else - return 0; - } - else if(from == myself || to == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not exist"), "ADD_EDGE", c->name, c->hostname); - e = new_edge(); - e->from.node = from; - e->to.node = to; - send_del_edge(c, e); - free_edge(e); - return 0; - } + if(!to) { + to = new_node(); + to->name = xstrdup(to_name); + node_add(to); + } - e = new_edge(); - e->from.node = from; - e->from.udpaddress = from_udpaddress; - e->to.node = to; - e->to.udpaddress = to_udpaddress; - e->options = options; - e->weight = weight; - edge_add(e); - /* Tell the rest about the new edge */ + /* Convert addresses */ - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%s", c->buffer); - } + address = str2sockaddr(to_address, to_port); - /* Run MST before or after we tell the rest? */ + /* Check if edge already exists */ - graph(); -cp - return 0; + e = lookup_edge(from, to); + + if(e) { + if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { + if(from == myself) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", + "ADD_EDGE", c->name, c->hostname); + send_add_edge(c, e); + return true; + } else { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", + "ADD_EDGE", c->name, c->hostname); + e->options = options; + + if(sockaddrcmp(&e->address, &address)) { + sockaddrfree(&e->address); + e->address = address; + } + + if(e->weight != weight) { + avl_node_t *node = avl_unlink(edge_weight_tree, e); + e->weight = weight; + avl_insert_node(edge_weight_tree, node); + } + + goto done; + } + } else { + return true; + } + } else if(from == myself) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", + "ADD_EDGE", c->name, c->hostname); + contradicting_add_edge++; + e = new_edge(); + e->from = from; + e->to = to; + send_del_edge(c, e); + free_edge(e); + return true; + } + + e = new_edge(); + e->from = from; + e->to = to; + e->address = address; + e->options = options; + e->weight = weight; + edge_add(e); + +done: + /* Tell the rest about the new edge */ + + if(!tunnelserver) { + forward_request(c); + } + + /* Run MST before or after we tell the rest? */ + + graph(); + + return true; } -int send_del_edge(connection_t *c, edge_t *e) -{ -cp - return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), - e->from.node->name, e->to.node->name); +bool send_del_edge(connection_t *c, const edge_t *e) { + return send_request(c, "%d %x %s %s", DEL_EDGE, rand(), + e->from->name, e->to->name); } -int del_edge_h(connection_t *c) -{ - edge_t *e; - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - node_t *from, *to; - connection_t *other; - avl_node_t *node; -cp - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING"", from_name, to_name) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE", - c->name, c->hostname); - return -1; - } +bool del_edge_h(connection_t *c) { + edge_t *e; + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + node_t *from, *to; - /* Check if names are valid */ + if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name, + c->hostname); + return false; + } - if(check_id(from_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } + /* Check if names are valid */ - if(check_id(to_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } + if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name, + c->hostname, "invalid name"); + return false; + } - if(seen_request(c->buffer)) - return 0; + if(seen_request(c->buffer)) { + return true; + } - /* Lookup nodes */ + /* Lookup nodes */ - from = lookup_node(from_name); - - if(!from) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } + from = lookup_node(from_name); + to = lookup_node(to_name); - to = lookup_node(to_name); - - if(!to) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } + if(tunnelserver && + from != myself && from != c->node && + to != myself && to != c->node) { + /* ignore indirect edge registrations for tunnelserver */ + ifdebug(PROTOCOL) logger(LOG_WARNING, + "Ignoring indirect %s from %s (%s)", + "DEL_EDGE", c->name, c->hostname); + return true; + } - /* Check if edge exists */ - - e = lookup_edge(from, to); - - if(!e) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } + if(!from) { + ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); + return true; + } - if(e->from.node == myself || e->to.node == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_EDGE", c->name, c->hostname); - send_add_edge(c, e); /* Send back a correction */ - return 0; - } + if(!to) { + ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); + return true; + } - /* Tell the rest about the deleted edge */ + /* Check if edge exists */ - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%s", c->buffer); - } + e = lookup_edge(from, to); - /* Delete the edge */ - - edge_del(e); + if(!e) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); + return true; + } - /* Run MST before or after we tell the rest? */ + if(e->from == myself) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", + "DEL_EDGE", c->name, c->hostname); + contradicting_del_edge++; + send_add_edge(c, e); /* Send back a correction */ + return true; + } - graph(); -cp - return 0; + /* Tell the rest about the deleted edge */ + + if(!tunnelserver) { + forward_request(c); + } + + /* Delete the edge */ + + edge_del(e); + + /* Run MST before or after we tell the rest? */ + + graph(); + + /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */ + + if(!to->status.reachable) { + e = lookup_edge(to, myself); + + if(e) { + if(!tunnelserver) { + send_del_edge(everyone, e); + } + + edge_del(e); + } + } + + return true; } diff --git a/src/protocol_key.c b/src/protocol_key.c index 016fbff..6140a53 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -1,7 +1,7 @@ /* protocol_key.c -- handle the meta-protocol, key exchange - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2016 Guus Sliepen 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 @@ -13,274 +13,333 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol_key.c,v 1.1.4.6 2002/03/22 13:31:18 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conf.h" -#include "net.h" -#include "netutl.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" -#include "node.h" -#include "edge.h" - #include "system.h" -int mykeyused = 0; +#include +#include +#include -int send_key_changed(connection_t *c, node_t *n) -{ - connection_t *other; - avl_node_t *node; -cp - /* Only send this message if some other daemon requested our key previously. - This reduces unnecessary key_changed broadcasts. - */ +#include "avl_tree.h" +#include "connection.h" +#include "logger.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "protocol.h" +#include "utils.h" +#include "xalloc.h" - if(n == myself && !mykeyused) - return 0; +static bool mykeyused = false; - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%d %lx %s", KEY_CHANGED, random(), n->name); - } -cp - return 0; -} +void send_key_changed(void) { + avl_node_t *node; + connection_t *c; -int key_changed_h(connection_t *c) -{ - char name[MAX_STRING_SIZE]; - avl_node_t *node; - connection_t *other; - node_t *n; -cp - if(sscanf(c->buffer, "%*d %*x "MAX_STRING, name) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED", - c->name, c->hostname); - return -1; - } + send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name); - if(seen_request(c->buffer)) - return 0; + /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */ - n = lookup_node(name); + for(node = connection_tree->head; node; node = node->next) { + c = node->data; - if(!n) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"), "KEY_CHANGED", - c->name, c->hostname, name); - return -1; - } - - n->status.validkey = 0; - n->status.waitingforkey = 0; - n->sent_seqno = 0; - - /* Tell the others */ - - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%s", c->buffer); - } -cp - return 0; -} - -int send_req_key(connection_t *c, node_t *from, node_t *to) -{ -cp - return send_request(c, "%d %s %s", REQ_KEY, - from->name, to->name); -} - -int req_key_h(connection_t *c) -{ - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - node_t *from, *to; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY", - c->name, c->hostname); - return -1; - } - - from = lookup_node(from_name); - - if(!from) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "REQ_KEY", - c->name, c->hostname, from_name); - return -1; - } - - to = lookup_node(to_name); - - if(!to) - { - syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "REQ_KEY", - c->name, c->hostname, to_name); - return -1; - } - - /* Check if this key request is for us */ - - if(to == myself) /* Yes, send our own key back */ - { - mykeyused = 1; - from->received_seqno = 0; - send_ans_key(c, myself, from); - } - else - { -/* Proxy keys - if(to->status.validkey) - { - send_ans_key(c, to, from); - } - else -*/ - send_req_key(to->nexthop->connection, from, to); - } - -cp - return 0; -} - -int send_ans_key(connection_t *c, node_t *from, node_t *to) -{ - char key[MAX_STRING_SIZE]; -cp - bin2hex(from->key, key, from->keylength); - key[from->keylength * 2] = '\0'; -cp - return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY, - from->name, to->name, key, from->cipher?from->cipher->nid:0, from->digest?from->digest->type:0, from->maclength, from->compression); -} - -int ans_key_h(connection_t *c) -{ - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - char key[MAX_STRING_SIZE]; - int cipher, digest, maclength, compression; - node_t *from, *to; -cp - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d", from_name, to_name, key, &cipher, &digest, &maclength, &compression) != 7) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY", - c->name, c->hostname); - return -1; - } - - from = lookup_node(from_name); - - if(!from) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "ANS_KEY", - c->name, c->hostname, from_name); - return -1; - } - - to = lookup_node(to_name); - - if(!to) - { - syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "ANS_KEY", - c->name, c->hostname, to_name); - return -1; - } - - /* Forward it if necessary */ - - if(to != myself) - { - return send_request(to->nexthop->connection, "%s", c->buffer); - } - - /* Update our copy of the origin's packet key */ - - if(from->key) - free(from->key); - - from->key = xstrdup(key); - from->keylength = strlen(key) / 2; - hex2bin(from->key, from->key, from->keylength); - from->key[from->keylength] = '\0'; - - from->status.validkey = 1; - from->status.waitingforkey = 0; - - /* Check and lookup cipher and digest algorithms */ - - if(cipher) - { - from->cipher = EVP_get_cipherbynid(cipher); - if(!from->cipher) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name, from->hostname); - return -1; + if(c->status.active && c->node && c->node->status.reachable) { + send_ans_key(c->node); + } } - if(from->keylength != from->cipher->key_len + from->cipher->iv_len) - { - syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, from->hostname); - return -1; - } - } - else - { - from->cipher = NULL; - } - - from->maclength = maclength; - - if(digest) - { - from->digest = EVP_get_digestbynid(digest); - if(!from->digest) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name, from->hostname); - return -1; - } - if(from->maclength > from->digest->md_size || from->maclength < 0) - { - syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), from->name, from->hostname); - return -1; - } - } - else - { - from->digest = NULL; - } - - from->compression = compression; - - flush_queue(from); -cp - return 0; +} + +bool key_changed_h(connection_t *c) { + char name[MAX_STRING_SIZE]; + node_t *n; + + if(sscanf(c->buffer, "%*d %*x " MAX_STRING, name) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED", + c->name, c->hostname); + return false; + } + + if(!check_id(name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "KEY_CHANGED", c->name, c->hostname, "invalid name"); + return false; + } + + if(seen_request(c->buffer)) { + return true; + } + + n = lookup_node(name); + + if(!n) { + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist", + "KEY_CHANGED", c->name, c->hostname, name); + return true; + } + + n->status.validkey = false; + n->last_req_key = 0; + + /* Tell the others */ + + if(!tunnelserver) { + forward_request(c); + } + + return true; +} + +bool send_req_key(node_t *to) { + return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name); +} + +bool req_key_h(connection_t *c) { + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + node_t *from, *to; + + if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, from_name, to_name) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name, + c->hostname); + return false; + } + + if(!check_id(from_name) || !check_id(to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name"); + return false; + } + + from = lookup_node(from_name); + + if(!from) { + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", + "REQ_KEY", c->name, c->hostname, from_name); + return true; + } + + to = lookup_node(to_name); + + if(!to) { + logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", + "REQ_KEY", c->name, c->hostname, to_name); + return true; + } + + /* Check if this key request is for us */ + + if(to == myself) { /* Yes, send our own key back */ + if(!send_ans_key(from)) { + return false; + } + } else { + if(tunnelserver) { + return true; + } + + if(!to->status.reachable) { + logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", + "REQ_KEY", c->name, c->hostname, to_name); + return true; + } + + send_request(to->nexthop->connection, "%s", c->buffer); + } + + return true; +} + +bool send_ans_key(node_t *to) { + // Set key parameters + to->incipher = myself->incipher; + to->inkeylength = myself->inkeylength; + to->indigest = myself->indigest; + to->inmaclength = myself->inmaclength; + to->incompression = myself->incompression; + + // Allocate memory for key + to->inkey = xrealloc(to->inkey, to->inkeylength); + + // Create a new key + if(1 != RAND_bytes((unsigned char *)to->inkey, to->inkeylength)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate random for key (%s)", ERR_error_string(err, NULL)); + return false; // Do not send insecure keys, let connection attempt fail. + } + + if(to->incipher) { + EVP_DecryptInit_ex(to->inctx, to->incipher, NULL, (unsigned char *)to->inkey, (unsigned char *)to->inkey + EVP_CIPHER_key_length(to->incipher)); + } + + // Reset sequence number and late packet window + mykeyused = true; + to->received_seqno = 0; + + if(replaywin) { + memset(to->late, 0, replaywin); + } + + // Convert to hexadecimal and send + char key[2 * to->inkeylength + 1]; + bin2hex(to->inkey, key, to->inkeylength); + key[to->inkeylength * 2] = '\0'; + + return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY, + myself->name, to->name, key, + to->incipher ? EVP_CIPHER_nid(to->incipher) : 0, + to->indigest ? EVP_MD_type(to->indigest) : 0, to->inmaclength, + to->incompression); +} + +bool ans_key_h(connection_t *c) { + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + char key[MAX_STRING_SIZE]; + char address[MAX_STRING_SIZE] = ""; + char port[MAX_STRING_SIZE] = ""; + int cipher, digest, maclength, compression; + node_t *from, *to; + + if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING, + from_name, to_name, key, &cipher, &digest, &maclength, + &compression, address, port) < 7) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name, + c->hostname); + return false; + } + + if(!check_id(from_name) || !check_id(to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name"); + return false; + } + + from = lookup_node(from_name); + + if(!from) { + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", + "ANS_KEY", c->name, c->hostname, from_name); + return true; + } + + to = lookup_node(to_name); + + if(!to) { + logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", + "ANS_KEY", c->name, c->hostname, to_name); + return true; + } + + /* Forward it if necessary */ + + if(to != myself) { + if(tunnelserver) { + return true; + } + + if(!to->status.reachable) { + logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", + "ANS_KEY", c->name, c->hostname, to_name); + return true; + } + + if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) { + char *address, *port; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); + sockaddr2str(&from->address, &address, &port); + send_request(to->nexthop->connection, "%s %s %s", c->buffer, address, port); + free(address); + free(port); + return true; + } + + return send_request(to->nexthop->connection, "%s", c->buffer); + } + + /* Don't use key material until every check has passed. */ + from->status.validkey = false; + + /* Update our copy of the origin's packet key */ + from->outkey = xrealloc(from->outkey, strlen(key) / 2); + from->outkeylength = strlen(key) / 2; + + if(!hex2bin(key, from->outkey, from->outkeylength)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key"); + return true; + } + + /* Check and lookup cipher and digest algorithms */ + + if(cipher) { + from->outcipher = EVP_get_cipherbynid(cipher); + + if(!from->outcipher) { + logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, + from->hostname); + return true; + } + + if(from->outkeylength != EVP_CIPHER_key_length(from->outcipher) + EVP_CIPHER_iv_length(from->outcipher)) { + logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, + from->hostname); + return true; + } + } else { + if(from->outkeylength != 1) { + logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname); + return true; + } + + from->outcipher = NULL; + } + + from->outmaclength = maclength; + + if(digest) { + from->outdigest = EVP_get_digestbynid(digest); + + if(!from->outdigest) { + logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, + from->hostname); + return true; + } + + if(from->outmaclength > EVP_MD_size(from->outdigest) || from->outmaclength < 0) { + logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!", + from->name, from->hostname); + return true; + } + } else { + from->outdigest = NULL; + } + + if(compression < 0 || compression > 11) { + logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname); + return true; + } + + from->outcompression = compression; + + if(from->outcipher) + if(!EVP_EncryptInit_ex(from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + EVP_CIPHER_key_length(from->outcipher))) { + logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s", + from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL)); + return true; + } + + from->status.validkey = true; + from->sent_seqno = 0; + + if(*address && *port) { + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); + sockaddr_t sa = str2sockaddr(address, port); + update_node_udp(from, &sa); + } + + if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) { + send_mtu_probe(from); + } + + return true; } diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 9f1a5fb..904ac3f 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -1,7 +1,7 @@ /* protocol_misc.c -- handle the meta-protocol, miscellaneous functions - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2012 Guus Sliepen 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 @@ -13,186 +13,88 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol_misc.c,v 1.1.4.3 2002/03/23 20:21:10 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "conf.h" -#include "net.h" -#include "netutl.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" - #include "system.h" -/* Status and error notification routines */ +#include "conf.h" +#include "connection.h" +#include "logger.h" +#include "meta.h" +#include "net.h" +#include "netutl.h" +#include "protocol.h" +#include "utils.h" -int send_status(connection_t *c, int statusno, char *statusstring) -{ -cp - if(!statusstring) - statusstring = status_text[statusno]; -cp - return send_request(c, "%d %d %s", STATUS, statusno, statusstring); +int maxoutbufsize = 0; + +bool send_ping(connection_t *c) { + c->status.pinged = true; + c->last_ping_time = now; + + return send_request(c, "%d", PING); } -int status_h(connection_t *c) -{ - int statusno; - char statusstring[MAX_STRING_SIZE]; -cp - if(sscanf(c->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS", - c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_STATUS) - { - syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"), - c->name, c->hostname, status_text[statusno], statusstring); - } - -cp - return 0; +bool ping_h(connection_t *c) { + return send_pong(c); } -int send_error(connection_t *c, int err, char *errstring) -{ -cp - if(!errstring) - errstring = strerror(err); - return send_request(c, "%d %d %s", ERROR, err, errstring); +bool send_pong(connection_t *c) { + return send_request(c, "%d", PONG); } -int error_h(connection_t *c) -{ - int err; - char errorstring[MAX_STRING_SIZE]; -cp - if(sscanf(c->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR", - c->name, c->hostname); - return -1; - } +bool pong_h(connection_t *c) { + c->status.pinged = false; - if(debug_lvl >= DEBUG_ERROR) - { - syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"), - c->name, c->hostname, strerror(err), errorstring); - } + /* Successful connection, reset timeout if this is an outgoing connection. */ - terminate_connection(c, c->status.active); -cp - return 0; -} + if(c->outgoing) { + c->outgoing->timeout = 0; + c->outgoing->cfg = NULL; -int send_termreq(connection_t *c) -{ -cp - return send_request(c, "%d", TERMREQ); -} + if(c->outgoing->ai) { + freeaddrinfo(c->outgoing->ai); + } -int termreq_h(connection_t *c) -{ -cp - terminate_connection(c, c->status.active); -cp - return 0; -} + c->outgoing->ai = NULL; + c->outgoing->aip = NULL; + } -int send_ping(connection_t *c) -{ -cp - c->status.pinged = 1; - c->last_ping_time = now; -cp - return send_request(c, "%d", PING); -} - -int ping_h(connection_t *c) -{ -cp - return send_pong(c); -} - -int send_pong(connection_t *c) -{ -cp - return send_request(c, "%d", PONG); -} - -int pong_h(connection_t *c) -{ -cp - c->status.pinged = 0; - - /* Succesful connection, reset timeout if this is an outgoing connection. */ - - if(c->outgoing) - c->outgoing->timeout = 0; -cp - return 0; + return true; } /* Sending and receiving packets via TCP */ -int send_tcppacket(connection_t *c, vpn_packet_t *packet) -{ - int x; -cp - /* Evil hack. */ +bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) { + /* If there already is a lot of data in the outbuf buffer, discard this packet. + We use a very simple Random Early Drop algorithm. */ - x = send_request(c, "%d %hd", PACKET, packet->len); + if(2.0 * c->outbuflen / (float)maxoutbufsize - 1 > (float)rand() / (float)RAND_MAX) { + return true; + } - if(x) - return x; -cp - return send_meta(c, packet->data, packet->len); + if(!send_request(c, "%d %hd", PACKET, packet->len)) { + return false; + } + + return send_meta(c, (char *)packet->data, packet->len) && flush_meta(c); } -int tcppacket_h(connection_t *c) -{ - short int len; -cp - if(sscanf(c->buffer, "%*d %hd", &len) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name, c->hostname); - return -1; - } +bool tcppacket_h(connection_t *c) { + length_t len; - /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */ + if(sscanf(c->buffer, "%*d %hu", &len) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name, + c->hostname); + return false; + } - c->tcplen = len; -cp - return 0; + /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */ + + c->tcplen = len; + + return true; } - -/* Status strings */ - -char (*status_text[]) = { - "Warning", -}; - -/* Error strings */ - -char (*error_text[]) = { - "Error", -}; diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index 7f6cfc1..2c4d08f 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -1,7 +1,8 @@ /* protocol_subnet.c -- handle the meta-protocol, subnets - Copyright (C) 1999-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2009 Guus Sliepen + 2009 Michael Tokarev 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 @@ -13,225 +14,242 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: protocol_subnet.c,v 1.1.4.3 2002/03/22 13:31:18 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conf.h" -#include "net.h" -#include "netutl.h" -#include "protocol.h" -#include "meta.h" -#include "connection.h" -#include "node.h" -#include "edge.h" -#include "graph.h" - #include "system.h" -int send_add_subnet(connection_t *c, subnet_t *subnet) -{ - int x; - char *netstr; -cp - x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(), - subnet->owner->name, netstr = net2str(subnet)); - free(netstr); -cp - return x; +#include "conf.h" +#include "connection.h" +#include "logger.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "protocol.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" + +bool send_add_subnet(connection_t *c, const subnet_t *subnet) { + char netstr[MAXNETSTR]; + + if(!net2str(netstr, sizeof(netstr), subnet)) { + return false; + } + + return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr); } -int add_subnet_h(connection_t *c) -{ - char subnetstr[MAX_STRING_SIZE]; - char name[MAX_STRING_SIZE]; - node_t *owner; - connection_t *other; - subnet_t *s; - avl_node_t *node; -cp - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname); - return -1; - } +bool add_subnet_h(connection_t *c) { + char subnetstr[MAX_STRING_SIZE]; + char name[MAX_STRING_SIZE]; + node_t *owner; + subnet_t s = {0}, *new, *old; - /* Check if owner name is a valid */ + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name, + c->hostname); + return false; + } - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid name")); - return -1; - } + /* Check if owner name is valid */ - /* Check if subnet string is valid */ + if(!check_id(name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_SUBNET", c->name, + c->hostname, "invalid name"); + return false; + } - if(!(s = str2net(subnetstr))) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid subnet string")); - return -1; - } + /* Check if subnet string is valid */ - if(seen_request(c->buffer)) - return 0; - - /* Check if the owner of the new subnet is in the connection list */ + if(!str2net(&s, subnetstr)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_SUBNET", c->name, + c->hostname, "invalid subnet string"); + return false; + } - owner = lookup_node(name); + if(seen_request(c->buffer)) { + return true; + } - if(!owner) - { - owner = new_node(); - owner->name = xstrdup(name); - node_add(owner); - } + /* Check if the owner of the new subnet is in the connection list */ - /* Check if we already know this subnet */ - - if(lookup_subnet(owner, s)) - { - free_subnet(s); - return 0; - } + owner = lookup_node(name); - /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */ + if(tunnelserver && owner != myself && owner != c->node) { + /* in case of tunnelserver, ignore indirect subnet registrations */ + ifdebug(PROTOCOL) logger(LOG_WARNING, "Ignoring indirect %s from %s (%s) for %s", + "ADD_SUBNET", c->name, c->hostname, subnetstr); + return true; + } - if(owner == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "ADD_SUBNET", c->name, c->hostname); - s->owner = myself; - send_del_subnet(c, s); - return 0; - } + if(!owner) { + owner = new_node(); + owner->name = xstrdup(name); + node_add(owner); + } - /* If everything is correct, add the subnet to the list of the owner */ + /* Check if we already know this subnet */ - subnet_add(owner, s); + if(lookup_subnet(owner, &s)) { + return true; + } - /* Tell the rest */ - - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%s", c->buffer); - } -cp - return 0; + /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */ + + if(owner == myself) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", + "ADD_SUBNET", c->name, c->hostname); + s.owner = myself; + send_del_subnet(c, &s); + return true; + } + + /* In tunnel server mode, we should already know all allowed subnets */ + + if(tunnelserver) { + logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s", + "ADD_SUBNET", c->name, c->hostname, subnetstr); + return true; + } + + /* Ignore if strictsubnets is true, but forward it to others */ + + if(strictsubnets) { + logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s", + "ADD_SUBNET", c->name, c->hostname, subnetstr); + forward_request(c); + return true; + } + + /* If everything is correct, add the subnet to the list of the owner */ + + *(new = new_subnet()) = s; + subnet_add(owner, new); + + if(owner->status.reachable) { + subnet_update(owner, new, true); + } + + /* Tell the rest */ + + forward_request(c); + + /* Fast handoff of roaming MAC addresses */ + + if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires) { + old->expires = now; + } + + return true; } -int send_del_subnet(connection_t *c, subnet_t *s) -{ - int x; - char *netstr; -cp - netstr = net2str(s); - x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr); - free(netstr); -cp - return x; +bool send_del_subnet(connection_t *c, const subnet_t *s) { + char netstr[MAXNETSTR]; + + if(!net2str(netstr, sizeof(netstr), s)) { + return false; + } + + return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr); } -int del_subnet_h(connection_t *c) -{ - char subnetstr[MAX_STRING_SIZE]; - char name[MAX_STRING_SIZE]; - node_t *owner; - connection_t *other; - subnet_t *s, *find; - avl_node_t *node; -cp - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname); - return -1; - } +bool del_subnet_h(connection_t *c) { + char subnetstr[MAX_STRING_SIZE]; + char name[MAX_STRING_SIZE]; + node_t *owner; + subnet_t s = {0}, *find; - /* Check if owner name is a valid */ + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_SUBNET", c->name, + c->hostname); + return false; + } - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid name")); - return -1; - } + /* Check if owner name is valid */ - /* Check if the owner of the new subnet is in the connection list */ + if(!check_id(name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_SUBNET", c->name, + c->hostname, "invalid name"); + return false; + } - if(!(owner = lookup_node(name))) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"), - "DEL_SUBNET", c->name, c->hostname, name); - return 0; - } + /* Check if subnet string is valid */ - /* Check if subnet string is valid */ + if(!str2net(&s, subnetstr)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_SUBNET", c->name, + c->hostname, "invalid subnet string"); + return false; + } - if(!(s = str2net(subnetstr))) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid subnet string")); - return -1; - } + if(seen_request(c->buffer)) { + return true; + } - if(seen_request(c->buffer)) - return 0; + /* Check if the owner of the subnet being deleted is in the connection list */ - /* If everything is correct, delete the subnet from the list of the owner */ + owner = lookup_node(name); - s->owner = owner; + if(tunnelserver && owner != myself && owner != c->node) { + /* in case of tunnelserver, ignore indirect subnet deletion */ + ifdebug(PROTOCOL) logger(LOG_WARNING, "Ignoring indirect %s from %s (%s) for %s", + "DEL_SUBNET", c->name, c->hostname, subnetstr); + return true; + } - find = lookup_subnet(owner, s); - - free_subnet(s); + if(!owner) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which is not in our node tree", + "DEL_SUBNET", c->name, c->hostname, name); + return true; + } - if(!find) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"), - "DEL_SUBNET", c->name, c->hostname, name); - return 0; - } - - /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */ - - if(owner == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_SUBNET", c->name, c->hostname); - send_add_subnet(c, find); - return 0; - } + /* If everything is correct, delete the subnet from the list of the owner */ - /* Tell the rest */ - - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_request(other, "%s", c->buffer); - } + s.owner = owner; - /* Finally, delete it. */ + find = lookup_subnet(owner, &s); - subnet_del(owner, find); + if(!find) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree", + "DEL_SUBNET", c->name, c->hostname, name); -cp - return 0; + if(strictsubnets) { + forward_request(c); + } + + return true; + } + + /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */ + + if(owner == myself) { + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", + "DEL_SUBNET", c->name, c->hostname); + send_add_subnet(c, find); + return true; + } + + if(tunnelserver) { + return true; + } + + /* Tell the rest */ + + forward_request(c); + + if(strictsubnets) { + return true; + } + + /* Finally, delete it. */ + + if(owner->status.reachable) { + subnet_update(owner, find, false); + } + + subnet_del(owner, find); + + return true; } diff --git a/src/proxy.c b/src/proxy.c new file mode 100644 index 0000000..979626c --- /dev/null +++ b/src/proxy.c @@ -0,0 +1,366 @@ +/* + proxy.c -- Proxy handling functions. + Copyright (C) 2015-2017 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "connection.h" +#include "logger.h" +#include "meta.h" +#include "netutl.h" +#include "protocol.h" +#include "proxy.h" +#include "utils.h" // + +proxytype_t proxytype; +char *proxyhost; +char *proxyport; +char *proxyuser; +char *proxypass; + +static void update_address_ipv4(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_INET; + + if(address) { + memcpy(&c->address.in.sin_addr, address, sizeof(ipv4_t)); + } + + if(port) { + memcpy(&c->address.in.sin_port, port, sizeof(uint16_t)); + } + + // OpenSSH -D returns all zero address, set it to 0.0.0.1 to prevent spamming ourselves. + if(!memcmp(&c->address.in.sin_addr, "\0\0\0\0", 4)) { + memcpy(&c->address.in.sin_addr, "\0\0\0\01", 4); + } +} + +static void update_address_ipv6(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_INET6; + + if(address) { + memcpy(&c->address.in6.sin6_addr, address, sizeof(ipv6_t)); + } + + if(port) { + memcpy(&c->address.in6.sin6_port, port, sizeof(uint16_t)); + } + + // OpenSSH -D returns all zero address, set it to 0100:: to prevent spamming ourselves. + if(!memcmp(&c->address.in6.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) { + memcpy(&c->address.in6.sin6_addr, "\01\0\0\0\0\0\0\0", 8); + } +} + +bool send_proxyrequest(connection_t *c) { + switch(proxytype) { + case PROXY_SOCKS4: + if(c->address.sa.sa_family != AF_INET) { + logger(LOG_ERR, "Can only connect to numeric IPv4 addresses through a SOCKS 4 proxy!"); + return false; + } + + // fallthrough + case PROXY_SOCKS4A: { + if(c->address.sa.sa_family != AF_INET && c->address.sa.sa_family != AF_UNKNOWN) { + logger(LOG_ERR, "Can only connect to IPv4 addresses or hostnames through a SOCKS 4a proxy!"); + return false; + } + + int len = 9; + + if(proxyuser) { + len += strlen(proxyuser); + } + + if(c->address.sa.sa_family == AF_UNKNOWN) { + len += 1 + strlen(c->address.unknown.address); + } + + char s4req[len]; + s4req[0] = 4; + s4req[1] = 1; + + if(c->address.sa.sa_family == AF_INET) { + memcpy(s4req + 2, &c->address.in.sin_port, 2); + memcpy(s4req + 4, &c->address.in.sin_addr, 4); + } else { + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s4req + 2, &port, 2); + memcpy(s4req + 4, "\0\0\0\1", 4); + strcpy(s4req + (9 + (proxyuser ? strlen(proxyuser) : 0)), c->address.unknown.address); + } + + if(proxyuser) { + strcpy(s4req + 8, proxyuser); + } else { + s4req[8] = 0; + } + + s4req[sizeof(s4req) - 1] = 0; + c->allow_request = PROXY; + return send_meta(c, s4req, sizeof(s4req)); + } + + case PROXY_SOCKS5: { + int len = 3 + 6; + + if(c->address.sa.sa_family == AF_INET) { + len += 4; + } else if(c->address.sa.sa_family == AF_INET6) { + len += 16; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + len += 1 + strlen(c->address.unknown.address); + } else { + logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family); + return false; + } + + if(proxypass) { + len += 3 + strlen(proxyuser) + strlen(proxypass); + } + + char s5req[len]; + int i = 0; + s5req[i++] = 5; + s5req[i++] = 1; + + if(proxypass) { + s5req[i++] = 2; + s5req[i++] = 1; + s5req[i++] = strlen(proxyuser); + strcpy(s5req + i, proxyuser); + i += strlen(proxyuser); + s5req[i++] = strlen(proxypass); + strcpy(s5req + i, proxypass); + i += strlen(proxypass); + } else { + s5req[i++] = 0; + } + + s5req[i++] = 5; + s5req[i++] = 1; + s5req[i++] = 0; + + if(c->address.sa.sa_family == AF_INET) { + s5req[i++] = 1; + memcpy(s5req + i, &c->address.in.sin_addr, 4); + i += 4; + memcpy(s5req + i, &c->address.in.sin_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_INET6) { + s5req[i++] = 4; + memcpy(s5req + i, &c->address.in6.sin6_addr, 16); + i += 16; + memcpy(s5req + i, &c->address.in6.sin6_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + s5req[i++] = 3; + int len = strlen(c->address.unknown.address); + s5req[i++] = len; + memcpy(s5req + i, c->address.unknown.address, len); + i += len; + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s5req + i, &port, 2); + i += 2; + } else { + logger(LOG_ERR, "Unknown address family while trying to connect to SOCKS5 proxy"); + return false; + } + + if(i > len) { + abort(); + } + + c->allow_request = PROXY; + return send_meta(c, s5req, sizeof(s5req)); + } + + case PROXY_HTTP: { + char *host; + char *port; + + sockaddr2str(&c->address, &host, &port); + send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); + free(host); + free(port); + c->allow_request = PROXY; + return true; + } + + case PROXY_EXEC: + abort(); + + default: + logger(LOG_ERR, "Unknown proxy type"); + return false; + } +} + +int receive_proxy_meta(connection_t *c) { + switch(proxytype) { + case PROXY_SOCKS4: + case PROXY_SOCKS4A: + if(c->buflen < 8) { + return 0; + } + + if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) { + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, c->buffer + 4, c->buffer + 2); + } + + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return 8; + } else { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + + case PROXY_SOCKS5: + if(c->buflen < 2) { + return 0; + } + + if(c->buffer[0] != 0x05 || c->buffer[1] == (char)0xff) { + logger(LOG_ERR, "Proxy authentication method rejected"); + return -1; + } + + int offset = 2; + + if(c->buffer[1] == 0x02) { + if(c->buflen < 4) { + return 0; + } + + if(c->buffer[2] != 0x05 || c->buffer[3] != 0x00) { + logger(LOG_ERR, "Proxy username/password rejected"); + return -1; + } + + offset += 2; + } + + if(c->buflen - offset < 7) { + return 0; + } + + if(c->buffer[offset] != 0x05 || c->buffer[offset + 1] != 0x00) { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + + int replen = offset + 6; + + switch(c->buffer[offset + 3]) { + case 0x01: // IPv4 + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, c->buffer + offset + 4, c->buffer + offset + 8); + } + + replen += 4; + break; + + case 0x03: // Hostname + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + } + + replen += ((uint8_t *)c->buffer)[offset + 4]; + break; + + case 0x04: // IPv6 + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv6(c, c->buffer + offset + 4, c->buffer + offset + 20); + } + + replen += 16; + break; + + default: + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + + if(c->buflen < replen) { + return 0; + } else { + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return replen; + } + + case PROXY_HTTP: { + char *p = memchr(c->buffer, '\n', c->buflen); + + if(!p || p - c->buffer >= c->buflen) { + return 0; + } + + while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) { + if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4)) { + break; + } + } + + if(!p) { + return 0; + } + + if(c->buflen < 9) { + return 0; + } + + if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) { + if(!strncmp(c->buffer + 9, "200", 3)) { + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + } + + logger(LOG_DEBUG, "Proxy request granted"); + replen = p + 1 - c->buffer; + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return replen; + } else { + p = memchr(c->buffer, '\n', c->buflen); + p[-1] = 0; + logger(LOG_ERR, "Proxy request rejected: %s", c->buffer + 9); + return false; + } + } else { + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + } + + default: + abort(); + } +} diff --git a/src/proxy.h b/src/proxy.h new file mode 100644 index 0000000..a96fc3d --- /dev/null +++ b/src/proxy.h @@ -0,0 +1,43 @@ +#ifndef TINC_PROXY_H +#define TINC_PROXY_H + +/* + proxy.h -- header for proxy.c + Copyright (C) 2015 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "connection.h" + +typedef enum proxytype_t { + PROXY_NONE = 0, + PROXY_SOCKS4, + PROXY_SOCKS4A, + PROXY_SOCKS5, + PROXY_HTTP, + PROXY_EXEC, +} proxytype_t; + +extern proxytype_t proxytype; +extern char *proxyhost; +extern char *proxyport; +extern char *proxyuser; +extern char *proxypass; + +extern bool send_proxyrequest(struct connection_t *c); +extern int receive_proxy_meta(struct connection_t *c); + +#endif diff --git a/src/raw_socket_device.c b/src/raw_socket_device.c new file mode 100644 index 0000000..f4ed694 --- /dev/null +++ b/src/raw_socket_device.c @@ -0,0 +1,157 @@ +/* + device.c -- raw socket + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2014 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#ifdef HAVE_NETPACKET_PACKET_H +#include +#endif + +#include "conf.h" +#include "device.h" +#include "net.h" +#include "logger.h" +#include "utils.h" +#include "route.h" +#include "xalloc.h" + +#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX) +static const char *device_info = "raw_socket"; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static bool setup_device(void) { + struct ifreq ifr; + struct sockaddr_ll sa; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) { + iface = xstrdup("eth0"); + } + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + device = xstrdup(iface); + } + + if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { + logger(LOG_ERR, "Could not open %s: %s", device_info, + strerror(errno)); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + + if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) { + close(device_fd); + logger(LOG_ERR, "Can't find interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno)); + return false; + } + + memset(&sa, 0, sizeof(sa)); + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons(ETH_P_ALL); + sa.sll_ifindex = ifr.ifr_ifindex; + + if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) { + logger(LOG_ERR, "Could not bind %s to %s: %s", device, ifr.ifr_ifrn.ifrn_name, strerror(errno)); + return false; + } + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} + +static void close_device(void) { + close(device_fd); + + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + if(write(device_fd, packet->data, packet->len) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t raw_socket_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; + +#else + +static bool not_supported(void) { + logger(LOG_ERR, "Raw socket device not supported on this platform"); + return false; +} + +const devops_t raw_socket_devops = { + .setup = not_supported, + .close = NULL, + .read = NULL, + .write = NULL, + .dump_stats = NULL, +}; +#endif diff --git a/src/route.c b/src/route.c index dcf43e4..f8b11bb 100644 --- a/src/route.c +++ b/src/route.c @@ -1,7 +1,8 @@ /* route.c -- routing - Copyright (C) 2000-2002 Ivo Timmermans , - 2000-2002 Guus Sliepen + Copyright (C) 2000-2005 Ivo Timmermans, + 2000-2017 Guus Sliepen + 2015-2016 Vittorio Gambaletta 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 @@ -13,481 +14,1138 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: route.c,v 1.1.2.37 2002/03/19 00:08:23 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) - #include -#endif -#include -#include -#if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD) - #include - #define ETHER_ADDR_LEN 6 -#else - #include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "net.h" -#include "connection.h" -#include "subnet.h" -#include "route.h" -#include "protocol.h" -#include "device.h" - #include "system.h" -int routing_mode = RMODE_ROUTER; -int priorityinheritance = 0; +#include "avl_tree.h" +#include "connection.h" +#include "ethernet.h" +#include "ipv4.h" +#include "ipv6.h" +#include "logger.h" +#include "net.h" +#include "protocol.h" +#include "route.h" +#include "subnet.h" +#include "utils.h" + +rmode_t routing_mode = RMODE_ROUTER; +fmode_t forwarding_mode = FMODE_INTERNAL; +bmode_t broadcast_mode = BMODE_MST; +bool decrement_ttl = false; +bool directonly = false; +bool priorityinheritance = false; int macexpire = 600; -subnet_t mymac; +bool overwrite_mac = false; +mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}}; -void learn_mac(mac_t *address) -{ - subnet_t *subnet; - avl_node_t *node; - connection_t *c; -cp - subnet = lookup_subnet_mac(address); +/* Sizes of various headers */ - /* If we don't know this MAC address yet, store it */ - - if(!subnet || subnet->owner!=myself) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"), - address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]); - - subnet = new_subnet(); - subnet->type = SUBNET_MAC; - memcpy(&subnet->net.mac.address, address, sizeof(mac_t)); - subnet_add(myself, subnet); +static const size_t ether_size = sizeof(struct ether_header); +static const size_t arp_size = sizeof(struct ether_arp); +static const size_t ip_size = sizeof(struct ip); +static const size_t icmp_size = sizeof(struct icmp) - sizeof(struct ip); +static const size_t ip6_size = sizeof(struct ip6_hdr); +static const size_t icmp6_size = sizeof(struct icmp6_hdr); +static const size_t ns_size = sizeof(struct nd_neighbor_solicit); +static const size_t opt_size = sizeof(struct nd_opt_hdr); - /* And tell all other tinc daemons it's our MAC */ - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c->status.active) - send_add_subnet(c, subnet); - } - } +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif - subnet->net.mac.lastseen = now; -} +/* RFC 1071 */ -void age_mac(void) -{ - subnet_t *s; - connection_t *c; - avl_node_t *node, *next, *node2; -cp - for(node = myself->subnet_tree->head; node; node = next) - { - next = node->next; - s = (subnet_t *)node->data; - if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"), - s->net.mac.address.x[0], s->net.mac.address.x[1], s->net.mac.address.x[2], s->net.mac.address.x[3], s->net.mac.address.x[4], s->net.mac.address.x[5]); - for(node2 = connection_tree->head; node2; node2 = node2->next) - { - c = (connection_t *)node2->data; - if(c->status.active) - send_del_subnet(c, s); - } - subnet_del(myself, s); +static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { + uint16_t *p = data; + uint32_t checksum = prevsum ^ 0xFFFF; + + while(len >= 2) { + checksum += *p++; + len -= 2; } - } -cp + + if(len) { + checksum += *(uint8_t *)p; + } + + while(checksum >> 16) { + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + return ~checksum; } -node_t *route_mac(vpn_packet_t *packet) -{ - subnet_t *subnet; -cp - /* Learn source address */ +static bool ratelimit(int frequency) { + static time_t lasttime = 0; + static int count = 0; - learn_mac((mac_t *)(&packet->data[6])); - - /* Lookup destination address */ - - subnet = lookup_subnet_mac((mac_t *)(&packet->data[0])); - - if(subnet) - return subnet->owner; - else - return NULL; -} - -node_t *route_ipv4(vpn_packet_t *packet) -{ - subnet_t *subnet; -cp - if(priorityinheritance) - packet->priority = packet->data[15]; - - subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]); -cp - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"), - packet->data[30], packet->data[31], packet->data[32], packet->data[33]); - } - - return NULL; - } -cp - return subnet->owner; -} - -node_t *route_ipv6(vpn_packet_t *packet) -{ - subnet_t *subnet; -cp - subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]); -cp - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), - ntohs(*(short unsigned int *)&packet->data[38]), - ntohs(*(short unsigned int *)&packet->data[40]), - ntohs(*(short unsigned int *)&packet->data[42]), - ntohs(*(short unsigned int *)&packet->data[44]), - ntohs(*(short unsigned int *)&packet->data[46]), - ntohs(*(short unsigned int *)&packet->data[48]), - ntohs(*(short unsigned int *)&packet->data[50]), - ntohs(*(short unsigned int *)&packet->data[52])); - } - - return NULL; - } -cp - return subnet->owner; -} - -unsigned short int inet_checksum(unsigned short int *data, int len, unsigned short int prevsum) -{ - unsigned long int checksum = prevsum ^ 0xFFFF; - - while(len--) - checksum += ntohs(*data++); - - while(checksum >> 16) - checksum = (checksum & 0xFFFF) + (checksum >> 16); - - return checksum ^ 0xFFFF; -} - -void route_neighborsol(vpn_packet_t *packet) -{ - struct ip6_hdr *hdr; - struct nd_neighbor_solicit *ns; - struct nd_opt_hdr *opt; - subnet_t *subnet; - short unsigned int checksum; - - struct { - struct in6_addr ip6_src; /* source address */ - struct in6_addr ip6_dst; /* destination address */ - uint32_t length; - uint8_t junk[4]; - } pseudo; - -cp - hdr = (struct ip6_hdr *)(packet->data + 14); - ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr)); - opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns)); - - /* First, snatch the source address from the neighbor solicitation packet */ - - memcpy(mymac.net.mac.address.x, packet->data + 6, 6); - - /* Check if this is a valid neighbor solicitation request */ - - if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT || - opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) - { - if(debug_lvl > DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request")); - } - return; - } - - /* Create pseudo header */ - - memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); - memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); - pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); - pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; - pseudo.junk[3] = IPPROTO_ICMPV6; - - /* Generate checksum */ - - checksum = inet_checksum((unsigned short int *)&pseudo, sizeof(pseudo)/2, ~0); - checksum = inet_checksum((unsigned short int *)ns, sizeof(*ns)/2 + 4, checksum); - - if(checksum) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request")); - return; - } - - /* Check if the IPv6 address exists on the VPN */ - - subnet = lookup_subnet_ipv6((ipv6_t *)&ns->nd_ns_target); - - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), - ntohs(((uint16_t *)&ns->nd_ns_target)[0]), ntohs(((uint16_t *)&ns->nd_ns_target)[1]), ntohs(((uint16_t *)&ns->nd_ns_target)[2]), ntohs(((uint16_t *)&ns->nd_ns_target)[3]), - ntohs(((uint16_t *)&ns->nd_ns_target)[4]), ntohs(((uint16_t *)&ns->nd_ns_target)[5]), ntohs(((uint16_t *)&ns->nd_ns_target)[6]), ntohs(((uint16_t *)&ns->nd_ns_target)[7])); - } - - return; - } - - /* Check if it is for our own subnet */ - - if(subnet->owner == myself) - return; /* silently ignore */ - - /* Create neighbor advertation reply */ - - memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ - packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ - - memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */ - memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */ - - memcpy((char *)opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */ - - ns->nd_ns_hdr.icmp6_cksum = 0; - ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT; - ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */ - ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0; - opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; - - /* Create pseudo header */ - - memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); - memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); - pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); - pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; - pseudo.junk[3] = IPPROTO_ICMPV6; - - /* Generate checksum */ - - checksum = inet_checksum((unsigned short int *)&pseudo, sizeof(pseudo)/2, ~0); - checksum = inet_checksum((unsigned short int *)ns, sizeof(*ns)/2 + 4, checksum); - - ns->nd_ns_hdr.icmp6_cksum = htons(checksum); - - write_packet(packet); -cp -} - -void route_arp(vpn_packet_t *packet) -{ - struct ether_arp *arp; - subnet_t *subnet; - unsigned char ipbuf[4]; -cp - /* First, snatch the source address from the ARP packet */ - - memcpy(mymac.net.mac.address.x, packet->data + 6, 6); - - /* This routine generates replies to ARP requests. - You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD). - Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp) - */ - - arp = (struct ether_arp *)(packet->data + 14); - - /* Check if this is a valid ARP request */ - - if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || - ntohs(arp->arp_pro) != ETHERTYPE_IP || - (int) (arp->arp_hln) != ETHER_ADDR_LEN || - (int) (arp->arp_pln) != 4 || - ntohs(arp->arp_op) != ARPOP_REQUEST ) - { - if(debug_lvl > DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request")); - } - return; - } - - /* Check if the IPv4 address exists on the VPN */ - - subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa); - - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"), - arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]); - } - - return; - } - - /* Check if it is for our own subnet */ - - if(subnet->owner == myself) - return; /* silently ignore */ - - memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ - packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ - - memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */ - memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */ - memcpy(arp->arp_spa, ipbuf, 4); /* ... */ - - memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */ - memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */ - arp->arp_op = htons(ARPOP_REPLY); - - write_packet(packet); -cp -} - -void route_outgoing(vpn_packet_t *packet) -{ - unsigned short int type; - node_t *n = NULL; -cp - /* FIXME: multicast? */ - - switch(routing_mode) - { - case RMODE_ROUTER: - type = ntohs(*((unsigned short*)(&packet->data[12]))); - switch(type) - { - case 0x0800: - n = route_ipv4(packet); - break; - case 0x86DD: - if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) - { - route_neighborsol(packet); - return; + if(lasttime == now) { + if(count >= frequency) { + return true; } - n = route_ipv6(packet); - break; - case 0x0806: - route_arp(packet); - return; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type); - } - return; - } - if(n) - send_packet(n, packet); - break; - - case RMODE_SWITCH: - n = route_mac(packet); - if(n) - send_packet(n, packet); - else - broadcast_packet(myself, packet); - break; - - case RMODE_HUB: - broadcast_packet(myself, packet); - break; - } + } else { + lasttime = now; + count = 0; + } + + count++; + return false; } -void route_incoming(node_t *source, vpn_packet_t *packet) -{ - switch(routing_mode) - { - case RMODE_ROUTER: - { - node_t *n = NULL; - unsigned short int type; +static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) { + if(packet->len < length) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname); + return false; + } else { + return true; + } +} - type = ntohs(*((unsigned short*)(&packet->data[12]))); - switch(type) - { - case 0x0800: - n = route_ipv4(packet); - break; - case 0x86DD: - n = route_ipv6(packet); - break; - default: - n = myself; +static void swap_mac_addresses(vpn_packet_t *packet) { + mac_t tmp; + memcpy(&tmp, &packet->data[0], sizeof(tmp)); + memcpy(&packet->data[0], &packet->data[6], sizeof(tmp)); + memcpy(&packet->data[6], &tmp, sizeof(tmp)); +} + +/* RFC 792 */ + +static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { + struct ip ip = {0}; + struct icmp icmp = {0}; + + struct in_addr ip_src; + struct in_addr ip_dst; + uint32_t oldlen; + + if(ratelimit(3)) { + return; + } + + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + + /* Copy headers from packet into properly aligned structs on the stack */ + + memcpy(&ip, packet->data + ether_size, ip_size); + + /* Remember original source and destination */ + + ip_src = ip.ip_src; + ip_dst = ip.ip_dst; + + /* Try to reply with an IP address assigned to the local machine */ + + if(type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if(sockfd != -1) { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr = ip.ip_src; + + if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + socklen_t addrlen = sizeof(addr); + + if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) { + ip_dst = addr.sin_addr; + } + } + + close(sockfd); + } + } + + oldlen = packet->len - ether_size; + + if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { + icmp.icmp_nextmtu = htons(packet->len - ether_size); + } + + if(oldlen >= IP_MSS - ip_size - icmp_size) { + oldlen = IP_MSS - ip_size - icmp_size; + } + + /* Copy first part of original contents to ICMP message */ + + memmove(packet->data + ether_size + ip_size + icmp_size, packet->data + ether_size, oldlen); + + /* Fill in IPv4 header */ + + ip.ip_v = 4; + ip.ip_hl = ip_size / 4; + ip.ip_tos = 0; + ip.ip_len = htons(ip_size + icmp_size + oldlen); + ip.ip_id = 0; + ip.ip_off = 0; + ip.ip_ttl = 255; + ip.ip_p = IPPROTO_ICMP; + ip.ip_sum = 0; + ip.ip_src = ip_dst; + ip.ip_dst = ip_src; + + ip.ip_sum = inet_checksum(&ip, ip_size, ~0); + + /* Fill in ICMP header */ + + icmp.icmp_type = type; + icmp.icmp_code = code; + icmp.icmp_cksum = 0; + + icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0); + icmp.icmp_cksum = inet_checksum(packet->data + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum); + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &ip, ip_size); + memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size); + + packet->len = ether_size + ip_size + icmp_size + oldlen; + + send_packet(source, packet); +} + +/* RFC 2463 */ + +static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { + struct ip6_hdr ip6; + struct icmp6_hdr icmp6 = {0}; + uint16_t checksum; + + struct { + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + uint32_t length; + uint32_t next; + } pseudo; + + if(ratelimit(3)) { + return; + } + + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + + /* Copy headers from packet to structs on the stack */ + + memcpy(&ip6, packet->data + ether_size, ip6_size); + + /* Remember original source and destination */ + + pseudo.ip6_src = ip6.ip6_dst; + pseudo.ip6_dst = ip6.ip6_src; + + /* Try to reply with an IP address assigned to the local machine */ + + if(type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) { + int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + + if(sockfd != -1) { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = ip6.ip6_src; + + if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + socklen_t addrlen = sizeof(addr); + + if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) { + pseudo.ip6_src = addr.sin6_addr; + } + } + + close(sockfd); + } + } + + pseudo.length = packet->len - ether_size; + + if(type == ICMP6_PACKET_TOO_BIG) { + icmp6.icmp6_mtu = htonl(pseudo.length); + } + + if(pseudo.length >= IP_MSS - ip6_size - icmp6_size) { + pseudo.length = IP_MSS - ip6_size - icmp6_size; + } + + /* Copy first part of original contents to ICMP message */ + + memmove(packet->data + ether_size + ip6_size + icmp6_size, packet->data + ether_size, pseudo.length); + + /* Fill in IPv6 header */ + + ip6.ip6_flow = htonl(0x60000000UL); + ip6.ip6_plen = htons(icmp6_size + pseudo.length); + ip6.ip6_nxt = IPPROTO_ICMPV6; + ip6.ip6_hlim = 255; + ip6.ip6_src = pseudo.ip6_src; + ip6.ip6_dst = pseudo.ip6_dst; + + /* Fill in ICMP header */ + + icmp6.icmp6_type = type; + icmp6.icmp6_code = code; + icmp6.icmp6_cksum = 0; + + /* Create pseudo header */ + + pseudo.length = htonl(icmp6_size + pseudo.length); + pseudo.next = htonl(IPPROTO_ICMPV6); + + /* Generate checksum */ + + checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&icmp6, icmp6_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum); + + icmp6.icmp6_cksum = checksum; + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &ip6, ip6_size); + memcpy(packet->data + ether_size + ip6_size, &icmp6, icmp6_size); + + packet->len = ether_size + ip6_size + ntohl(pseudo.length); + + send_packet(source, packet); +} + +static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) { + uint16_t type = packet->data[12] << 8 | packet->data[13]; + length_t ethlen = ether_size; + + if(type == ETH_P_8021Q) { + type = packet->data[16] << 8 | packet->data[17]; + ethlen += 4; + } + + switch(type) { + case ETH_P_IP: + if(!checklength(source, packet, ethlen + ip_size)) { + return false; + } + + if(packet->data[ethlen + 8] <= 1) { + if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED) { + route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL); + } + + return false; + } + + uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; + packet->data[ethlen + 8]--; + uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; + + uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11]; + checksum += old + (~new & 0xFFFF); + + while(checksum >> 16) { + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + packet->data[ethlen + 10] = checksum >> 8; + packet->data[ethlen + 11] = checksum & 0xff; + + return true; + + case ETH_P_IPV6: + if(!checklength(source, packet, ethlen + ip6_size)) { + return false; + } + + if(packet->data[ethlen + 7] <= 1) { + if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED) { + route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT); + } + + return false; + } + + packet->data[ethlen + 7]--; + + return true; + + default: + return true; + } +} + +static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) { + if(!source || !via || !(via->options & OPTION_CLAMP_MSS)) { + return; + } + + uint16_t mtu = source->mtu; + + if(via != myself && via->mtu < mtu) { + mtu = via->mtu; + } + + /* Find TCP header */ + int start = ether_size; + uint16_t type = packet->data[12] << 8 | packet->data[13]; + + if(type == ETH_P_8021Q) { + start += 4; + type = packet->data[16] << 8 | packet->data[17]; + } + + if(type == ETH_P_IP && packet->data[start + 9] == 6) { + start += (packet->data[start] & 0xf) * 4; + } else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6) { + start += 40; + } else { + return; + } + + if(packet->len <= start + 20) { + return; + } + + /* Use data offset field to calculate length of options field */ + int len = ((packet->data[start + 12] >> 4) - 5) * 4; + + if(packet->len < start + 20 + len) { + return; + } + + /* Search for MSS option header */ + for(int i = 0; i < len;) { + if(packet->data[start + 20 + i] == 0) { + break; + } + + if(packet->data[start + 20 + i] == 1) { + i++; + continue; + } + + if(i > len - 2 || i > len - packet->data[start + 21 + i]) { + break; + } + + if(packet->data[start + 20 + i] != 2) { + if(packet->data[start + 21 + i] < 2) { + break; + } + + i += packet->data[start + 21 + i]; + continue; + } + + if(packet->data[start + 21] != 4) { + break; + } + + /* Found it */ + uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i]; + uint16_t newmss = mtu - start - 20; + uint32_t csum = packet->data[start + 16] << 8 | packet->data[start + 17]; + + if(oldmss <= newmss) { + break; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss); + + /* Update the MSS value and the checksum */ + packet->data[start + 22 + i] = newmss >> 8; + packet->data[start + 23 + i] = newmss & 0xff; + csum ^= 0xffff; + csum += oldmss ^ 0xffff; + csum += newmss; + csum = (csum & 0xffff) + (csum >> 16); + csum += csum >> 16; + csum ^= 0xffff; + packet->data[start + 16] = csum >> 8; + packet->data[start + 17] = csum; break; - } - - if(n) - { - if(n == myself) - { - memcpy(packet->data, mymac.net.mac.address.x, 6); - write_packet(packet); - } - else - send_packet(n, packet); - } - } - break; - case RMODE_SWITCH: - { - subnet_t *subnet; - - subnet = lookup_subnet_mac((mac_t *)(&packet->data[0])); - - if(subnet) - { - if(subnet->owner == myself) - write_packet(packet); - else - send_packet(subnet->owner, packet); - } - else - { - broadcast_packet(source, packet); - write_packet(packet); - } - } - break; - case RMODE_HUB: - broadcast_packet(source, packet); /* Spread it on */ - write_packet(packet); - break; - } + } +} + +static void learn_mac(mac_t *address) { + subnet_t *subnet; + avl_node_t *node; + connection_t *c; + + subnet = lookup_subnet_mac(myself, address); + + /* If we don't know this MAC address yet, store it */ + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Learned new MAC address %x:%x:%x:%x:%x:%x", + address->x[0], address->x[1], address->x[2], address->x[3], + address->x[4], address->x[5]); + + subnet = new_subnet(); + subnet->type = SUBNET_MAC; + subnet->expires = now + macexpire; + subnet->net.mac.address = *address; + subnet->weight = 10; + subnet_add(myself, subnet); + subnet_update(myself, subnet, true); + + /* And tell all other tinc daemons it's our MAC */ + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c->status.active) { + send_add_subnet(c, subnet); + } + } + } + + if(subnet->expires) { + subnet->expires = now + macexpire; + } +} + +void age_subnets(void) { + subnet_t *s; + connection_t *c; + avl_node_t *node, *next, *node2; + + for(node = myself->subnet_tree->head; node; node = next) { + next = node->next; + s = node->data; + + if(s->expires && s->expires <= now) { + ifdebug(TRAFFIC) { + char netstr[MAXNETSTR]; + + if(net2str(netstr, sizeof(netstr), s)) { + logger(LOG_INFO, "Subnet %s expired", netstr); + } + } + + for(node2 = connection_tree->head; node2; node2 = node2->next) { + c = node2->data; + + if(c->status.active) { + send_del_subnet(c, s); + } + } + + subnet_update(myself, s, false); + subnet_del(myself, s); + } + } +} + +static void route_broadcast(node_t *source, vpn_packet_t *packet) { + if(decrement_ttl && source != myself) + if(!do_decrement_ttl(source, packet)) { + return; + } + + broadcast_packet(source, packet); +} + +/* RFC 791 */ + +static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) { + struct ip ip; + vpn_packet_t fragment; + int len, maxlen, todo; + uint8_t *offset; + uint16_t ip_off, origf; + + memcpy(&ip, packet->data + ether_size, ip_size); + fragment.priority = packet->priority; + + if(ip.ip_hl != ip_size / 4) { + return; + } + + todo = ntohs(ip.ip_len) - ip_size; + + if(ether_size + ip_size + todo != packet->len) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%d)", packet->len, (int)(ether_size + ip_size + todo)); + return; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Fragmenting packet of %d bytes to %s (%s)", packet->len, dest->name, dest->hostname); + + offset = packet->data + ether_size + ip_size; + maxlen = (MAX(dest->mtu, 590) - ether_size - ip_size) & ~0x7; + ip_off = ntohs(ip.ip_off); + origf = ip_off & ~IP_OFFMASK; + ip_off &= IP_OFFMASK; + + while(todo) { + len = todo > maxlen ? maxlen : todo; + memcpy(fragment.data + ether_size + ip_size, offset, len); + todo -= len; + offset += len; + + ip.ip_len = htons(ip_size + len); + ip.ip_off = htons(ip_off | origf | (todo ? IP_MF : 0)); + ip.ip_sum = 0; + ip.ip_sum = inet_checksum(&ip, ip_size, ~0); + memcpy(fragment.data, packet->data, ether_size); + memcpy(fragment.data + ether_size, &ip, ip_size); + fragment.len = ether_size + ip_size + len; + + send_packet(dest, &fragment); + + ip_off += len / 8; + } +} + +static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) { + subnet_t *subnet; + node_t *via; + ipv4_t dest; + + memcpy(&dest, &packet->data[30], sizeof(dest)); + subnet = lookup_subnet_ipv4(&dest); + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv4 destination address %d.%d.%d.%d", + source->name, source->hostname, + dest.x[0], + dest.x[1], + dest.x[2], + dest.x[3]); + + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN); + return; + } + + if(subnet->owner == source) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname); + return; + } + + if(!subnet->owner->status.reachable) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH); + return; + } + + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO); + return; + } + + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) { + return; + } + + if(priorityinheritance) { + packet->priority = packet->data[15]; + } + + via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; + + if(via == source) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname); + return; + } + + if(directonly && subnet->owner != via) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO); + return; + } + + if(via && packet->len > MAX(via->mtu, 590) && via != myself) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); + + if(packet->data[20] & 0x40) { + packet->len = MAX(via->mtu, 590); + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); + } else { + fragment_ipv4_packet(via, packet, ether_size); + } + + return; + } + + clamp_mss(source, via, packet); + + send_packet(subnet->owner, packet); +} + +static void route_ipv4(node_t *source, vpn_packet_t *packet) { + if(!checklength(source, packet, ether_size + ip_size)) { + return; + } + + if(broadcast_mode && (((packet->data[30] & 0xf0) == 0xe0) || ( + packet->data[30] == 255 && + packet->data[31] == 255 && + packet->data[32] == 255 && + packet->data[33] == 255))) { + route_broadcast(source, packet); + } else { + route_ipv4_unicast(source, packet); + } +} + +static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) { + subnet_t *subnet; + node_t *via; + ipv6_t dest; + + memcpy(&dest, &packet->data[38], sizeof(dest)); + subnet = lookup_subnet_ipv6(&dest); + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", + source->name, source->hostname, + ntohs(dest.x[0]), + ntohs(dest.x[1]), + ntohs(dest.x[2]), + ntohs(dest.x[3]), + ntohs(dest.x[4]), + ntohs(dest.x[5]), + ntohs(dest.x[6]), + ntohs(dest.x[7])); + + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR); + return; + } + + if(subnet->owner == source) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname); + return; + } + + if(!subnet->owner->status.reachable) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE); + return; + } + + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); + return; + } + + if(decrement_ttl && source != myself && subnet->owner != myself) { + if(!do_decrement_ttl(source, packet)) { + return; + } + } + + if(priorityinheritance) { + packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4); + } + + via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; + + if(via == source) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname); + return; + } + + if(directonly && subnet->owner != via) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); + return; + } + + if(via && packet->len > MAX(via->mtu, 1294) && via != myself) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); + packet->len = MAX(via->mtu, 1294); + route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0); + return; + } + + clamp_mss(source, via, packet); + + send_packet(subnet->owner, packet); +} + +/* RFC 2461 */ + +static void route_neighborsol(node_t *source, vpn_packet_t *packet) { + struct ip6_hdr ip6; + struct nd_neighbor_solicit ns; + struct nd_opt_hdr opt; + subnet_t *subnet; + uint16_t checksum; + bool has_opt; + + struct { + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + uint32_t length; + uint32_t next; + } pseudo; + + if(!checklength(source, packet, ether_size + ip6_size + ns_size)) { + return; + } + + has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN; + + if(source != myself) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got neighbor solicitation request from %s (%s) while in router mode!", source->name, source->hostname); + return; + } + + /* Copy headers from packet to structs on the stack */ + + memcpy(&ip6, packet->data + ether_size, ip6_size); + memcpy(&ns, packet->data + ether_size + ip6_size, ns_size); + + if(has_opt) { + memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size); + } + + /* First, snatch the source address from the neighbor solicitation packet */ + + if(overwrite_mac) { + memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN); + } + + /* Check if this is a valid neighbor solicitation request */ + + if(ns.nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT || + (has_opt && opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR)) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type neighbor solicitation request"); + return; + } + + /* Create pseudo header */ + + pseudo.ip6_src = ip6.ip6_src; + pseudo.ip6_dst = ip6.ip6_dst; + + if(has_opt) { + pseudo.length = htonl(ns_size + opt_size + ETH_ALEN); + } else { + pseudo.length = htonl(ns_size); + } + + pseudo.next = htonl(IPPROTO_ICMPV6); + + /* Generate checksum */ + + checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&ns, ns_size, checksum); + + if(has_opt) { + checksum = inet_checksum(&opt, opt_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + } + + if(checksum) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: checksum error for neighbor solicitation request"); + return; + } + + /* Check if the IPv6 address exists on the VPN */ + + subnet = lookup_subnet_ipv6((ipv6_t *) &ns.nd_ns_target); + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", + ntohs(((uint16_t *) &ns.nd_ns_target)[0]), + ntohs(((uint16_t *) &ns.nd_ns_target)[1]), + ntohs(((uint16_t *) &ns.nd_ns_target)[2]), + ntohs(((uint16_t *) &ns.nd_ns_target)[3]), + ntohs(((uint16_t *) &ns.nd_ns_target)[4]), + ntohs(((uint16_t *) &ns.nd_ns_target)[5]), + ntohs(((uint16_t *) &ns.nd_ns_target)[6]), + ntohs(((uint16_t *) &ns.nd_ns_target)[7])); + + return; + } + + /* Check if it is for our own subnet */ + + if(subnet->owner == myself) { + return; /* silently ignore */ + } + + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) { + return; + } + + /* Create neighbor advertation reply */ + + memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */ + packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ + + ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocol address */ + ip6.ip6_src = ns.nd_ns_target; + + if(has_opt) { + memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */ + } + + ns.nd_ns_cksum = 0; + ns.nd_ns_type = ND_NEIGHBOR_ADVERT; + ns.nd_ns_reserved = htonl(0x40000000UL); /* Set solicited flag */ + opt.nd_opt_type = ND_OPT_TARGET_LINKADDR; + + /* Create pseudo header */ + + pseudo.ip6_src = ip6.ip6_src; + pseudo.ip6_dst = ip6.ip6_dst; + + if(has_opt) { + pseudo.length = htonl(ns_size + opt_size + ETH_ALEN); + } else { + pseudo.length = htonl(ns_size); + } + + pseudo.next = htonl(IPPROTO_ICMPV6); + + /* Generate checksum */ + + checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&ns, ns_size, checksum); + + if(has_opt) { + checksum = inet_checksum(&opt, opt_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum); + } + + ns.nd_ns_hdr.icmp6_cksum = checksum; + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &ip6, ip6_size); + memcpy(packet->data + ether_size + ip6_size, &ns, ns_size); + + if(has_opt) { + memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size); + } + + send_packet(source, packet); +} + +static void route_ipv6(node_t *source, vpn_packet_t *packet) { + if(!checklength(source, packet, ether_size + ip6_size)) { + return; + } + + if(packet->data[20] == IPPROTO_ICMPV6 && checklength(source, packet, ether_size + ip6_size + icmp6_size) && packet->data[54] == ND_NEIGHBOR_SOLICIT) { + route_neighborsol(source, packet); + return; + } + + if(broadcast_mode && packet->data[38] == 255) { + route_broadcast(source, packet); + } else { + route_ipv6_unicast(source, packet); + } +} + +/* RFC 826 */ + +static void route_arp(node_t *source, vpn_packet_t *packet) { + struct ether_arp arp; + subnet_t *subnet; + struct in_addr addr; + + if(!checklength(source, packet, ether_size + arp_size)) { + return; + } + + if(source != myself) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got ARP request from %s (%s) while in router mode!", source->name, source->hostname); + return; + } + + /* First, snatch the source address from the ARP packet */ + + if(overwrite_mac) { + memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN); + } + + /* Copy headers from packet to structs on the stack */ + + memcpy(&arp, packet->data + ether_size, arp_size); + + /* Check if this is a valid ARP request */ + + if(ntohs(arp.arp_hrd) != ARPHRD_ETHER || ntohs(arp.arp_pro) != ETH_P_IP || + arp.arp_hln != ETH_ALEN || arp.arp_pln != sizeof(addr) || ntohs(arp.arp_op) != ARPOP_REQUEST) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type ARP request"); + return; + } + + /* Check if the IPv4 address exists on the VPN */ + + subnet = lookup_subnet_ipv4((ipv4_t *) &arp.arp_tpa); + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: ARP request for unknown address %d.%d.%d.%d", + arp.arp_tpa[0], arp.arp_tpa[1], arp.arp_tpa[2], + arp.arp_tpa[3]); + return; + } + + /* Check if it is for our own subnet */ + + if(subnet->owner == myself) { + return; /* silently ignore */ + } + + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) { + return; + } + + memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */ + packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ + + memcpy(&addr, arp.arp_tpa, sizeof(addr)); /* save protocol addr */ + memcpy(arp.arp_tpa, arp.arp_spa, sizeof(addr)); /* swap destination and source protocol address */ + memcpy(arp.arp_spa, &addr, sizeof(addr)); /* ... */ + + memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN); /* set target hard/proto addr */ + memcpy(arp.arp_sha, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */ + arp.arp_op = htons(ARPOP_REPLY); + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &arp, arp_size); + + send_packet(source, packet); +} + +static void route_mac(node_t *source, vpn_packet_t *packet) { + subnet_t *subnet; + mac_t dest; + + /* Learn source address */ + + if(source == myself) { + mac_t src; + memcpy(&src, &packet->data[6], sizeof(src)); + learn_mac(&src); + } + + /* Lookup destination address */ + + memcpy(&dest, &packet->data[0], sizeof(dest)); + subnet = lookup_subnet_mac(NULL, &dest); + + if(!subnet) { + route_broadcast(source, packet); + return; + } + + if(subnet->owner == source) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname); + return; + } + + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { + return; + } + + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) { + return; + } + + uint16_t type = packet->data[12] << 8 | packet->data[13]; + + if(priorityinheritance) { + if(type == ETH_P_IP && packet->len >= ether_size + ip_size) { + packet->priority = packet->data[15]; + } else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size) { + packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4); + } + } + + // Handle packets larger than PMTU + + node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; + + if(directonly && subnet->owner != via) { + return; + } + + if(via && packet->len > via->mtu && via != myself) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); + length_t ethlen = 14; + + if(type == ETH_P_8021Q) { + type = packet->data[16] << 8 | packet->data[17]; + ethlen += 4; + } + + if(type == ETH_P_IP && packet->len > 576 + ethlen) { + if(packet->data[6 + ethlen] & 0x40) { + packet->len = via->mtu; + route_ipv4_unreachable(source, packet, ethlen, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); + } else { + fragment_ipv4_packet(via, packet, ethlen); + } + + return; + } else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) { + packet->len = via->mtu; + route_ipv6_unreachable(source, packet, ethlen, ICMP6_PACKET_TOO_BIG, 0); + return; + } + } + + clamp_mss(source, via, packet); + + send_packet(subnet->owner, packet); +} + +void route(node_t *source, vpn_packet_t *packet) { + if(forwarding_mode == FMODE_KERNEL && source != myself) { + send_packet(myself, packet); + return; + } + + if(!checklength(source, packet, ether_size)) { + return; + } + + switch(routing_mode) { + case RMODE_ROUTER: { + uint16_t type = packet->data[12] << 8 | packet->data[13]; + + switch(type) { + case ETH_P_ARP: + route_arp(source, packet); + break; + + case ETH_P_IP: + route_ipv4(source, packet); + break; + + case ETH_P_IPV6: + route_ipv6(source, packet); + break; + + default: + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown type %hx", source->name, source->hostname, type); + break; + } + } + break; + + case RMODE_SWITCH: + route_mac(source, packet); + break; + + case RMODE_HUB: + route_broadcast(source, packet); + break; + } } diff --git a/src/route.h b/src/route.h index d188af2..5b9e808 100644 --- a/src/route.h +++ b/src/route.h @@ -1,7 +1,10 @@ +#ifndef TINC_ROUTE_H +#define TINC_ROUTE_H + /* route.h -- header file for route.c - Copyright (C) 2000-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 2000-2005 Ivo Timmermans + 2000-2012 Guus Sliepen 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 @@ -13,29 +16,44 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: route.h,v 1.1.2.7 2002/03/01 14:09:31 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_ROUTE_H__ -#define __TINC_ROUTE_H__ +#include "net.h" +#include "node.h" -enum -{ - RMODE_HUB = 0, - RMODE_SWITCH, - RMODE_ROUTER, -}; +typedef enum rmode_t { + RMODE_HUB = 0, + RMODE_SWITCH, + RMODE_ROUTER, +} rmode_t; -extern int routing_mode; -extern int priorityinheritance; +typedef enum fmode_t { + FMODE_OFF = 0, + FMODE_INTERNAL, + FMODE_KERNEL, +} fmode_t; + +typedef enum bmode_t { + BMODE_NONE = 0, + BMODE_MST, + BMODE_DIRECT, +} bmode_t; + +extern rmode_t routing_mode; +extern fmode_t forwarding_mode; +extern bmode_t broadcast_mode; +extern bool decrement_ttl; +extern bool directonly; +extern bool overwrite_mac; +extern bool priorityinheritance; extern int macexpire; -extern void age_mac(void); -extern void route_incoming(node_t *, vpn_packet_t *); -extern void route_outgoing(vpn_packet_t *); +extern mac_t mymac; -#endif /* __TINC_ROUTE_H__ */ +extern void age_subnets(void); +extern void route(struct node_t *source, struct vpn_packet_t *packet); + +#endif diff --git a/src/solaris/device.c b/src/solaris/device.c index 758068d..fa2e6e6 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -1,7 +1,8 @@ /* device.c -- Interaction with Solaris tun device - Copyright (C) 2001-2002 Ivo Timmermans , - 2001-2002 Guus Sliepen + Copyright (C) 2001-2005 Ivo Timmermans, + 2002-2010 OpenVPN Technologies, Inc. + 2001-2017 Guus Sliepen 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 @@ -13,184 +14,417 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "../system.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include +#include -#define DEFAULT_DEVICE "/dev/tun" +#include "../conf.h" +#include "../device.h" +#include "../logger.h" +#include "../net.h" +#include "../route.h" +#include "../utils.h" +#include "../xalloc.h" -#include -#include "conf.h" -#include "net.h" -#include "subnet.h" +#ifndef TUNNEWPPA +#warning Missing net/if_tun.h, using hardcoded value for TUNNEWPPA +#define TUNNEWPPA (('T'<<16) | 0x0001) +#endif -#include "system.h" +#define DEFAULT_TUN_DEVICE "/dev/tun" +#define DEFAULT_TAP_DEVICE "/dev/tap" +#define IP_DEVICE "/dev/udp" + +static enum { + DEVICE_TYPE_TUN, + DEVICE_TYPE_TAP, +} device_type = DEVICE_TYPE_TUN; int device_fd = -1; -int device_type; +static int if_fd = -1; +static int ip_fd = -1; char *device = NULL; -char *interface = NULL; -char ifrname[IFNAMSIZ]; -char *device_info = NULL; +char *iface = NULL; +static const char *device_info = NULL; -int device_total_in = 0; -int device_total_out = 0; +uint64_t device_total_in = 0; +uint64_t device_total_out = 0; -subnet_t mymac; +static bool setup_device(void) { + char *type; -int setup_device(void) -{ - int ip_fd = -1, if_fd = -1; - int ppa; - char *ptr; + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + if(routing_mode == RMODE_ROUTER) { + device = xstrdup(DEFAULT_TUN_DEVICE); + } else { + device = xstrdup(DEFAULT_TAP_DEVICE); + } + } -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; + if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { + if(!strcasecmp(type, "tun")) + /* use default */; + else if(!strcasecmp(type, "tap")) { + device_type = DEVICE_TYPE_TAP; + } else { + logger(LOG_ERR, "Unknown device type %s!", type); + return false; + } + } else { + if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) { + device_type = DEVICE_TYPE_TAP; + } + } -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - ppa = 0; + if(device_type == DEVICE_TYPE_TUN) { + device_info = "Solaris tun device"; + } else { + device_info = "Solaris tap device"; + } - ptr = device; - while(*ptr && !isdigit((int)*ptr)) ptr++; - ppa = atoi(ptr); + if(device_type == DEVICE_TYPE_TAP && routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } - if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){ - syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno)); - return -1; - } + /* The following is black magic copied from OpenVPN. */ - /* Assign a new PPA and get its unit number. */ - if( (ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0){ - syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno)); - return -1; - } + if((ip_fd = open(IP_DEVICE, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", IP_DEVICE, strerror(errno)); + return false; + } - if( (if_fd = open(device, O_RDWR, 0)) < 0){ - syslog(LOG_ERR, _("Could not open %s twice: %s"), device, strerror(errno)); - return -1; - } + if((device_fd = open(device, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno)); + return false; + } - if(ioctl(if_fd, I_PUSH, "ip") < 0){ - syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno)); - return -1; - } + /* Get unit number. */ - /* Assign ppa according to the unit number returned by tun device */ - if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){ - syslog(LOG_ERR, _("Can't set PPA %d: %s"), ppa, strerror(errno)); - return -1; - } + char *ptr = device; + get_config_string(lookup_config(config_tree, "Interface"), &ptr); - if(ioctl(ip_fd, I_LINK, if_fd) < 0){ - syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno)); - return -1; - } + while(*ptr && !isdigit(*ptr)) { + ptr++; + } - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - asprintf(&interface, "tun%d", ppa); + int ppa = atoi(ptr); - device_info = _("Solaris tun device"); + /* Assign a new PPA and get its unit number. */ - /* Set default MAC address for ethertap devices */ + struct strioctl strioc_ppa = { + .ic_cmd = TUNNEWPPA, + .ic_len = sizeof(ppa), + .ic_dp = (char *) &ppa, + }; - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; + if(!*ptr) { /* no number given, try dynamic */ + bool found = false; - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + while(!found && ppa < 64) { + int new_ppa = ioctl(device_fd, I_STR, &strioc_ppa); + + if(new_ppa >= 0) { + ppa = new_ppa; + found = true; + break; + } + + ppa++; + } + + if(!found) { + logger(LOG_ERR, "Could not find free PPA for %s %s!", device_info, device); + return false; + } + } else { /* try this particular one */ + if((ppa = ioctl(device_fd, I_STR, &strioc_ppa)) < 0) { + logger(LOG_ERR, "Could not assign PPA %d for %s %s!", ppa, device_info, device); + return false; + } + } + + if((if_fd = open(device, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno)); + return false; + } + + if(ioctl(if_fd, I_PUSH, "ip") < 0) { + logger(LOG_ERR, "Could not push IP module onto %s %s!", device_info, device); + return false; + } + + xasprintf(&iface, "%s%d", device_type == DEVICE_TYPE_TUN ? "tun" : "tap", ppa); + + { + /* Remove muxes just in case they are left over from a crashed tincd */ + struct lifreq ifr = {}; + strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name)); + + if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) { + int muxid = ifr.lifr_arp_muxid; + ioctl(ip_fd, I_PUNLINK, muxid); + muxid = ifr.lifr_ip_muxid; + ioctl(ip_fd, I_PUNLINK, muxid); + } + } + + if(device_type == DEVICE_TYPE_TUN) { + /* Assign ppa according to the unit number returned by tun device */ + if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) { + logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device); + return false; + } + } + + int arp_fd = -1; + + if(device_type == DEVICE_TYPE_TAP) { + struct lifreq ifr = {}; + + if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) { + logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device); + return false; + } + + strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name)); + ifr.lifr_ppa = ppa; + + /* Assign ppa according to the unit number returned by tun device */ + if(ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0) { + logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device); + return false; + } + + if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) { + logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device); + return false; + } + + /* Push arp module to if_fd */ + if(ioctl(if_fd, I_PUSH, "arp") < 0) { + logger(LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device); + return false; + } + + /* Pop any modules on the stream */ + while(true) { + if(ioctl(ip_fd, I_POP, NULL) < 0) { + break; + } + } + + /* Push arp module to ip_fd */ + if(ioctl(ip_fd, I_PUSH, "arp") < 0) { + logger(LOG_ERR, "Could not push ARP module onto %s!", IP_DEVICE); + return false; + } + + /* Open arp_fd */ + if((arp_fd = open(device, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno)); + return false; + } + + /* Push arp module to arp_fd */ + if(ioctl(arp_fd, I_PUSH, "arp") < 0) { + logger(LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device); + return false; + } + + /* Set ifname to arp */ + struct strioctl strioc_if = { + .ic_cmd = SIOCSLIFNAME, + .ic_len = sizeof(ifr), + .ic_dp = (char *) &ifr, + }; + + if(ioctl(arp_fd, I_STR, &strioc_if) < 0) { + logger(LOG_ERR, "Could not set ifname to %s %s", device_info, device); + return false; + } + } + + int ip_muxid, arp_muxid; + + if((ip_muxid = ioctl(ip_fd, I_PLINK, if_fd)) < 0) { + logger(LOG_ERR, "Could not link %s %s to IP", device_info, device); + return false; + } + + if(device_type == DEVICE_TYPE_TAP) { + if((arp_muxid = ioctl(ip_fd, I_PLINK, arp_fd)) < 0) { + logger(LOG_ERR, "Could not link %s %s to ARP", device_info, device); + return false; + } + + close(arp_fd); + } + + struct lifreq ifr = {}; + + strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name)); + + ifr.lifr_ip_muxid = ip_muxid; + + if(device_type == DEVICE_TYPE_TAP) { + ifr.lifr_arp_muxid = arp_muxid; + } + + if(ioctl(ip_fd, SIOCSLIFMUXID, &ifr) < 0) { + if(device_type == DEVICE_TYPE_TAP) { + ioctl(ip_fd, I_PUNLINK, arp_muxid); + } + + ioctl(ip_fd, I_PUNLINK, ip_muxid); + logger(LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device); + return false; + } + + close(if_fd); + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); + fcntl(ip_fd, F_SETFD, FD_CLOEXEC); +#endif + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; } -void close_device(void) -{ -cp - close(device_fd); +static void close_device(void) { + if(iface) { + struct lifreq ifr = {}; + strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name)); + + if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) { + int muxid = ifr.lifr_arp_muxid; + ioctl(ip_fd, I_PUNLINK, muxid); + muxid = ifr.lifr_ip_muxid; + ioctl(ip_fd, I_PUNLINK, muxid); + } + } + + close(ip_fd); + close(device_fd); + + free(device); + free(iface); } -int read_packet(vpn_packet_t *packet) -{ - int lenin; -cp - if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } +static bool read_packet(vpn_packet_t *packet) { + int result; + struct strbuf sbuf; + int f = 0; - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - packet->data[12] = 0x08; - packet->data[13] = 0x00; + switch(device_type) { + case DEVICE_TYPE_TUN: + sbuf.maxlen = MTU - 14; + sbuf.buf = (char *)packet->data + 14; - packet->len = lenin + 14; + if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); + return false; + } - device_total_in += packet->len; + switch(packet->data[14] >> 4) { + case 4: + packet->data[12] = 0x08; + packet->data[13] = 0x00; + break; - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } + case 6: + packet->data[12] = 0x86; + packet->data[13] = 0xDD; + break; - return 0; -cp + default: + ifdebug(TRAFFIC) logger(LOG_ERR, "Unknown IP version %d while reading packet from %s %s", packet->data[14] >> 4, device_info, device); + return false; + } + + memset(packet->data, 0, 12); + packet->len = sbuf.len + 14; + break; + + case DEVICE_TYPE_TAP: + sbuf.maxlen = MTU; + sbuf.buf = (char *)packet->data; + + if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + packet->len = sbuf.len; + break; + + default: + abort(); + } + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info); + + return true; } -int write_packet(vpn_packet_t *packet) -{ -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info); - if(write(device_fd, packet->data + 14, packet->len - 14) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, strerror(errno)); - return -1; - } + struct strbuf sbuf; - device_total_out += packet->len; -cp - return 0; + switch(device_type) { + case DEVICE_TYPE_TUN: + sbuf.len = packet->len - 14; + sbuf.buf = (char *)packet->data + 14; + + if(putmsg(device_fd, NULL, &sbuf, 0) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_TAP: + sbuf.len = packet->len; + sbuf.buf = (char *)packet->data; + + if(putmsg(device_fd, NULL, &sbuf, 0) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + break; + + default: + abort(); + } + + device_total_out += packet->len; + + return true; } -void dump_device_stats(void) -{ -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } + +const devops_t os_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/subnet.c b/src/subnet.c index 0320957..154fd80 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -1,7 +1,7 @@ /* subnet.c -- handle subnet lookups and lists - Copyright (C) 2000-2002 Guus Sliepen , - 2000-2002 Ivo Timmermans + Copyright (C) 2000-2019 Guus Sliepen , + 2000-2005 Ivo Timmermans 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 @@ -13,382 +13,653 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: subnet.c,v 1.1.2.34 2002/04/09 11:42:48 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conf.h" -#include "net.h" -#include "node.h" -#include "subnet.h" -#include "netutl.h" - #include "system.h" +#include "avl_tree.h" +#include "device.h" +#include "logger.h" +#include "net.h" +#include "netutl.h" +#include "node.h" +#include "process.h" +#include "subnet.h" +#include "utils.h" +#include "xalloc.h" + /* lists type of subnet */ avl_tree_t *subnet_tree; +/* Subnet lookup cache */ + +static ipv4_t cache_ipv4_address[2]; +static subnet_t *cache_ipv4_subnet[2]; +static bool cache_ipv4_valid[2]; +static int cache_ipv4_slot; + +static ipv6_t cache_ipv6_address[2]; +static subnet_t *cache_ipv6_subnet[2]; +static bool cache_ipv6_valid[2]; +static int cache_ipv6_slot; + +static mac_t cache_mac_address[2]; +static subnet_t *cache_mac_subnet[2]; +static bool cache_mac_valid[2]; +static int cache_mac_slot; + +void subnet_cache_flush(void) { + cache_ipv4_valid[0] = cache_ipv4_valid[1] = false; + cache_ipv6_valid[0] = cache_ipv6_valid[1] = false; + cache_mac_valid[0] = cache_mac_valid[1] = false; +} + /* Subnet comparison */ -int subnet_compare_mac(subnet_t *a, subnet_t *b) -{ -cp - return memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t)); +static int subnet_compare_mac(const subnet_t *a, const subnet_t *b) { + int result; + + result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t)); + + if(result) { + return result; + } + + result = a->weight - b->weight; + + if(result || !a->owner || !b->owner) { + return result; + } + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare_ipv4(subnet_t *a, subnet_t *b) -{ - int result; -cp - result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t)); - - if(result) - return result; +static int subnet_compare_ipv4(const subnet_t *a, const subnet_t *b) { + int result; - return a->net.ipv4.prefixlength - b->net.ipv4.prefixlength; + result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength; + + if(result) { + return result; + } + + result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t)); + + if(result) { + return result; + } + + result = a->weight - b->weight; + + if(result || !a->owner || !b->owner) { + return result; + } + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare_ipv6(subnet_t *a, subnet_t *b) -{ - int result; -cp - result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t)); - - if(result) - return result; +static int subnet_compare_ipv6(const subnet_t *a, const subnet_t *b) { + int result; - return a->net.ipv6.prefixlength - b->net.ipv6.prefixlength; + result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength; + + if(result) { + return result; + } + + result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t)); + + if(result) { + return result; + } + + result = a->weight - b->weight; + + if(result || !a->owner || !b->owner) { + return result; + } + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare(subnet_t *a, subnet_t *b) -{ - int result; -cp - result = a->type - b->type; - - if(result) - return result; - - switch(a->type) - { - case SUBNET_MAC: - return subnet_compare_mac(a, b); - case SUBNET_IPV4: - return subnet_compare_ipv4(a, b); - case SUBNET_IPV6: - return subnet_compare_ipv6(a, b); - default: - syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"), a->type); - cp_trace(); - exit(0); - } +int subnet_compare(const subnet_t *a, const subnet_t *b) { + int result; - return 0; + result = a->type - b->type; + + if(result) { + return result; + } + + switch(a->type) { + case SUBNET_MAC: + return subnet_compare_mac(a, b); + + case SUBNET_IPV4: + return subnet_compare_ipv4(a, b); + + case SUBNET_IPV6: + return subnet_compare_ipv6(a, b); + + default: + logger(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!", + a->type); + exit(0); + } + + return 0; } /* Initialising trees */ -void init_subnets(void) -{ -cp - subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, (avl_action_t)free_subnet); -cp +void init_subnets(void) { + subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet); + + subnet_cache_flush(); } -void exit_subnets(void) -{ -cp - avl_delete_tree(subnet_tree); -cp +void exit_subnets(void) { + avl_delete_tree(subnet_tree); } -avl_tree_t *new_subnet_tree(void) -{ -cp - return avl_alloc_tree((avl_compare_t)subnet_compare, NULL); -cp +avl_tree_t *new_subnet_tree(void) { + return avl_alloc_tree((avl_compare_t) subnet_compare, NULL); } -void free_subnet_tree(avl_tree_t *subnet_tree) -{ -cp - avl_delete_tree(subnet_tree); -cp +void free_subnet_tree(avl_tree_t *subnet_tree) { + avl_delete_tree(subnet_tree); } /* Allocating and freeing space for subnets */ -subnet_t *new_subnet(void) -{ -cp - return (subnet_t *)xmalloc(sizeof(subnet_t)); +subnet_t *new_subnet(void) { + return xmalloc_and_zero(sizeof(subnet_t)); } -void free_subnet(subnet_t *subnet) -{ -cp - free(subnet); +void free_subnet(subnet_t *subnet) { + free(subnet); } /* Adding and removing subnets */ -void subnet_add(node_t *n, subnet_t *subnet) -{ -cp - subnet->owner = n; +void subnet_add(node_t *n, subnet_t *subnet) { + subnet->owner = n; - avl_insert(subnet_tree, subnet); -cp - avl_insert(n->subnet_tree, subnet); -cp + avl_insert(subnet_tree, subnet); + avl_insert(n->subnet_tree, subnet); + + subnet_cache_flush(); } -void subnet_del(node_t *n, subnet_t *subnet) -{ -cp - avl_delete(n->subnet_tree, subnet); -cp - avl_delete(subnet_tree, subnet); -cp +void subnet_del(node_t *n, subnet_t *subnet) { + avl_delete(n->subnet_tree, subnet); + avl_delete(subnet_tree, subnet); + + subnet_cache_flush(); } /* Ascii representation of subnets */ -subnet_t *str2net(char *subnetstr) -{ - int i, l; - subnet_t *subnet; - unsigned short int x[8]; -cp - subnet = new_subnet(); -cp - if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d", - &x[0], &x[1], &x[2], &x[3], - &l) == 5) - { - subnet->type = SUBNET_IPV4; - subnet->net.ipv4.prefixlength = l; - for(i = 0; i < 4; i++) - subnet->net.ipv4.address.x[i] = x[i]; - return subnet; - } - - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], - &l) == 9) - { - subnet->type = SUBNET_IPV6; - subnet->net.ipv6.prefixlength = l; - for(i = 0; i < 8; i++) - subnet->net.ipv6.address.x[i] = htons(x[i]); - return subnet; - } +bool str2net(subnet_t *subnet, const char *subnetstr) { + char str[1024]; + strncpy(str, subnetstr, sizeof(str)); + str[sizeof(str) - 1] = 0; + int consumed; - if(sscanf(subnetstr, "%hu.%hu.%hu.%hu", - &x[0], &x[1], &x[2], &x[3]) == 4) - { - subnet->type = SUBNET_IPV4; - subnet->net.ipv4.prefixlength = 32; - for(i = 0; i < 4; i++) - subnet->net.ipv4.address.x[i] = x[i]; - return subnet; - } - - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8) - { - subnet->type = SUBNET_IPV6; - subnet->net.ipv6.prefixlength = 128; - for(i = 0; i < 8; i++) - subnet->net.ipv6.address.x[i] = htons(x[i]); - return subnet; - } + int weight = 10; + char *weight_separator = strchr(str, '#'); - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6) - { - subnet->type = SUBNET_MAC; - for(i = 0; i < 6; i++) - subnet->net.mac.address.x[i] = x[i]; - return subnet; - } + if(weight_separator) { + char *weight_str = weight_separator + 1; - free(subnet); - return NULL; + if(sscanf(weight_str, "%d%n", &weight, &consumed) < 1) { + return false; + } + + if(weight_str[consumed]) { + return false; + } + + *weight_separator = 0; + } + + int prefixlength = -1; + char *prefixlength_separator = strchr(str, '/'); + + if(prefixlength_separator) { + char *prefixlength_str = prefixlength_separator + 1; + + if(sscanf(prefixlength_str, "%d%n", &prefixlength, &consumed) < 1) { + return false; + } + + if(prefixlength_str[consumed]) { + return false; + } + + *prefixlength_separator = 0; + + if(prefixlength < 0) { + return false; + } + } + + uint16_t x[8]; + + if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx%n", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &consumed) >= 6 && !str[consumed]) { + /* + Normally we should check that each part has two digits to prevent ambiguities. + However, in old tinc versions net2str() will aggressively return MAC addresses with one-digit parts, + so we have to accept them otherwise we would be unable to parse ADD_SUBNET messages. + */ + if(prefixlength >= 0) { + return false; + } + + subnet->type = SUBNET_MAC; + subnet->weight = weight; + + for(int i = 0; i < 6; i++) { + subnet->net.mac.address.x[i] = x[i]; + } + + return true; + } + + if(sscanf(str, "%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !str[consumed]) { + if(prefixlength == -1) { + prefixlength = 32; + } + + if(prefixlength > 32) { + return false; + } + + subnet->type = SUBNET_IPV4; + subnet->net.ipv4.prefixlength = prefixlength; + subnet->weight = weight; + + for(int i = 0; i < 4; i++) { + if(x[i] > 255) { + return false; + } + + subnet->net.ipv4.address.x[i] = x[i]; + } + + return true; + } + + /* IPv6 */ + + char *last_colon = strrchr(str, ':'); + + if(last_colon && sscanf(last_colon, ":%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !last_colon[consumed]) { + /* Dotted quad suffix notation, convert to standard IPv6 notation */ + for(int i = 0; i < 4; i++) + if(x[i] > 255) { + return false; + } + + snprintf(last_colon, sizeof(str) - (last_colon - str), ":%02x%02x:%02x%02x", x[0], x[1], x[2], x[3]); + } + + char *double_colon = strstr(str, "::"); + + if(double_colon) { + /* Figure out how many zero groups we need to expand */ + int zero_group_count = 8; + + for(const char *cur = str; *cur; cur++) + if(*cur != ':') { + zero_group_count--; + + while(cur[1] && cur[1] != ':') { + cur++; + } + } + + if(zero_group_count < 1) { + return false; + } + + /* Split the double colon in the middle to make room for zero groups */ + double_colon++; + memmove(double_colon + (zero_group_count * 2 - 1), double_colon, strlen(double_colon) + 1); + + /* Write zero groups in the resulting gap, overwriting the second colon */ + for(int i = 0; i < zero_group_count; i++) { + memcpy(&double_colon[i * 2], "0:", 2); + } + + /* Remove any leading or trailing colons */ + if(str[0] == ':') { + memmove(&str[0], &str[1], strlen(&str[1]) + 1); + } + + if(str[strlen(str) - 1] == ':') { + str[strlen(str) - 1] = 0; + } + } + + if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx%n", + &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &consumed) >= 8 && !str[consumed]) { + if(prefixlength == -1) { + prefixlength = 128; + } + + if(prefixlength > 128) { + return false; + } + + subnet->type = SUBNET_IPV6; + subnet->net.ipv6.prefixlength = prefixlength; + subnet->weight = weight; + + for(int i = 0; i < 8; i++) { + subnet->net.ipv6.address.x[i] = htons(x[i]); + } + + return true; + } + + return false; } -char *net2str(subnet_t *subnet) -{ - char *netstr; -cp - switch(subnet->type) - { - case SUBNET_MAC: - asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx", - subnet->net.mac.address.x[0], - subnet->net.mac.address.x[1], - subnet->net.mac.address.x[2], - subnet->net.mac.address.x[3], - subnet->net.mac.address.x[4], - subnet->net.mac.address.x[5]); - break; - case SUBNET_IPV4: - asprintf(&netstr, "%hu.%hu.%hu.%hu/%d", - subnet->net.ipv4.address.x[0], - subnet->net.ipv4.address.x[1], - subnet->net.ipv4.address.x[2], - subnet->net.ipv4.address.x[3], - subnet->net.ipv4.prefixlength); - break; - case SUBNET_IPV6: - asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", - ntohs(subnet->net.ipv6.address.x[0]), - ntohs(subnet->net.ipv6.address.x[1]), - ntohs(subnet->net.ipv6.address.x[2]), - ntohs(subnet->net.ipv6.address.x[3]), - ntohs(subnet->net.ipv6.address.x[4]), - ntohs(subnet->net.ipv6.address.x[5]), - ntohs(subnet->net.ipv6.address.x[6]), - ntohs(subnet->net.ipv6.address.x[7]), - subnet->net.ipv6.prefixlength); - break; - default: - syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exitting!"), subnet->type); - cp_trace(); - exit(0); - } -cp - return netstr; +bool net2str(char *netstr, int len, const subnet_t *subnet) { + if(!netstr || !subnet) { + logger(LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", (void *)netstr, (void *)subnet); + return false; + } + + switch(subnet->type) { + case SUBNET_MAC: + snprintf(netstr, len, "%x:%x:%x:%x:%x:%x#%d", + subnet->net.mac.address.x[0], + subnet->net.mac.address.x[1], + subnet->net.mac.address.x[2], + subnet->net.mac.address.x[3], + subnet->net.mac.address.x[4], + subnet->net.mac.address.x[5], + subnet->weight); + break; + + case SUBNET_IPV4: + snprintf(netstr, len, "%u.%u.%u.%u/%d#%d", + subnet->net.ipv4.address.x[0], + subnet->net.ipv4.address.x[1], + subnet->net.ipv4.address.x[2], + subnet->net.ipv4.address.x[3], + subnet->net.ipv4.prefixlength, + subnet->weight); + break; + + case SUBNET_IPV6: + snprintf(netstr, len, "%x:%x:%x:%x:%x:%x:%x:%x/%d#%d", + ntohs(subnet->net.ipv6.address.x[0]), + ntohs(subnet->net.ipv6.address.x[1]), + ntohs(subnet->net.ipv6.address.x[2]), + ntohs(subnet->net.ipv6.address.x[3]), + ntohs(subnet->net.ipv6.address.x[4]), + ntohs(subnet->net.ipv6.address.x[5]), + ntohs(subnet->net.ipv6.address.x[6]), + ntohs(subnet->net.ipv6.address.x[7]), + subnet->net.ipv6.prefixlength, + subnet->weight); + break; + + default: + logger(LOG_ERR, + "net2str() was called with unknown subnet type %d, exiting!", + subnet->type); + exit(0); + } + + return true; } /* Subnet lookup routines */ -subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet) -{ -cp - return avl_search(owner->subnet_tree, subnet); +subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) { + return avl_search(owner->subnet_tree, subnet); } -subnet_t *lookup_subnet_mac(mac_t *address) -{ - subnet_t subnet, *p; -cp - subnet.type = SUBNET_MAC; - memcpy(&subnet.net.mac.address, address, sizeof(mac_t)); +subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) { + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; - p = (subnet_t *)avl_search(subnet_tree, &subnet); -cp - return p; + // Check if this address is cached + + for(i = 0; i < 2; i++) { + if(!cache_mac_valid[i]) { + continue; + } + + if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner) { + continue; + } + + if(!memcmp(address, &cache_mac_address[i], sizeof(*address))) { + return cache_mac_subnet[i]; + } + } + + // Search all subnets for a matching one + + for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) { + p = n->data; + + if(!p || p->type != SUBNET_MAC) { + continue; + } + + if(!memcmp(address, &p->net.mac.address, sizeof(*address))) { + r = p; + + if(p->owner->status.reachable) { + break; + } + } + } + + // Cache the result + + cache_mac_slot = !cache_mac_slot; + memcpy(&cache_mac_address[cache_mac_slot], address, sizeof(*address)); + cache_mac_subnet[cache_mac_slot] = r; + cache_mac_valid[cache_mac_slot] = true; + + return r; } -subnet_t *lookup_subnet_ipv4(ipv4_t *address) -{ - subnet_t subnet, *p; -cp - subnet.type = SUBNET_IPV4; - memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t)); - subnet.net.ipv4.prefixlength = 32; +subnet_t *lookup_subnet_ipv4(const ipv4_t *address) { + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; - do - { - /* Go find subnet */ - - p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet); + // Check if this address is cached - /* Check if the found subnet REALLY matches */ -cp - if(p) - { - if(p->type != SUBNET_IPV4) - { - p = NULL; - break; - } + for(i = 0; i < 2; i++) { + if(!cache_ipv4_valid[i]) { + continue; + } - if (!maskcmp((char *)address, (char *)&p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t))) - break; - else - { - /* Otherwise, see if there is a bigger enclosing subnet */ + if(!memcmp(address, &cache_ipv4_address[i], sizeof(*address))) { + return cache_ipv4_subnet[i]; + } + } - subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1; - maskcpy((char *)&subnet.net.ipv4.address, (char *)&p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t)); - } - } - } while (p); -cp - return p; + // Search all subnets for a matching one + + for(n = subnet_tree->head; n; n = n->next) { + p = n->data; + + if(!p || p->type != SUBNET_IPV4) { + continue; + } + + if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) { + r = p; + + if(p->owner->status.reachable) { + break; + } + } + } + + // Cache the result + + cache_ipv4_slot = !cache_ipv4_slot; + memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof(*address)); + cache_ipv4_subnet[cache_ipv4_slot] = r; + cache_ipv4_valid[cache_ipv4_slot] = true; + + return r; } -subnet_t *lookup_subnet_ipv6(ipv6_t *address) -{ - subnet_t subnet, *p; -cp - subnet.type = SUBNET_IPV6; - memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t)); - subnet.net.ipv6.prefixlength = 128; - - do - { - /* Go find subnet */ - - p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet); +subnet_t *lookup_subnet_ipv6(const ipv6_t *address) { + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; - /* Check if the found subnet REALLY matches */ + // Check if this address is cached -cp - if(p) - { - if(p->type != SUBNET_IPV6) - return NULL; + for(i = 0; i < 2; i++) { + if(!cache_ipv6_valid[i]) { + continue; + } - if (!maskcmp((char *)address, (char *)&p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t))) - break; - else - { - /* Otherwise, see if there is a bigger enclosing subnet */ + if(!memcmp(address, &cache_ipv6_address[i], sizeof(*address))) { + return cache_ipv6_subnet[i]; + } + } - subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1; - maskcpy((char *)&subnet.net.ipv6.address, (char *)&p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)); - } - } - } while (p); -cp - return p; + // Search all subnets for a matching one + + for(n = subnet_tree->head; n; n = n->next) { + p = n->data; + + if(!p || p->type != SUBNET_IPV6) { + continue; + } + + if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) { + r = p; + + if(p->owner->status.reachable) { + break; + } + } + } + + // Cache the result + + cache_ipv6_slot = !cache_ipv6_slot; + memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof(*address)); + cache_ipv6_subnet[cache_ipv6_slot] = r; + cache_ipv6_valid[cache_ipv6_slot] = true; + + return r; } -void dump_subnets(void) -{ - char *netstr; - subnet_t *subnet; - avl_node_t *node; -cp - syslog(LOG_DEBUG, _("Subnet list:")); - for(node = subnet_tree->head; node; node = node->next) - { - subnet = (subnet_t *)node->data; - netstr = net2str(subnet); - syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name); - free(netstr); - } - syslog(LOG_DEBUG, _("End of subnet list.")); -cp +void subnet_update(node_t *owner, subnet_t *subnet, bool up) { + avl_node_t *node; + int i; + char *envp[10] = {NULL}; + char netstr[MAXNETSTR]; + char *name, *address, *port; + char empty[] = ""; + + // Prepare environment variables to be passed to the script + + xasprintf(&envp[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); + xasprintf(&envp[3], "NODE=%s", owner->name); + xasprintf(&envp[4], "NAME=%s", myself->name); + + if(owner != myself) { + sockaddr2str(&owner->address, &address, &port); + // 5 and 6 are reserved for SUBNET and WEIGHT + xasprintf(&envp[7], "REMOTEADDRESS=%s", address); + xasprintf(&envp[8], "REMOTEPORT=%s", port); + free(port); + free(address); + } + + name = up ? "subnet-up" : "subnet-down"; + + if(!subnet) { + for(node = owner->subnet_tree->head; node; node = node->next) { + subnet = node->data; + + if(!net2str(netstr, sizeof(netstr), subnet)) { + continue; + } + + // Strip the weight from the subnet, and put it in its own environment variable + char *weight = strchr(netstr, '#'); + + if(weight) { + *weight++ = 0; + } else { + weight = empty; + } + + // Prepare the SUBNET and WEIGHT variables + free(envp[5]); + free(envp[6]); + + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); + + execute_script(name, envp); + } + } else { + if(net2str(netstr, sizeof(netstr), subnet)) { + // Strip the weight from the subnet, and put it in its own environment variable + char *weight = strchr(netstr, '#'); + + if(weight) { + *weight++ = 0; + } else { + weight = empty; + } + + // Prepare the SUBNET and WEIGHT variables + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); + + execute_script(name, envp); + } + } + + for(i = 0; i < 9; i++) { + free(envp[i]); + } +} + +void dump_subnets(void) { + char netstr[MAXNETSTR]; + subnet_t *subnet; + avl_node_t *node; + + logger(LOG_DEBUG, "Subnet list:"); + + for(node = subnet_tree->head; node; node = node->next) { + subnet = node->data; + + if(!net2str(netstr, sizeof(netstr), subnet)) { + continue; + } + + logger(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name); + } + + logger(LOG_DEBUG, "End of subnet list."); } diff --git a/src/subnet.h b/src/subnet.h index be20315..6fecca3 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -1,7 +1,10 @@ +#ifndef TINC_SUBNET_H +#define TINC_SUBNET_H + /* subnet.h -- header for subnet.c - Copyright (C) 2000,2001 Guus Sliepen , - 2000,2001 Ivo Timmermans + Copyright (C) 2000-2009 Guus Sliepen , + 2000-2005 Ivo Timmermans 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 @@ -13,76 +16,72 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: subnet.h,v 1.1.2.18 2002/04/09 11:42:48 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_SUBNET_H__ -#define __TINC_SUBNET_H__ - #include "net.h" -enum -{ - SUBNET_MAC = 0, - SUBNET_IPV4, - SUBNET_IPV6, - SUBNET_TYPES /* Guardian */ -}; +typedef enum subnet_type_t { + SUBNET_MAC = 0, + SUBNET_IPV4, + SUBNET_IPV6, + SUBNET_TYPES, /* Guardian */ +} subnet_type_t; -typedef struct subnet_mac_t -{ - mac_t address; - time_t lastseen; +typedef struct subnet_mac_t { + mac_t address; } subnet_mac_t; -typedef struct subnet_ipv4_t -{ - ipv4_t address; - int prefixlength; +typedef struct subnet_ipv4_t { + ipv4_t address; + int prefixlength; } subnet_ipv4_t; -typedef struct subnet_ipv6_t -{ - ipv6_t address; - int prefixlength; +typedef struct subnet_ipv6_t { + ipv6_t address; + int prefixlength; } subnet_ipv6_t; #include "node.h" typedef struct subnet_t { - struct node_t *owner; /* the owner of this subnet */ - struct node_t *uplink; /* the uplink which we should send packets to for this subnet */ + struct node_t *owner; /* the owner of this subnet */ - int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ + subnet_type_t type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ + time_t expires; /* expiry time */ + int weight; /* weight (higher value is higher priority) */ - /* And now for the actual subnet: */ + /* And now for the actual subnet: */ - union net - { - subnet_mac_t mac; - subnet_ipv4_t ipv4; - subnet_ipv6_t ipv6; - } net; + union net { + subnet_mac_t mac; + subnet_ipv4_t ipv4; + subnet_ipv6_t ipv6; + } net; } subnet_t; -extern subnet_t *new_subnet(void); -extern void free_subnet(subnet_t *); +#define MAXNETSTR 64 + +extern avl_tree_t *subnet_tree; + +extern subnet_t *new_subnet(void) __attribute__((__malloc__)); +extern void free_subnet(subnet_t *subnet); extern void init_subnets(void); extern void exit_subnets(void); -extern avl_tree_t *new_subnet_tree(void); -extern void free_subnet_tree(avl_tree_t *); -extern void subnet_add(struct node_t *, subnet_t *); -extern void subnet_del(struct node_t *, subnet_t *); -extern char *net2str(subnet_t *); -extern subnet_t *str2net(char *); -extern subnet_t *lookup_subnet(struct node_t *, subnet_t *); -extern subnet_t *lookup_subnet_mac(mac_t *); -extern subnet_t *lookup_subnet_ipv4(ipv4_t *); -extern subnet_t *lookup_subnet_ipv6(ipv6_t *); +extern avl_tree_t *new_subnet_tree(void) __attribute__((__malloc__)); +extern void free_subnet_tree(avl_tree_t *subnet_tree); +extern void subnet_add(struct node_t *owner, subnet_t *subnet); +extern void subnet_del(struct node_t *owner, subnet_t *subnet); +extern void subnet_update(struct node_t *owner, subnet_t *subnet, bool up); +extern bool net2str(char *netstr, int len, const subnet_t *subnet); +extern bool str2net(subnet_t *subnet, const char *netstr); +extern subnet_t *lookup_subnet(const struct node_t *owner, const subnet_t *subnet); +extern subnet_t *lookup_subnet_mac(const struct node_t *owner, const mac_t *address); +extern subnet_t *lookup_subnet_ipv4(const ipv4_t *address); +extern subnet_t *lookup_subnet_ipv6(const ipv6_t *address); extern void dump_subnets(void); +extern void subnet_cache_flush(void); -#endif /* __TINC_SUBNET_H__ */ +#endif diff --git a/src/system.h b/src/system.h new file mode 100644 index 0000000..14db7f5 --- /dev/null +++ b/src/system.h @@ -0,0 +1,40 @@ +#ifndef TINC_SYSTEM_H +#define TINC_SYSTEM_H + +/* + system.h -- system headers + Copyright (C) 1998-2005 Ivo Timmermans + 2003-2006 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "config.h" + +#include "have.h" + +#ifndef HAVE_STRSIGNAL +# define strsignal(p) "" +#endif + +/* Other functions */ + +#include "dropin.h" + +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + +#endif diff --git a/src/tincd.c b/src/tincd.c index b8b2959..066ad9c 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -1,7 +1,11 @@ /* tincd.c -- the main file for tincd - Copyright (C) 1998-2002 Ivo Timmermans - 2000-2002 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans + 2000-2019 Guus Sliepen + 2008 Max Rijevski + 2009 Michael Tokarev + 2010 Julien Muchembled + 2010 Timothy Redaelli 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 @@ -13,56 +17,67 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: tincd.c,v 1.10.4.58 2002/03/11 11:23:04 guus Exp $ + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "system.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/* Darwin (MacOS/X) needs the following definition... */ +#ifndef _P1003_1B_VISIBLE +#define _P1003_1B_VISIBLE +#endif -#ifdef HAVE_SYS_IOCTL_H -# include +#ifdef HAVE_SYS_MMAN_H +#include #endif #include #include #include #include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include -#include -#include +#ifdef HAVE_LZO +#include LZO1X_H +#endif + +#ifndef HAVE_MINGW +#include +#include +#include +#endif + +#ifdef HAVE_GETOPT_LONG +#include +#else +#include "getopt.h" +#endif + +#include "pidfile.h" #include "conf.h" +#include "device.h" +#include "logger.h" #include "net.h" #include "netutl.h" #include "process.h" #include "protocol.h" -#include "subnet.h" - -#include "system.h" +#include "utils.h" +#include "xalloc.h" /* The name this program was run with. */ -char *program_name; +char *program_name = NULL; /* If nonzero, display usage information and exit. */ -int show_help; +bool show_help = false; /* If nonzero, print the version on standard output and exit. */ -int show_version; +bool show_version = false; /* If nonzero, it will attempt to kill a running tincd and exit. */ int kill_tincd = 0; @@ -71,330 +86,745 @@ int kill_tincd = 0; int generate_keys = 0; /* If nonzero, use null ciphers and skip all key exchanges. */ -int bypass_security = 0; +bool bypass_security = false; -char *identname; /* program name for syslog */ -char *pidfilename; /* pid file location */ -char **g_argv; /* a copy of the cmdline arguments */ -char **environment; /* A pointer to the environment on - startup */ +/* If nonzero, disable swapping for this process. */ +bool do_mlock = false; -static struct option const long_options[] = -{ - { "config", required_argument, NULL, 'c' }, - { "kill", optional_argument, NULL, 'k' }, - { "net", required_argument, NULL, 'n' }, - { "help", no_argument, &show_help, 1 }, - { "version", no_argument, &show_version, 1 }, - { "no-detach", no_argument, &do_detach, 0 }, - { "generate-keys", optional_argument, NULL, 'K'}, - { "debug", optional_argument, NULL, 'd'}, - { "bypass-security", no_argument, &bypass_security, 1 }, - { NULL, 0, NULL, 0 } +/* If nonzero, chroot to netdir after startup. */ +static bool do_chroot = false; + +/* If !NULL, do setuid to given user after startup */ +static const char *switchuser = NULL; + +/* If nonzero, write log entries to a separate file. */ +bool use_logfile = false; + +char *identname = NULL; /* program name for syslog */ +char *pidfilename = NULL; /* pid file location */ +char *logfilename = NULL; /* log file location */ +char **g_argv; /* a copy of the cmdline arguments */ + +static int status = 1; + +static struct option const long_options[] = { + {"config", required_argument, NULL, 'c'}, + {"kill", optional_argument, NULL, 'k'}, + {"net", required_argument, NULL, 'n'}, + {"help", no_argument, NULL, 1}, + {"version", no_argument, NULL, 2}, + {"no-detach", no_argument, NULL, 'D'}, + {"generate-keys", optional_argument, NULL, 'K'}, + {"debug", optional_argument, NULL, 'd'}, + {"bypass-security", no_argument, NULL, 3}, + {"mlock", no_argument, NULL, 'L'}, + {"chroot", no_argument, NULL, 'R'}, + {"user", required_argument, NULL, 'U'}, + {"logfile", optional_argument, NULL, 4}, + {"pidfile", required_argument, NULL, 5}, + {"option", required_argument, NULL, 'o'}, + {NULL, 0, NULL, 0} }; -static void -usage(int status) -{ - if(status != 0) - fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name); - else - { - printf(_("Usage: %s [option]...\n\n"), program_name); - printf(_(" -c, --config=DIR Read configuration options from DIR.\n" - " -D, --no-detach Don't fork and detach.\n" - " -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" - " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" - " -n, --net=NETNAME Connect to net NETNAME.\n")); - printf(_(" -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" - " --help Display this help and exit.\n" - " --version Output version information and exit.\n\n")); - printf(_("Report bugs to tinc@nl.linux.org.\n")); - } - exit(status); +#ifdef HAVE_MINGW +static struct WSAData wsa_state; +CRITICAL_SECTION mutex; +int main2(int argc, char **argv); +#endif + +static void usage(bool status) { + if(status) + fprintf(stderr, "Try `%s --help\' for more information.\n", + program_name); + else { + printf("Usage: %s [option]...\n\n", program_name); + printf(" -c, --config=DIR Read configuration options from DIR.\n" + " -D, --no-detach Don't fork and detach.\n" + " -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" + " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" + " -n, --net=NETNAME Connect to net NETNAME.\n" + " -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" + " -L, --mlock Lock tinc into main memory.\n" + " --logfile[=FILENAME] Write log entries to a logfile.\n" + " --pidfile=FILENAME Write PID to FILENAME.\n" + " -o, --option=[HOST.]KEY=VALUE Set global/host configuration value.\n" + " -R, --chroot chroot to NET dir at startup.\n" + " -U, --user=USER setuid to given USER at startup.\n" + " --help Display this help and exit.\n" + " --version Output version information and exit.\n\n"); + printf("Report bugs to tinc@tinc-vpn.org.\n"); + } } -void -parse_options(int argc, char **argv, char **envp) -{ - int r; - int option_index = 0; +static bool parse_options(int argc, char **argv) { + config_t *cfg; + int r; + int option_index = 0; + int lineno = 0; - while((r = getopt_long(argc, argv, "c:Dd::k::n:K::", long_options, &option_index)) != EOF) - { - switch(r) - { - case 0: /* long option */ - break; - case 'c': /* config file */ - confbase = xmalloc(strlen(optarg)+1); - strcpy(confbase, optarg); - break; - case 'D': /* no detach */ - do_detach = 0; - break; - case 'd': /* inc debug level */ - if(optarg) - debug_lvl = atoi(optarg); - else - debug_lvl++; - break; - case 'k': /* kill old tincds */ - if(optarg) - { - if(!strcasecmp(optarg, "HUP")) - kill_tincd = SIGHUP; - else if(!strcasecmp(optarg, "TERM")) - kill_tincd = SIGTERM; - else if(!strcasecmp(optarg, "KILL")) - kill_tincd = SIGKILL; - else if(!strcasecmp(optarg, "USR1")) - kill_tincd = SIGUSR1; - else if(!strcasecmp(optarg, "USR2")) - kill_tincd = SIGUSR2; - else if(!strcasecmp(optarg, "WINCH")) - kill_tincd = SIGWINCH; - else if(!strcasecmp(optarg, "INT")) - kill_tincd = SIGINT; - else if(!strcasecmp(optarg, "ALRM")) - kill_tincd = SIGALRM; - else - { - kill_tincd = atoi(optarg); - if(!kill_tincd) - { - fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"), optarg); - usage(1); - } - } - } - else - kill_tincd = SIGTERM; - break; - case 'n': /* net name given */ - netname = xmalloc(strlen(optarg)+1); - strcpy(netname, optarg); - break; - case 'K': /* generate public/private keypair */ - if(optarg) - { - generate_keys = atoi(optarg); - if(generate_keys < 512) - { - fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"), - optarg); - usage(1); - } - generate_keys &= ~7; /* Round it to bytes */ - } - else - generate_keys = 1024; - break; - case '?': - usage(1); - default: - break; - } - } + cmdline_conf = list_alloc((list_action_t)free_config); + + while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:", long_options, &option_index)) != EOF) { + switch(r) { + case 0: /* long option */ + break; + + case 'c': /* config file */ + if(confbase) { + fprintf(stderr, "Only one configuration directory can be given.\n"); + usage(true); + return false; + } + + confbase = xstrdup(optarg); + break; + + case 'D': /* no detach */ + do_detach = false; + break; + + case 'L': /* no detach */ +#ifndef HAVE_MLOCKALL + logger(LOG_ERR, "%s not supported on this platform", "mlockall()"); + return false; +#else + do_mlock = true; + break; +#endif + + case 'd': /* increase debug level */ + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + debug_level = atoi(optarg); + } else { + debug_level++; + } + + break; + + case 'k': /* kill old tincds */ +#ifndef HAVE_MINGW + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + if(!strcasecmp(optarg, "HUP")) { + kill_tincd = SIGHUP; + } else if(!strcasecmp(optarg, "TERM")) { + kill_tincd = SIGTERM; + } else if(!strcasecmp(optarg, "KILL")) { + kill_tincd = SIGKILL; + } else if(!strcasecmp(optarg, "USR1")) { + kill_tincd = SIGUSR1; + } else if(!strcasecmp(optarg, "USR2")) { + kill_tincd = SIGUSR2; + } else if(!strcasecmp(optarg, "WINCH")) { + kill_tincd = SIGWINCH; + } else if(!strcasecmp(optarg, "INT")) { + kill_tincd = SIGINT; + } else if(!strcasecmp(optarg, "ALRM")) { + kill_tincd = SIGALRM; + } else if(!strcasecmp(optarg, "ABRT")) { + kill_tincd = SIGABRT; + } else { + kill_tincd = atoi(optarg); + + if(!kill_tincd) { + fprintf(stderr, "Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n", + optarg); + usage(true); + return false; + } + } + } else { + kill_tincd = SIGTERM; + } + +#else + kill_tincd = 1; +#endif + break; + + case 'n': /* net name given */ + + /* netname "." is special: a "top-level name" */ + if(netname) { + fprintf(stderr, "Only one netname can be given.\n"); + usage(true); + return false; + } + + if(optarg && strcmp(optarg, ".")) { + netname = xstrdup(optarg); + } + + break; + + case 'o': /* option */ + cfg = parse_config_line(optarg, NULL, ++lineno); + + if(!cfg) { + return false; + } + + list_insert_tail(cmdline_conf, cfg); + break; + + case 'K': /* generate public/private keypair */ + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + generate_keys = atoi(optarg); + + if(generate_keys < 512) { + fprintf(stderr, "Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n", + optarg); + usage(true); + return false; + } + + generate_keys &= ~7; /* Round it to bytes */ + } else { + generate_keys = 2048; + } + + break; + + case 'R': /* chroot to NETNAME dir */ + do_chroot = true; + break; + + case 'U': /* setuid to USER */ + switchuser = optarg; + break; + + case 1: /* show help */ + show_help = true; + break; + + case 2: /* show version */ + show_version = true; + break; + + case 3: /* bypass security */ + bypass_security = true; + break; + + case 4: /* write log entries to a file */ + use_logfile = true; + + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + if(logfilename) { + fprintf(stderr, "Only one logfile can be given.\n"); + usage(true); + return false; + } + + logfilename = xstrdup(optarg); + } + + break; + + case 5: /* write PID to a file */ + if(pidfilename) { + fprintf(stderr, "Only one pidfile can be given.\n"); + usage(true); + return false; + } + + pidfilename = xstrdup(optarg); + break; + + case '?': + usage(true); + return false; + + default: + break; + } + } + + if(optind < argc) { + fprintf(stderr, "%s: unrecognized argument '%s'\n", argv[0], argv[optind]); + usage(true); + return false; + } + + return true; } /* This function prettyprints the key generation process */ -void indicator(int a, int b, void *p) -{ - switch(a) - { - case 0: - fprintf(stderr, "."); - break; - case 1: - fprintf(stderr, "+"); - break; - case 2: - fprintf(stderr, "-"); - break; - case 3: - switch(b) - { - case 0: - fprintf(stderr, " p\n"); - break; - case 1: - fprintf(stderr, " q\n"); - break; - default: - fprintf(stderr, "?"); - } - break; - default: - fprintf(stderr, "?"); - } +static int indicator(int a, int b, BN_GENCB *cb) { + (void)cb; + + switch(a) { + case 0: + fprintf(stderr, "."); + break; + + case 1: + fprintf(stderr, "+"); + break; + + case 2: + fprintf(stderr, "-"); + break; + + case 3: + switch(b) { + case 0: + fprintf(stderr, " p\n"); + break; + + case 1: + fprintf(stderr, " q\n"); + break; + + default: + fprintf(stderr, "?"); + } + + break; + + default: + fprintf(stderr, "?"); + } + + return 1; } +#ifndef HAVE_BN_GENCB_NEW +BN_GENCB *BN_GENCB_new(void) { + return xmalloc_and_zero(sizeof(BN_GENCB)); +} + +void BN_GENCB_free(BN_GENCB *cb) { + free(cb); +} +#endif + /* Generate a public/private RSA keypair, and ask for a file to store them in. */ -int keygen(int bits) -{ - RSA *rsa_key; - FILE *f; - char *name = NULL; - char *filename; +static bool keygen(int bits) { + BIGNUM *e = NULL; + RSA *rsa_key; + FILE *f; + char filename[PATH_MAX]; + BN_GENCB *cb; + int result; - fprintf(stderr, _("Generating %d bits keys:\n"), bits); - rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL); + fprintf(stderr, "Generating %d bits keys:\n", bits); - if(!rsa_key) - { - fprintf(stderr, _("Error during key generation!\n")); - return -1; - } - else - fprintf(stderr, _("Done.\n")); + cb = BN_GENCB_new(); - get_config_string(lookup_config(config_tree, "Name"), &name); + if(!cb) { + abort(); + } - if(name) - asprintf(&filename, "%s/hosts/%s", confbase, name); - else - asprintf(&filename, "%s/rsa_key.pub", confbase); + BN_GENCB_set(cb, indicator, NULL); - if((f = ask_and_safe_open(filename, _("public RSA key"), "a")) == NULL) - return -1; + rsa_key = RSA_new(); - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + if(BN_hex2bn(&e, "10001") == 0) { + abort(); + } - PEM_write_RSAPublicKey(f, rsa_key); - fclose(f); - free(filename); + if(!rsa_key || !e) { + abort(); + } - asprintf(&filename, "%s/rsa_key.priv", confbase); - if((f = ask_and_safe_open(filename, _("private RSA key"), "a")) == NULL) - return -1; + result = RSA_generate_key_ex(rsa_key, bits, e, cb); - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + BN_free(e); + BN_GENCB_free(cb); - PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); - fclose(f); - free(filename); + if(!result) { + fprintf(stderr, "Error during key generation!\n"); + RSA_free(rsa_key); + return false; + } else { + fprintf(stderr, "Done.\n"); + } - return 0; + snprintf(filename, sizeof(filename), "%s/rsa_key.priv", confbase); + f = ask_and_open(filename, "private RSA key"); + + if(!f) { + RSA_free(rsa_key); + return false; + } + +#ifdef HAVE_FCHMOD + /* Make it unreadable for others. */ + fchmod(fileno(f), 0600); +#endif + + fputc('\n', f); + PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(f); + + char *name = get_name(); + + if(name) { + snprintf(filename, sizeof(filename), "%s/hosts/%s", confbase, name); + free(name); + } else { + snprintf(filename, sizeof(filename), "%s/rsa_key.pub", confbase); + } + + f = ask_and_open(filename, "public RSA key"); + + if(!f) { + RSA_free(rsa_key); + return false; + } + + fputc('\n', f); + PEM_write_RSAPublicKey(f, rsa_key); + fclose(f); + + RSA_free(rsa_key); + + return true; } /* Set all files and paths according to netname */ -void make_names(void) -{ - if(netname) - { - if(!pidfilename) - asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname); - if(!confbase) - asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname); - else - syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter...")); - if(!identname) - asprintf(&identname, "tinc.%s", netname); - } - else - { - if(!pidfilename) - pidfilename = LOCALSTATEDIR "/run/tinc.pid"; - if(!confbase) - asprintf(&confbase, "%s/tinc", CONFDIR); - if(!identname) - identname = "tinc"; - } -} - -int -main(int argc, char **argv, char **envp) -{ - program_name = argv[0]; - - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); - - environment = envp; - parse_options(argc, argv, envp); - - if(show_version) - { - printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT); - printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n" - "See the AUTHORS file for a complete list.\n\n" - "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" - "and you are welcome to redistribute it under certain conditions;\n" - "see the file COPYING for details.\n")); - - return 0; - } - - if(show_help) - usage(0); - -#ifdef HAVE_SOLARIS - openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ -#else - openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ +static void make_names(void) { +#ifdef HAVE_MINGW + HKEY key; + char installdir[1024] = ""; + DWORD len = sizeof(installdir); #endif - g_argv = argv; + if(netname) { + xasprintf(&identname, "tinc.%s", netname); + } else { + identname = xstrdup("tinc"); + } - make_names(); - init_configuration(&config_tree); +#ifdef HAVE_MINGW - /* Slllluuuuuuurrrrp! */ -cp - RAND_load_file("/dev/urandom", 1024); + if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) { + if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) { + if(!confbase) { + if(netname) { + xasprintf(&confbase, "%s/%s", installdir, netname); + } else { + xasprintf(&confbase, "%s", installdir); + } + } + + if(!logfilename) { + xasprintf(&logfilename, "%s/tinc.log", confbase); + } + } + + RegCloseKey(key); + + if(*installdir) { + return; + } + } -#ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS - SSLeay_add_all_algorithms(); -#else - OpenSSL_add_all_algorithms(); #endif -cp - if(generate_keys) - { - read_server_config(); - exit(keygen(generate_keys)); - } + if(!pidfilename) { + xasprintf(&pidfilename, RUNSTATEDIR "/%s.pid", identname); + } - if(kill_tincd) - exit(kill_other(kill_tincd)); + if(!logfilename) { + xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); + } - if(read_server_config()) - exit(1); -cp - if(detach()) - exit(0); -cp - for(;;) - { - if(!setup_network_connections()) - { - main_loop(); - cleanup_and_exit(1); - } - - syslog(LOG_ERR, _("Unrecoverable error")); - cp_trace(); - - if(do_detach) - { - syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout); - sleep(maxtimeout); - } - else - { - syslog(LOG_ERR, _("Not restarting.")); - exit(1); - } - } + if(netname) { + if(!confbase) { + xasprintf(&confbase, CONFDIR "/tinc/%s", netname); + } else { + logger(LOG_INFO, "Both netname and configuration directory given, using the latter..."); + } + } else { + if(!confbase) { + xasprintf(&confbase, CONFDIR "/tinc"); + } + } +} + +static void free_names() { + free(identname); + free(netname); + free(pidfilename); + free(logfilename); + free(confbase); +} + +static bool drop_privs() { +#ifdef HAVE_MINGW + + if(switchuser) { + logger(LOG_ERR, "%s not supported on this platform", "-U"); + return false; + } + + if(do_chroot) { + logger(LOG_ERR, "%s not supported on this platform", "-R"); + return false; + } + +#else + uid_t uid = 0; + + if(switchuser) { + struct passwd *pw = getpwnam(switchuser); + + if(!pw) { + logger(LOG_ERR, "unknown user `%s'", switchuser); + return false; + } + + uid = pw->pw_uid; + + if(initgroups(switchuser, pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "initgroups", strerror(errno)); + return false; + } + +#ifndef ANDROID +// Not supported in android NDK + endgrent(); + endpwent(); +#endif + } + + if(do_chroot) { + tzset(); /* for proper timestamps in logs */ + + if(chroot(confbase) != 0 || chdir("/") != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "chroot", strerror(errno)); + return false; + } + + free(confbase); + confbase = xstrdup(""); + } + + if(switchuser) + if(setuid(uid) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setuid", strerror(errno)); + return false; + } + +#endif + return true; +} + +#ifdef HAVE_MINGW +# define setpriority(level) !SetPriorityClass(GetCurrentProcess(), (level)) +#else +# define NORMAL_PRIORITY_CLASS 0 +# define BELOW_NORMAL_PRIORITY_CLASS 10 +# define HIGH_PRIORITY_CLASS -10 +# define setpriority(level) (setpriority(PRIO_PROCESS, 0, (level))) +#endif + +int main(int argc, char **argv) { + program_name = argv[0]; + + if(!parse_options(argc, argv)) { + return 1; + } + + if(show_version) { + printf("%s version %s\n", PACKAGE, VERSION); + printf("Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and others.\n" + "See the AUTHORS file for a complete list.\n\n" + "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" + "and you are welcome to redistribute it under certain conditions;\n" + "see the file COPYING for details.\n"); + + return 0; + } + + if(show_help) { + usage(false); + return 0; + } + + make_names(); + + if(kill_tincd) { + return !kill_other(kill_tincd); + } + + openlogger("tinc", use_logfile ? LOGMODE_FILE : LOGMODE_STDERR); + + g_argv = argv; + + if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid()) { + do_detach = false; + } + +#ifdef HAVE_UNSETENV + unsetenv("LISTEN_PID"); +#endif + + init_configuration(&config_tree); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + OpenSSL_add_all_algorithms(); +#endif + + if(generate_keys) { + read_server_config(); + return !keygen(generate_keys); + } + + if(!read_server_config()) { + return 1; + } + +#ifdef HAVE_LZO + + if(lzo_init() != LZO_E_OK) { + logger(LOG_ERR, "Error initializing LZO compressor!"); + return 1; + } + +#endif + +#ifdef HAVE_MINGW + + if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { + logger(LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); + return 1; + } + + if(!do_detach || !init_service()) { + return main2(argc, argv); + } else { + return 1; + } +} + +int main2(int argc, char **argv) { + InitializeCriticalSection(&mutex); + EnterCriticalSection(&mutex); +#endif + char *priority = NULL; + + if(!detach()) { + return 1; + } + +#ifdef HAVE_MLOCKALL + + /* Lock all pages into memory if requested. + * This has to be done after daemon()/fork() so it works for child. + * No need to do that in parent as it's very short-lived. */ + if(do_mlock && mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "mlockall", + strerror(errno)); + return 1; + } + +#endif + + /* Setup sockets and open device. */ + + if(!setup_network()) { + goto end; + } + + /* Initiate all outgoing connections. */ + + try_outgoing_connections(); + + /* Change process priority */ + + if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) { + if(!strcasecmp(priority, "Normal")) { + if(setpriority(NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "Low")) { + if(setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "High")) { + if(setpriority(HIGH_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else { + logger(LOG_ERR, "Invalid priority `%s`!", priority); + goto end; + } + } + + /* drop privileges */ + if(!drop_privs()) { + goto end; + } + + /* Start main loop. It only exits when tinc is killed. */ + + status = main_loop(); + + /* Shutdown properly. */ + + ifdebug(CONNECTIONS) + devops.dump_stats(); + + close_network_connections(); + +end: + logger(LOG_NOTICE, "Terminating"); + +#ifndef HAVE_MINGW + remove_pid(pidfilename); +#endif + + free(priority); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_cleanup(); + ERR_free_strings(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif +#endif + + exit_configuration(&config_tree); + list_delete_list(cmdline_conf); + free_names(); + + return status; } diff --git a/src/uml_device.c b/src/uml_device.c new file mode 100644 index 0000000..66de431 --- /dev/null +++ b/src/uml_device.c @@ -0,0 +1,310 @@ +/* + device.c -- UML network socket + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2012 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include + +#include "conf.h" +#include "device.h" +#include "net.h" +#include "logger.h" +#include "utils.h" +#include "route.h" +#include "xalloc.h" + +static int listen_fd = -1; +static int request_fd = -1; +static int data_fd = -1; +static int write_fd = -1; +static int state = 0; +static const char *device_info = "UML network socket"; + +extern char *identname; +extern volatile bool running; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +enum request_type { REQ_NEW_CONTROL }; + +static struct request { + uint32_t magic; + uint32_t version; + enum request_type type; + struct sockaddr_un sock; +} request; + +static struct sockaddr_un data_sun; + +static bool setup_device(void) { + struct sockaddr_un listen_sun; + static const int one = 1; + struct { + char zero; + int pid; + int usecs; + } name; + struct timeval tv; + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + xasprintf(&device, RUNSTATEDIR "/%s.umlsocket", identname); + } + + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + if((write_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { + logger(LOG_ERR, "Could not open write %s: %s", device_info, strerror(errno)); + running = false; + return false; + } + +#ifdef FD_CLOEXEC + fcntl(write_fd, F_SETFD, FD_CLOEXEC); +#endif + + setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; + return false; + } + + if((data_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { + logger(LOG_ERR, "Could not open data %s: %s", device_info, strerror(errno)); + running = false; + return false; + } + +#ifdef FD_CLOEXEC + fcntl(data_fd, F_SETFD, FD_CLOEXEC); +#endif + + setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; + return false; + } + + name.zero = 0; + name.pid = getpid(); + gettimeofday(&tv, NULL); + name.usecs = tv.tv_usec; + data_sun.sun_family = AF_UNIX; + memcpy(&data_sun.sun_path, &name, sizeof(name)); + + if(bind(data_fd, (struct sockaddr *)&data_sun, sizeof(data_sun)) < 0) { + logger(LOG_ERR, "Could not bind data %s: %s", device_info, strerror(errno)); + running = false; + return false; + } + + if((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s", device_info, + strerror(errno)); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + return false; + } + + listen_sun.sun_family = AF_UNIX; + strncpy(listen_sun.sun_path, device, sizeof(listen_sun.sun_path)); + + if(bind(listen_fd, (struct sockaddr *)&listen_sun, sizeof(listen_sun)) < 0) { + logger(LOG_ERR, "Could not bind %s to %s: %s", device_info, device, strerror(errno)); + return false; + } + + if(listen(listen_fd, 1) < 0) { + logger(LOG_ERR, "Could not listen on %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + device_fd = listen_fd; + state = 0; + + logger(LOG_INFO, "%s is a %s", device, device_info); + + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + return true; +} + +void close_device(void) { + if(listen_fd >= 0) { + close(listen_fd); + } + + if(request_fd >= 0) { + close(request_fd); + } + + if(data_fd >= 0) { + close(data_fd); + } + + if(write_fd >= 0) { + close(write_fd); + } + + unlink(device); + + free(device); + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + switch(state) { + case 0: { + struct sockaddr sa; + socklen_t salen = sizeof(sa); + + request_fd = accept(listen_fd, &sa, &salen); + + if(request_fd < 0) { + logger(LOG_ERR, "Could not accept connection to %s %s: %s", device_info, device, strerror(errno)); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(request_fd, F_SETFD, FD_CLOEXEC); +#endif + + if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; + return false; + } + + close(listen_fd); + listen_fd = -1; + device_fd = request_fd; + state = 1; + + return false; + } + + case 1: { + if((lenin = read(request_fd, &request, sizeof(request))) != sizeof request) { + logger(LOG_ERR, "Error while reading request from %s %s: %s", device_info, + device, strerror(errno)); + running = false; + return false; + } + + if(request.magic != 0xfeedface || request.version != 3 || request.type != REQ_NEW_CONTROL) { + logger(LOG_ERR, "Unknown magic %x, version %d, request type %d from %s %s", + request.magic, request.version, request.type, device_info, device); + running = false; + return false; + } + + if(connect(write_fd, (struct sockaddr *)&request.sock, sizeof(request.sock)) < 0) { + logger(LOG_ERR, "Could not bind write %s: %s", device_info, strerror(errno)); + running = false; + return false; + } + + write(request_fd, &data_sun, sizeof(data_sun)); + device_fd = data_fd; + + logger(LOG_INFO, "Connection with UML established"); + + state = 2; + return false; + } + + case 2: { + if((lenin = read(data_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + running = false; + return false; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; + } + + default: + logger(LOG_ERR, "Invalid value for state variable in " __FILE__); + abort(); + } +} + +static bool write_packet(vpn_packet_t *packet) { + if(state != 2) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Dropping packet of %d bytes to %s: not connected to UML yet", + packet->len, device_info); + return false; + } + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + if(write(write_fd, packet->data, packet->len) < 0) { + if(errno != EINTR && errno != EAGAIN) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + running = false; + } + + return false; + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t uml_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..70a5c99 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,105 @@ +/* + utils.c -- gathering of some stupid small functions + Copyright (C) 1999-2005 Ivo Timmermans + 2000-2014 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "../src/logger.h" +#include "utils.h" + +static const char hexadecimals[] = "0123456789ABCDEF"; + +static int charhex2bin(char c) { + if(isdigit(c)) { + return c - '0'; + } else { + return toupper(c) - 'A' + 10; + } +} + +bool hex2bin(char *src, char *dst, int length) { + for(int i = 0; i < length; i++) { + if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1])) { + return false; + } + + dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]); + } + + return true; +} + +void bin2hex(char *src, char *dst, int length) { + int i; + + for(i = length - 1; i >= 0; i--) { + dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15]; + dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4]; + } +} + +#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN) +#ifdef HAVE_CYGWIN +#include +#endif + +const char *winerror(int err) { + static char buf[1024], *ptr; + + ptr = buf + sprintf(buf, "(%d) ", err); + + if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), ptr, sizeof(buf) - (ptr - buf), NULL)) { + strcpy(ptr, "(unable to format errormessage)"); + }; + + if((ptr = strchr(buf, '\r'))) { + *ptr = '\0'; + } + + return buf; +} +#endif + +unsigned int bitfield_to_int(const void *bitfield, size_t size) { + unsigned int value = 0; + + if(size > sizeof(value)) { + size = sizeof(value); + } + + memcpy(&value, bitfield, size); + return value; +} + +/** + * As memcmp(), but constant-time. + * Returns 0 when data is equal, non-zero otherwise. + */ +int memcmp_constant_time(const void *a, const void *b, size_t size) { + const uint8_t *a1 = a, *b1 = b; + int ret = 0; + size_t i; + + for(i = 0; i < size; i++) { + ret |= *a1++ ^ *b1++; + } + + return ret; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..7952025 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,50 @@ +#ifndef TINC_UTILS_H +#define TINC_UTILS_H + +/* + utils.h -- header file for utils.c + Copyright (C) 1999-2005 Ivo Timmermans + 2000-2014 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +extern bool hex2bin(char *src, char *dst, int length); +extern void bin2hex(char *src, char *dst, int length); + +#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN) +extern const char *winerror(int); +#endif + +#ifdef HAVE_MINGW +#define strerror(x) ((x)>0?strerror(x):winerror(GetLastError())) +#define sockerrno WSAGetLastError() +#define sockstrerror(x) winerror(x) +#define sockwouldblock(x) ((x) == WSAEWOULDBLOCK || (x) == WSAEINTR) +#define sockmsgsize(x) ((x) == WSAEMSGSIZE) +#define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK) +#else +#define sockerrno errno +#define sockstrerror(x) strerror(x) +#define sockwouldblock(x) ((x) == EWOULDBLOCK || (x) == EINTR) +#define sockmsgsize(x) ((x) == EMSGSIZE) +#define sockinprogress(x) ((x) == EINPROGRESS) +#endif + +extern unsigned int bitfield_to_int(const void *bitfield, size_t size); + +int memcmp_constant_time(const void *a, const void *b, size_t size); + +#endif diff --git a/src/vde_device.c b/src/vde_device.c new file mode 100644 index 0000000..6d854a6 --- /dev/null +++ b/src/vde_device.c @@ -0,0 +1,147 @@ +/* + device.c -- VDE plug + Copyright (C) 2012 Guus Sliepen + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include + +#include "conf.h" +#include "device.h" +#include "net.h" +#include "logger.h" +#include "utils.h" +#include "route.h" +#include "xalloc.h" + +static struct vdepluglib plug; +static struct vdeconn *conn = NULL; +static int port = 0; +static char *group = NULL; +static const char *device_info = "VDE socket"; + +extern char *identname; +extern volatile bool running; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static bool setup_device(void) { + libvdeplug_dynopen(plug); + + if(!plug.dl_handle) { + logger(LOG_ERR, "Could not open libvdeplug library!"); + return false; + } + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + xasprintf(&device, RUNSTATEDIR "/vde.ctl"); + } + + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + get_config_int(lookup_config(config_tree, "VDEPort"), &port); + + get_config_string(lookup_config(config_tree, "VDEGroup"), &group); + + struct vde_open_args args = { + .port = port, + .group = group, + .mode = 0700, + }; + + conn = plug.vde_open(device, identname, &args); + + if(!conn) { + logger(LOG_ERR, "Could not open VDE socket %s", device); + return false; + } + + device_fd = plug.vde_datafd(conn); + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + logger(LOG_INFO, "%s is a %s", device, device_info); + + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + return true; +} + +static void close_device(void) { + if(conn) { + plug.vde_close(conn); + } + + if(plug.dl_handle) { + libvdeplug_dynclose(plug); + } + + free(device); + + free(iface); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin = (ssize_t)plug.vde_recv(conn, packet->data, MTU, 0); + + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); + running = false; + return false; + } + + packet->len = lenin; + device_total_in += packet->len; + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + if((ssize_t)plug.vde_send(conn, packet->data, packet->len, 0) < 0) { + if(errno != EINTR && errno != EAGAIN) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + running = false; + } + + return false; + } + + device_total_out += packet->len; + + return true; +} + +static void dump_device_stats(void) { + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); +} + +const devops_t vde_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; diff --git a/src/xalloc.h b/src/xalloc.h new file mode 100644 index 0000000..cda0871 --- /dev/null +++ b/src/xalloc.h @@ -0,0 +1,97 @@ +#ifndef TINC_XALLOC_H +#define TINC_XALLOC_H + +/* + xalloc.h -- malloc and related functions with out of memory checking + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + Copyright (C) 2011-2017 Guus Sliepen + + 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., Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +static inline void *xmalloc(size_t n) __attribute__((__malloc__)); +static inline void *xmalloc(size_t n) { + void *p = malloc(n); + + if(!p) { + abort(); + } + + return p; +} + +static inline void *xmalloc_and_zero(size_t n) __attribute__((__malloc__)); +static inline void *xmalloc_and_zero(size_t n) { + void *p = calloc(1, n); + + if(!p) { + abort(); + } + + return p; +} + +static inline void *xrealloc(void *p, size_t n) { + p = realloc(p, n); + + if(!p) { + abort(); + } + + return p; +} + +static inline char *xstrdup(const char *s) __attribute__((__malloc__)); +static inline char *xstrdup(const char *s) { + char *p = strdup(s); + + if(!p) { + abort(); + } + + return p; +} + +static inline int xvasprintf(char **strp, const char *fmt, va_list ap) { +#ifdef HAVE_MINGW + char buf[1024]; + int result = vsnprintf(buf, sizeof(buf), fmt, ap); + + if(result < 0) { + abort(); + } + + *strp = xstrdup(buf); +#else + int result = vasprintf(strp, fmt, ap); + + if(result < 0) { + abort(); + } + +#endif + return result; +} + +static inline int xasprintf(char **strp, const char *fmt, ...) __attribute__((__format__(printf, 2, 3))); +static inline int xasprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int result = xvasprintf(strp, fmt, ap); + va_end(ap); + return result; +} + +#endif diff --git a/stamp-h.in b/stamp-h.in deleted file mode 100644 index e69de29..0000000 diff --git a/system.h b/system.h deleted file mode 100644 index 51adca0..0000000 --- a/system.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - system.h -- header for locale settings - Copyright (C) 1998,99,2000 Ivo Timmermans - - 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 __TINC_SYSTEM_H__ -#define __TINC_SYSTEM_H__ - -/* Take care of NLS matters. -- from fileutils 4.0 */ - -#if HAVE_LOCALE_H -# include -#endif -#if !HAVE_SETLOCALE -# define setlocale(Category, Locale) /* empty */ -#endif - -#if ENABLE_NLS -# include -# define _(Text) gettext (Text) -#else -# undef bindtextdomain -# define bindtextdomain(Domain, Directory) /* empty */ -# undef textdomain -# define textdomain(Domain) /* empty */ -# define _(Text) Text -#endif -#define N_(Text) Text - -#ifndef HAVE_STRSIGNAL -# define strsignal(p) "" -#endif - -/* Other functions */ -#include - -#endif /* __TINC_SYSTEM_H__ */ - diff --git a/systemd/Makefile.am b/systemd/Makefile.am new file mode 100644 index 0000000..dac2b73 --- /dev/null +++ b/systemd/Makefile.am @@ -0,0 +1,18 @@ +EXTRA_DIST = tinc.service.in tinc@.service.in + +CLEANFILES = tinc.service tinc@.service + +if WITH_SYSTEMD +systemddir = @systemd_path@ +nodist_systemd_DATA = tinc.service tinc@.service +endif + +substitute = sed \ + -e s,'@sbindir\@',"$(sbindir)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g + +tinc.service: $(srcdir)/tinc.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.service.in > $@ + +tinc@.service: $(srcdir)/tinc@.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc@.service.in > $@ diff --git a/systemd/Makefile.in b/systemd/Makefile.in new file mode 100644 index 0000000..e27e947 --- /dev/null +++ b/systemd/Makefile.in @@ -0,0 +1,486 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = systemd +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(systemddir)" +DATA = $(nodist_systemd_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = tinc.service.in tinc@.service.in +CLEANFILES = tinc.service tinc@.service +@WITH_SYSTEMD_TRUE@systemddir = @systemd_path@ +@WITH_SYSTEMD_TRUE@nodist_systemd_DATA = tinc.service tinc@.service +substitute = sed \ + -e s,'@sbindir\@',"$(sbindir)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu systemd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu systemd/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-nodist_systemdDATA: $(nodist_systemd_DATA) + @$(NORMAL_INSTALL) + @list='$(nodist_systemd_DATA)'; test -n "$(systemddir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(systemddir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(systemddir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemddir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(systemddir)" || exit $$?; \ + done + +uninstall-nodist_systemdDATA: + @$(NORMAL_UNINSTALL) + @list='$(nodist_systemd_DATA)'; test -n "$(systemddir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(systemddir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || 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 $(DATA) +installdirs: + for dir in "$(DESTDIR)$(systemddir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-nodist_systemdDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-nodist_systemdDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-nodist_systemdDATA \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-nodist_systemdDATA + +.PRECIOUS: Makefile + + +tinc.service: $(srcdir)/tinc.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.service.in > $@ + +tinc@.service: $(srcdir)/tinc@.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc@.service.in > $@ + +# 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/systemd/tinc.service.in b/systemd/tinc.service.in new file mode 100644 index 0000000..b671042 --- /dev/null +++ b/systemd/tinc.service.in @@ -0,0 +1,20 @@ +# This is a mostly empty service, but allows commands like stop, start, reload +# to propagate to all tinc@ service instances. + +[Unit] +Description=Tinc VPN +Documentation=info:tinc +Documentation=man:tinc(8) man:tinc.conf(5) +Documentation=http://tinc-vpn.org/docs/ +After=network.target +Wants=network.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/true +ExecReload=/bin/true +WorkingDirectory=@sysconfdir@/tinc + +[Install] +WantedBy=multi-user.target diff --git a/systemd/tinc@.service.in b/systemd/tinc@.service.in new file mode 100644 index 0000000..8fbf551 --- /dev/null +++ b/systemd/tinc@.service.in @@ -0,0 +1,20 @@ +[Unit] +Description=Tinc net %i +Documentation=info:tinc +Documentation=man:tinc(8) man:tinc.conf(5) +Documentation=http://tinc-vpn.org/docs/ +PartOf=tinc.service +ReloadPropagatedFrom=tinc.service + +[Service] +Type=simple +WorkingDirectory=@sysconfdir@/tinc/%i +ExecStart=@sbindir@/tincd -n %i -D +ExecReload=@sbindir@/tincd -n %i -kHUP +KillMode=mixed +Restart=on-failure +RestartSec=5 +TimeoutStopSec=5 + +[Install] +WantedBy=tinc.service