From ed8d36a43442f4e474477427e7a880a4b5e005bd Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 26 Aug 2019 13:44:36 +0200 Subject: [PATCH] Import Upstream version 1.0pre7 --- ABOUT-NLS | 324 +++ AUTHORS | 13 + COPYING | 339 +++ COPYING.README | 4 + ChangeLog | 4614 ++++++++++++++++++++++++++++++++ INSTALL | 182 ++ Makefile.am | 37 + Makefile.in | 460 ++++ NEWS | 267 ++ README | 117 + THANKS | 25 + TODO | 5 + acconfig.h | 77 + aclocal.m4 | 1408 ++++++++++ config.guess | 1321 +++++++++ config.h.in | 310 +++ config.sub | 1443 ++++++++++ configure | 5240 ++++++++++++++++++++++++++++++++++++ configure.in | 125 + depcomp | 411 +++ doc/GNUmakefile | 23 + doc/Makefile.am | 25 + doc/Makefile.in | 539 ++++ doc/Makefile.maint | 38 + doc/Makefile.summ | 2 + doc/es/Makefile.am | 3 + doc/es/Makefile.in | 218 ++ doc/help2man | 375 +++ doc/sample-config.tar.gz | Bin 0 -> 1742 bytes doc/texinfo.tex | 5484 ++++++++++++++++++++++++++++++++++++++ doc/tinc.conf.5 | 340 +++ doc/tinc.info | 79 + doc/tinc.info-1 | 1317 +++++++++ doc/tinc.info-2 | 520 ++++ doc/tinc.texi | 1893 +++++++++++++ doc/tincd.8 | 174 ++ install-sh | 251 ++ intl/ChangeLog | 4 + intl/Makefile.in | 313 +++ intl/VERSION | 1 + intl/bindtextdom.c | 369 +++ intl/config.charset | 438 +++ intl/dcgettext.c | 58 + intl/dcigettext.c | 1259 +++++++++ intl/dcngettext.c | 60 + intl/dgettext.c | 59 + intl/dngettext.c | 61 + intl/explodename.c | 192 ++ intl/finddomain.c | 198 ++ intl/gettext.c | 64 + intl/gettext.h | 102 + intl/gettextP.h | 252 ++ intl/hash-string.h | 59 + intl/intl-compat.c | 166 ++ intl/l10nflist.c | 405 +++ intl/libgettext.h | 49 + intl/libgnuintl.h | 128 + intl/loadinfo.h | 109 + intl/loadmsgcat.c | 567 ++++ intl/localcharset.c | 271 ++ intl/locale.alias | 78 + intl/localealias.c | 404 +++ intl/ngettext.c | 68 + intl/plural.c | 1326 +++++++++ intl/plural.y | 413 +++ intl/ref-add.sin | 31 + intl/ref-del.sin | 26 + intl/textdomain.c | 142 + lib/Makefile.am | 15 + lib/Makefile.in | 338 +++ lib/README | 1 + lib/alloca.c | 494 ++++ lib/avl_tree.c | 723 +++++ lib/avl_tree.h | 145 + lib/dropin.c | 171 ++ lib/dropin.h | 38 + lib/getopt.c | 1053 ++++++++ lib/getopt.h | 133 + lib/getopt1.c | 189 ++ lib/list.c | 197 ++ lib/list.h | 82 + lib/malloc.c | 39 + lib/memcmp.c | 391 +++ lib/pidfile.c | 138 + lib/pidfile.h | 50 + lib/realloc.c | 44 + lib/utils.c | 87 + lib/utils.h | 57 + lib/xalloc.h | 26 + lib/xmalloc.c | 156 ++ m4/Makefile.am | 19 + m4/Makefile.am.in | 16 + m4/Makefile.in | 232 ++ m4/README | 8 + m4/aclocal-include.m4 | 14 + m4/malloc.m4 | 44 + m4/openssl.m4 | 49 + m4/perl.m4 | 39 + m4/realloc.m4 | 44 + m4/tuntap.m4 | 39 + m4/zlib.m4 | 31 + missing | 283 ++ mkinstalldirs | 40 + po/ChangeLog | 28 + po/Makefile.in.in | 196 ++ po/POTFILES.in | 33 + po/nl.gmo | Bin 0 -> 26037 bytes po/nl.po | 1288 +++++++++ po/tinc.pot | 1232 +++++++++ src/Makefile.am | 31 + src/Makefile.in | 402 +++ src/conf.c | 623 +++++ src/conf.h | 70 + src/connection.c | 137 + src/connection.h | 121 + src/device.c | 224 ++ src/device.h | 36 + src/edge.c | 211 ++ src/edge.h | 62 + src/event.c | 110 + src/event.h | 48 + src/freebsd/device.c | 148 + src/graph.c | 290 ++ src/graph.h | 25 + src/linux/device.c | 224 ++ src/meta.c | 210 ++ src/meta.h | 32 + src/net.c | 449 ++++ src/net.h | 153 ++ src/net_packet.c | 431 +++ src/net_setup.c | 564 ++++ src/net_socket.c | 484 ++++ src/netutl.c | 246 ++ src/netutl.h | 46 + src/node.c | 173 ++ src/node.h | 88 + src/openbsd/device.c | 195 ++ src/process.c | 507 ++++ src/process.h | 36 + src/protocol.c | 244 ++ src/protocol.h | 120 + src/protocol_auth.c | 605 +++++ src/protocol_edge.c | 298 +++ src/protocol_key.c | 286 ++ src/protocol_misc.c | 198 ++ src/protocol_subnet.c | 237 ++ src/route.c | 493 ++++ src/route.h | 41 + src/solaris/device.c | 196 ++ src/subnet.c | 394 +++ src/subnet.h | 88 + src/tincd.c | 400 +++ stamp-h.in | 0 system.h | 52 + 154 files changed, 53905 insertions(+) create mode 100644 ABOUT-NLS create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING.README create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 THANKS create mode 100644 TODO create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.in create mode 100755 depcomp create mode 100644 doc/GNUmakefile create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/Makefile.maint create mode 100644 doc/Makefile.summ create mode 100644 doc/es/Makefile.am create mode 100644 doc/es/Makefile.in create mode 100755 doc/help2man create mode 100644 doc/sample-config.tar.gz create mode 100644 doc/texinfo.tex create mode 100644 doc/tinc.conf.5 create mode 100644 doc/tinc.info create mode 100644 doc/tinc.info-1 create mode 100644 doc/tinc.info-2 create mode 100644 doc/tinc.texi create mode 100644 doc/tincd.8 create mode 100755 install-sh create mode 100644 intl/ChangeLog create mode 100644 intl/Makefile.in create mode 100644 intl/VERSION create mode 100644 intl/bindtextdom.c create mode 100755 intl/config.charset create mode 100644 intl/dcgettext.c create mode 100644 intl/dcigettext.c create mode 100644 intl/dcngettext.c create mode 100644 intl/dgettext.c create mode 100644 intl/dngettext.c create mode 100644 intl/explodename.c create mode 100644 intl/finddomain.c create mode 100644 intl/gettext.c create mode 100644 intl/gettext.h create mode 100644 intl/gettextP.h create mode 100644 intl/hash-string.h create mode 100644 intl/intl-compat.c create mode 100644 intl/l10nflist.c create mode 100644 intl/libgettext.h create mode 100644 intl/libgnuintl.h create mode 100644 intl/loadinfo.h create mode 100644 intl/loadmsgcat.c create mode 100644 intl/localcharset.c create mode 100644 intl/locale.alias create mode 100644 intl/localealias.c create mode 100644 intl/ngettext.c create mode 100644 intl/plural.c create mode 100644 intl/plural.y create mode 100644 intl/ref-add.sin create mode 100644 intl/ref-del.sin create mode 100644 intl/textdomain.c create mode 100644 lib/Makefile.am create mode 100644 lib/Makefile.in create mode 100644 lib/README create mode 100644 lib/alloca.c create mode 100644 lib/avl_tree.c create mode 100644 lib/avl_tree.h create mode 100644 lib/dropin.c create mode 100644 lib/dropin.h create mode 100644 lib/getopt.c create mode 100644 lib/getopt.h create mode 100644 lib/getopt1.c create mode 100644 lib/list.c create mode 100644 lib/list.h create mode 100644 lib/malloc.c create mode 100644 lib/memcmp.c create mode 100644 lib/pidfile.c create mode 100644 lib/pidfile.h create mode 100644 lib/realloc.c create mode 100644 lib/utils.c create mode 100644 lib/utils.h create mode 100644 lib/xalloc.h create mode 100644 lib/xmalloc.c create mode 100644 m4/Makefile.am create mode 100644 m4/Makefile.am.in create mode 100644 m4/Makefile.in create mode 100644 m4/README create mode 100644 m4/aclocal-include.m4 create mode 100644 m4/malloc.m4 create mode 100644 m4/openssl.m4 create mode 100644 m4/perl.m4 create mode 100644 m4/realloc.m4 create mode 100644 m4/tuntap.m4 create mode 100644 m4/zlib.m4 create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 po/ChangeLog create mode 100644 po/Makefile.in.in create mode 100644 po/POTFILES.in create mode 100644 po/nl.gmo create mode 100644 po/nl.po create mode 100644 po/tinc.pot create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/conf.c create mode 100644 src/conf.h create mode 100644 src/connection.c create mode 100644 src/connection.h create mode 100644 src/device.c create mode 100644 src/device.h create mode 100644 src/edge.c create mode 100644 src/edge.h create mode 100644 src/event.c create mode 100644 src/event.h create mode 100644 src/freebsd/device.c create mode 100644 src/graph.c create mode 100644 src/graph.h create mode 100644 src/linux/device.c create mode 100644 src/meta.c create mode 100644 src/meta.h create mode 100644 src/net.c create mode 100644 src/net.h create mode 100644 src/net_packet.c create mode 100644 src/net_setup.c create mode 100644 src/net_socket.c create mode 100644 src/netutl.c create mode 100644 src/netutl.h create mode 100644 src/node.c create mode 100644 src/node.h create mode 100644 src/openbsd/device.c create mode 100644 src/process.c create mode 100644 src/process.h create mode 100644 src/protocol.c create mode 100644 src/protocol.h create mode 100644 src/protocol_auth.c create mode 100644 src/protocol_edge.c create mode 100644 src/protocol_key.c create mode 100644 src/protocol_misc.c create mode 100644 src/protocol_subnet.c create mode 100644 src/route.c create mode 100644 src/route.h create mode 100644 src/solaris/device.c create mode 100644 src/subnet.c create mode 100644 src/subnet.h create mode 100644 src/tincd.c create mode 100644 stamp-h.in create mode 100644 system.h diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..5fde45a --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,324 @@ +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 new file mode 100644 index 0000000..4721984 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,13 @@ +Main tinc authors: +Guus Sliepen +Ivo Timmermans + +These files are from other sources: + * lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from + the syslog 1.3 sources. + +Also some of the macro files in the directory m4, and their +accompanying files in lib, were taken from GNU fileutils. + +Please see the file THANKS for more information on contributions from +users. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + 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 new file mode 100644 index 0000000..144207e --- /dev/null +++ b/COPYING.README @@ -0,0 +1,4 @@ +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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..7622c02 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4614 @@ +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. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + 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'). + + 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. + + 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 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. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 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 + 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. + +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 + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +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 +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 `..'. + + 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. + +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'. + + 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. + + 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. + + 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'. + +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 +package recognizes. + + 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. + +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: + 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. + + 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. + +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. + +Operation Controls +================== + + `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' + Print a summary of the options to `configure', and exit. + +`--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' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..805c312 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,37 @@ +## Process this file with automake to get Makefile.in + +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 + +ChangeLog: + cvs2cl -U cvsusers --fsf + +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 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..46f73d7 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,460 @@ +# 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@ + +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 +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = intl/Makefile +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 +DIST_SUBDIRS = $(SUBDIRS) +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 + +$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h stamp-hT + @echo timestamp > stamp-hT 2> /dev/null + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @mv stamp-hT stamp-h +$(srcdir)/config.h.in: $(srcdir)/./stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/./stamp-h.in; \ + $(MAKE) $(srcdir)/./stamp-h.in; \ + else :; fi +$(srcdir)/./stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/acconfig.h + @rm -f $(srcdir)/./stamp-h.in $(srcdir)/./stamp-h.inT + @echo timestamp > $(srcdir)/./stamp-h.inT 2> /dev/null + cd $(top_srcdir) && $(AUTOHEADER) + @mv $(srcdir)/./stamp-h.inT $(srcdir)/./stamp-h.in + +distclean-hdr: + -rm -f config.h +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: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) + +GTAGS: + here=`CDPATH=: && cd $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = . +# Avoid unsightly `./'. +distdir = $(PACKAGE)-$(VERSION) + +GZIP_ENV = --best + +distdir: $(DISTFILES) + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) + mkdir $(distdir) + $(mkinstalldirs) $(distdir)/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; \ + if test -d $$d/$$file; then \ + cp -pR $$d/$$file $(distdir) \ + || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + chmod a-w $(distdir) + dc_install_base=`CDPATH=: && cd $(distdir)/=inst && pwd` \ + && cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + --with-included-gettext \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ + || (echo "Error: files left after uninstall" 1>&2; \ + exit 1) ) \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && $(MAKE) $(AM_MAKEFLAGS) distclean \ + && rm -f $(distdir).tar.gz \ + && (test `find . -type f -print | wc -l` -eq 0 \ + || (echo "Error: files left after distclean" 1>&2; \ + exit 1) ) + -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) + @echo "$(distdir).tar.gz is ready for distribution" | \ + sed 'h;s/./=/g;p;x;p;x' +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) +distclean: distclean-recursive + -rm -f config.status config.cache config.log +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.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 + + +ChangeLog: + cvs2cl -U cvsusers --fsf + +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 +# 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 new file mode 100644 index 0000000..0317dd5 --- /dev/null +++ b/NEWS @@ -0,0 +1,267 @@ +version 1.0pre7 Apr 7 2002 + +* Don't do blocking read()s when getting a signal. + +* Remove RSA key checking code, since it sometimes thinks perfectly good RSA + keys are bad. + +* Fix handling of subnets when prefixlength isn't divisible by 8. + + +version 1.0pre6 Mar 27 2002 + +* Improvement of redundant links: + + * Non-blocking connects. + + * Protocol broadcast messages can no longer go into an infinite loop. + + * Graph algorithm updated to look harder for direct connections. + +* Good support for routing IPv6 packets over the VPN. Works on Linux, + FreeBSD, possibly OpenBSD but not on Solaris. + +* Support for tunnels over IPv6 networks. Works on all supported + operating systems. + +* Optional compression of UDP connections using zlib. + +* Optionally let UDP connections inherit TOS field of tunneled packets. + +* Optionally start scripts when certain hosts become (un)reachable. + + +version 1.0pre5 Feb 9 2002 + +* Security enhancements: + + * Added sequence number and optional message authentication code to + the packets. + + * Configurable encryption cipher and digest algorithms. + +* More robust handling of dis- and reconnects. + +* Added a "switch" and a "hub" mode to allow bridging setups. + +* Preliminary support for routing of IPv6 packets. + +* Supports Linux, FreeBSD, OpenBSD and Solaris. + + +It looks like this might be the last release before 1.0. + + +version 1.0pre4 Jan 17 2001 + +* Updated documentation; the documentation now reflects the + configuration as it is. + +* Some internal changes to make tinc scale better for large + networks, such as using AVL trees instead of linked lists for the + connection list. + +* RSA keys can be stored in separate files if needed. See the + documentation for more information. + +* tinc has now been reported to run on Linux PowerPC and FreeBSD x86. + + + +version 1.0pre3 Oct 31 2000 + +* The protocol has been redesigned, and although some details are + still under discussion, this is secure. Care has been taken to + resist most, if not all, attacks. + +* Unfortunately this protocol is not compatible with earlier versions, + nor are earlier versions compatible with this version. Because the + older protocol has huge security flaws, we feel that not + implementing backwards compatibility is justified. + +* Some data about the protocol: + + * It uses public/private RSA keys for authentication (this is the + actual fix for the security hole). + + * All cryptographic functions have been taken out of tinc, instead + it uses the OpenSSL library functions. + + * Offers support for multiple subnets per tinc daemon. + +* New is also the support for the universal tun/tap device. This + means better portability to FreeBSD and Solaris. + +* tinc is tested to compile on Solaris, Linux x86, Linux alpha. + +* tinc now uses the OpenSSL library for cryptographic operations. + More information on getting and installing OpenSSL is in the manual. + This also means that the GMP library is no longer required. + +* Further, thanks to Enrique Zanardi, we have Spanish messages; Matias + Carrasco provided us with a Spanish translation of the manual. + + +What still needs to be done before 1.0: + +* Documentation. Especially since the protocol has changed, and a lot + of configuration directives have been added. + + + + +version 1.0pre2 May 31 2000 + +* This version has been internationalized; and a Dutch translation has + been included. + +* Two configuration variables have been added: + * VpnMask - the IP network mask for the entire VPN, not just our + subnet (as given by MyVirtualIP). The Redhat and Debian packages + use this variable in their system startup scripts, but it is + ignored by tinc. + * Hostnames - if set to `yes', look up the names of IP addresses + trying to connect to us. Default set to `no', to prevent lockups + during lookups. + +* The system startup scripts for Debian and Redhat use + /etc/tinc/nets.boot to find out which networks need to be started + during system boot. + +* Fixes to prevent denial of service attacks by sending random data + after connecting (and even when the connection has been established), + either random garbage or just nonsensical protocol fields. + +* tinc will retry to connect upon startup, does not quit if it doesn't + work the first time. + +* Hosts that are disconnected implicitly if we lose a connection get + deleted from the internal list, to prevent hogging eachother with + add and delete requests when the connection is restored. + + +What still needs to be done before 1.0: + +* Documentation. +* Failover ConnectTo lines, try another one if the first doesn't work. + + + + +version 1.0pre1 May 12 2000 + * New meta-protocol + * Various other bugfixes + * Documentation updates + +version 0.3.3 Feb 9 2000 + * Fixed bug that made tinc stop working with latest kernels (Guus + Sliepen) + * Updated the manual + +version 0.3.2 Nov 12 1999 + * no more `Invalid filedescriptor' when working with multiple + connections + * forward unknown packets to uplink + +version 0.3.1 Oct 20 1999 + * fixed a bug where tinc would exit without a trace + +version 0.3 Aug 20 1999 + * pings now work immediately + * all packet sizes get transmitted correctly + +version 0.2.26 Aug 15 1999 + * fixed some remaining bugs + * --sysconfdir works with configure + * last version before 0.3 + +version 0.2.25 Aug 8 1999 + * improved stability, going towards 0.3 now. + +version 0.2.24 Aug 7 1999 + * added key aging, there's a new config variable, KeyExpire. + * updated man and info pages + +version 0.2.23 Aug 5 1999 + * all known bugs fixed, this is a candidate for 0.3 + +version 0.2.22 Apr 11 1999 + * multiconnection thing is now working nearly perfect :) + +version 0.2.21 Apr 10 1999 + * You shouldn't notice a thing, but a lot has changed wrt key +management - except that it refuses to talk to versions < 0.2.20 + +version 0.2.20 + +version 0.2.19 Apr 3 1999 + * don't install a libcipher.so + +version 0.2.18 Apr 3 1999 + * blowfish library dynamically loaded upon execution + * included Eric Young's IDEA library + +version 0.2.17 Apr 1 1999 + * tincd now re-executes itself in case of a segmentation fault. + +version 0.2.16 Apr 1 1999 + * wrote tincd.conf(5) man page, which still needs a lot of work. + * config file now accepts and tolerates spaces, and any integer base +for integer variables, and better error reporting. See +doc/tincd.conf.sample for an example. + +version 0.2.15 Mar 29 1999 + * fixed bugs + +version 0.2.14 Feb 10 1999 + * added --timeout flag and PingTimeout configuration + * did some first syslog cleanup work + +version 0.2.13 Jan 23 1999 + * bugfixes + +version 0.2.12 Jan 23 1999 + * fixed nauseating bug so that it would crash whenever a connection +got lost + +version 0.2.11 Jan 22 1999 + * framework for multiple connections has been done + * simple manpage for tincd + +version 0.2.10 Jan 18 1999 + * passphrase support added + +version 0.2.9 Jan 13 1999 + * bugs fixed. + +version 0.2.8 Jan 11 1999 + * a reworked protocol version + * a ping/pong system + * more reliable networking code + * automatic reconnection + * still does not work with more than one connection :) + * strips MAC addresses before sending, so there's less overhead, and +less redundancy + +version 0.2.7 Jan 3 1999 + * several updates to make extending more easy. + +version 0.2.6 Dec 20 1998 + * Point-to-Point connections have been established, including +blowfish encryption and a secret key-exchange. + +version 0.2.5 Dec 16 1998 + * Project renamed to tinc, in honour of TINC. + +version 0.2.4 Dec 16 1998 + * now it really does ;) + +version 0.2.3 Nov 24 1998 + * it sort of works now + +version 0.2.2 Nov 20 1998 + * uses GNU gmp. + +version 0.2.1 Nov 14 1998 + + * Bare version. diff --git a/README b/README new file mode 100644 index 0000000..d75d7f6 --- /dev/null +++ b/README @@ -0,0 +1,117 @@ +This is the README file for tinc version 1.0pre7. Installation +instructions may be found in the INSTALL file. + +tinc is Copyright (C) 1998-2002 by: + +Ivo Timmermans , +Guus Sliepen , +and others. + +For a complete list of authors see the AUTHORS file. + +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. See the file COPYING for more details. + + +Security statement +------------------ + +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 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. + +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. + + +Changes to configuration file format since 1.0pre5 +-------------------------------------------------- + +Some configuration variables have different names now. Most notably "TapDevice" +should be changed into "Device", and "Device" should be changed into +"BindToDevice". + + +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. + +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. + +In order to compile tinc, you will also need autoconf, automake, GNU make, m4 +and gettext. + + +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. + +tincd regenerates its encryption key pairs. It does this on the first +activity after the keys have expired. This period is adjustable in the +configuration file, and the default time is 3600 seconds (one hour). + +This version supports multiple subnets at once. They are also sorted +on subnet mask size. This means that it is possible to have +overlapping subnets on the VPN, as long as their subnet mask sizes +differ. + +Since pre5, tinc can operate in several routing modes. The default mode, +"router", works exactly like the older version, and uses Subnet lines to +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. + +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. + +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. + +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/THANKS b/THANKS new file mode 100644 index 0000000..e4cfd6d --- /dev/null +++ b/THANKS @@ -0,0 +1,25 @@ +We would like to thank + + * 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) + +for their help, support and ideas. Thank you guys! + +Ivo Timmermans +Guus Sliepen diff --git a/TODO b/TODO new file mode 100644 index 0000000..c0f2ee3 --- /dev/null +++ b/TODO @@ -0,0 +1,5 @@ +TODO LIST + +1.0: + +* A nice, secure and stable release diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..41fdb99 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,77 @@ +/* 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 new file mode 100644 index 0000000..46a4f8c --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1408 @@ +# aclocal.m4 generated automatically by aclocal 1.5 + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 5 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# We require 2.13 because we rely on SHELL being computed by configure. +AC_PREREQ([2.13]) + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED. +# The purpose of this macro is to provide the user with a means to +# check macros which are provided without letting her know how the +# information is coded. +# If this macro is not defined by Autoconf, define it here. +ifdef([AC_PROVIDE_IFELSE], + [], + [define([AC_PROVIDE_IFELSE], + [ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AM_INIT_AUTOMAKE(PACKAGE,VERSION, [NO-DEFINE]) +# ---------------------------------------------- +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first]) +fi + +# Define the identity of the package. +PACKAGE=$1 +AC_SUBST(PACKAGE)dnl +VERSION=$2 +AC_SUBST(VERSION)dnl +ifelse([$3],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])]) + +# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow +# the ones we care about. +ifdef([m4_pattern_allow], + [m4_pattern_allow([^AM_[A-Z]+FLAGS])])dnl + +# Autoconf 2.50 always computes EXEEXT. However we need to be +# compatible with 2.13, for now. So we always define EXEEXT, but we +# don't compute it. +AC_SUBST(EXEEXT) +# Similar for OBJEXT -- only we only use OBJEXT if the user actually +# requests that it be used. This is a bit dumb. +: ${OBJEXT=o} +AC_SUBST(OBJEXT) + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl +AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_][CC], + defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_][CXX], + defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) + +# +# Check to make sure that the build environment is sane. +# + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + + +# serial 2 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + am_backtick='`' + AC_MSG_WARN([${am_backtick}missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` +]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# serial 4 -*- Autoconf -*- + + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# --------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX" or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +$1DEPMODE="depmode=$am_cv_$1_dependencies_compiler_type" +AC_SUBST([$1DEPMODE]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null +AC_SUBST(DEPDIR) +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +pushdef([subst], defn([AC_SUBST])) +subst(AMDEPBACKSLASH) +popdef([subst]) +]) + +# Generate code to set up dependency tracking. +# This macro should only be invoked once -- use via AC_REQUIRE. +# Usage: +# AM_OUTPUT_DEPENDENCY_COMMANDS + +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],[ +AC_OUTPUT_COMMANDS([ +test x"$AMDEP_TRUE" != x"" || +for mf in $CONFIG_FILES; do + case "$mf" in + Makefile) dirpart=.;; + */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;; + *) continue;; + esac + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`echo "$file" | sed -e 's|/[^/]*$||'` + $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1 + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +], [AMDEP_TRUE="$AMDEP_TRUE" +ac_aux_dir="$ac_aux_dir"])]) + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include='#' +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote='"' + _am_result=BSD + fi +fi +AC_SUBST(am__include) +AC_SUBST(am__quote) +AC_MSG_RESULT($_am_result) +rm -f confinc confmf +]) + +# serial 3 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +# +# FIXME: Once using 2.50, use this: +# m4_match([$1], [^TRUE\|FALSE$], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_DEFUN([AM_CONDITIONAL], +[ifelse([$1], [TRUE], + [errprint(__file__:__line__: [$0: invalid condition: $1 +])dnl +m4exit(1)])dnl +ifelse([$1], [FALSE], + [errprint(__file__:__line__: [$0: invalid condition: $1 +])dnl +m4exit(1)])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +# serial 3 + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. We must strip everything past the first ":", +# and everything past the last "/". + +AC_PREREQ([2.12]) + +AC_DEFUN([AM_CONFIG_HEADER], +[ifdef([AC_FOREACH],dnl + [dnl init our file count if it isn't already + m4_ifndef([_AM_Config_Header_Index], m4_define([_AM_Config_Header_Index], [0])) + dnl prepare to store our destination file list for use in config.status + AC_FOREACH([_AM_File], [$1], + [m4_pushdef([_AM_Dest], m4_patsubst(_AM_File, [:.*])) + m4_define([_AM_Config_Header_Index], m4_incr(_AM_Config_Header_Index)) + dnl and add it to the list of files AC keeps track of, along + dnl with our hook + AC_CONFIG_HEADERS(_AM_File, +dnl COMMANDS, [, INIT-CMDS] +[# update the timestamp +echo timestamp >"AS_ESCAPE(_AM_DIRNAME(]_AM_Dest[))/stamp-h]_AM_Config_Header_Index[" +][$2]m4_ifval([$3], [, [$3]]))dnl AC_CONFIG_HEADERS + m4_popdef([_AM_Dest])])],dnl +[AC_CONFIG_HEADER([$1]) + AC_OUTPUT_COMMANDS( + ifelse(patsubst([$1], [[^ ]], []), + [], + [test -z "$CONFIG_HEADERS" || echo timestamp >dnl + patsubst([$1], [^\([^:]*/\)?.*], [\1])stamp-h]),dnl +[am_indx=1 +for am_file in $1; do + case " \$CONFIG_HEADERS " in + *" \$am_file "*) + am_dir=\`echo \$am_file |sed 's%:.*%%;s%[^/]*\$%%'\` + if test -n "\$am_dir"; then + am_tmpdir=\`echo \$am_dir |sed 's%^\(/*\).*\$%\1%'\` + for am_subdir in \`echo \$am_dir |sed 's%/% %'\`; do + am_tmpdir=\$am_tmpdir\$am_subdir/ + if test ! -d \$am_tmpdir; then + mkdir \$am_tmpdir + fi + done + fi + echo timestamp > "\$am_dir"stamp-h\$am_indx + ;; + esac + am_indx=\`expr \$am_indx + 1\` +done]) +])]) # AM_CONFIG_HEADER + +# _AM_DIRNAME(PATH) +# ----------------- +# Like AS_DIRNAME, only do it during macro expansion +AC_DEFUN([_AM_DIRNAME], + [m4_if(m4_regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1, + m4_if(m4_regexp([$1], [^//\([^/]\|$\)]), -1, + m4_if(m4_regexp([$1], [^/.*]), -1, + [.], + m4_patsubst([$1], [^\(/\).*], [\1])), + m4_patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])), + m4_patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl +]) # _AM_DIRNAME + +# 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 +]) + +#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.] ) +]) + +#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. +# +# 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 10 + +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) + + 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. +# +# 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 + +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 + fi + 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 +]) + +#serial 2 + +# 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.")] + ) +]) + diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..ed2e03b --- /dev/null +++ b/config.guess @@ -0,0 +1,1321 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# 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,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 c99 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..b004d30 --- /dev/null +++ b/config.h.in @@ -0,0 +1,310 @@ +/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* 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 + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* 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 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares struct tm. */ +#undef TM_IN_SYS_TIME + +/* 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 + +/* Linux */ +#undef HAVE_LINUX + +/* FreeBSD */ +#undef HAVE_FREEBSD + +/* OpenBSD */ +#undef HAVE_OPENBSD + +/* Solaris */ +#undef HAVE_SOLARIS + +/* NetBSD */ +#undef HAVE_NETBSD + +/* 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 + +/* Define if you have the DONE_WORKING_MALLOC_CHECK function. */ +#undef HAVE_DONE_WORKING_MALLOC_CHECK + +/* Define if you have the DONE_WORKING_REALLOC_CHECK function. */ +#undef HAVE_DONE_WORKING_REALLOC_CHECK + +/* Define if you have the RAND_pseudo_bytes function. */ +#undef HAVE_RAND_PSEUDO_BYTES + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the asprintf function. */ +#undef HAVE_ASPRINTF + +/* Define if you have the daemon function. */ +#undef HAVE_DAEMON + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the fcloseall function. */ +#undef HAVE_FCLOSEALL + +/* Define if you have the feof_unlocked function. */ +#undef HAVE_FEOF_UNLOCKED + +/* Define if you have the fgets_unlocked function. */ +#undef HAVE_FGETS_UNLOCKED + +/* Define if you have the flock function. */ +#undef HAVE_FLOCK + +/* Define if you have the ftime function. */ +#undef HAVE_FTIME + +/* Define if you have the get_current_dir_name function. */ +#undef HAVE_GET_CURRENT_DIR_NAME + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getegid function. */ +#undef HAVE_GETEGID + +/* 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. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_EVP_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SHA_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define 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. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define 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 + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + +/* Define if you have the iconv() function. */ +#undef HAVE_ICONV + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Define if you have and nl_langinfo(CODESET). */ +#undef HAVE_LANGINFO_CODESET + +/* Define if your file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define to 1 if translation of program messages to the user's native language + is requested. */ +#undef ENABLE_NLS + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..f365797 --- /dev/null +++ b/config.sub @@ -0,0 +1,1443 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-07' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..2eed879 --- /dev/null +++ b/configure @@ -0,0 +1,5240 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors" +ac_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)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=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=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:584: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure: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 +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + am_backtick='`' + echo "configure: warning: ${am_backtick}missing' script is too old or missing" 1>&2 +fi + +for ac_prog in mawk gawk nawk awk +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure: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 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AWK="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AWK" && break +done + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure: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 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + : +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null + + +# test to see if srcdir already configured +if test "`CDPATH=:; cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run \"make distclean\" there first" 1>&2; exit 1; } +fi + +# Define the identity of the package. +PACKAGE=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 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure: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 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure: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 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure: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 + +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 + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure: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 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure: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 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + +am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +echo $ac_n "checking for style of include used by $am_make""... $ac_c" 1>&6 +echo "configure: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 +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote='"' + _am_result=BSD + fi +fi + + +echo "$ac_t""$_am_result" 1>&6 +rm -f confinc confmf + + +depcc="$CC" am_compiler_list= + +echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6 +echo "configure: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 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi + +echo "$ac_t""$am_cv_CC_dependencies_compiler_type" 1>&6 +CCDEPMODE="depmode=$am_cv_CC_dependencies_compiler_type" + + +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 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +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 +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 + +test -n "$AWK" && break +done + +# 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 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether 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 +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking 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 + + + 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 + fi + 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 ;; +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" + 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 < +#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* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure: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; +} +main () +{ + exit (find_stack_direction() < 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 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&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 + +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 +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* +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 <&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 <&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 <&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 +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: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" +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 + + 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 +#include +#include +#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 +#else +$ac_func(); +#endif + +; 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 + +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 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 + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* 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 + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * 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); + + /* + * 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); + + /* + * 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); +} + +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 +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 +fi +done + + 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 +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: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* +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 + + + + + # 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 + +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 +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 +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 +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 +#else +$ac_func(); +#endif + +; 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" +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 + + 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 +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: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 +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 +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 + + + CATOBJEXT=.gmo + fi + +else + echo "$ac_t""no" 1>&6 +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 +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 +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 +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" +fi +fi +INTLBISON="$ac_cv_prog_INTLBISON" +if test -n "$INTLBISON"; then + echo "$ac_t""$INTLBISON" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$INTLBISON" && break +done + + 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;; + esac + echo "$ac_t""$ac_prog_version" 1>&6 + 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" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 + + 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 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $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 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&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 +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" +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" +LIBS="-lnsl $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 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + +fi + + +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + + + +# Check whether --with-kernel or --without-kernel was given. +if test "${with_kernel+set}" = set; then + withval="$with_kernel" + kerneldir="$withval" +else + kerneldir="/usr/src/linux" + +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 +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" +LIBS="-lz $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 -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 + + +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 + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile +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 +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'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS < "\$am_dir"stamp-h\$am_indx + ;; + esac + am_indx=\`expr \$am_indx + 1\` +done +AMDEP_TRUE="$AMDEP_TRUE" +ac_aux_dir="$ac_aux_dir" + + +EOF +cat >> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +test x"$AMDEP_TRUE" != x"" || +for mf in $CONFIG_FILES; do + case "$mf" in + Makefile) dirpart=.;; + */Makefile) dirpart=`echo "$mf" | sed -e 's|/[^/]*$||'`;; + *) continue;; + esac + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`echo "$file" | sed -e 's|/[^/]*$||'` + $ac_aux_dir/mkinstalldirs "$dirpart/$fdir" > /dev/null 2>&1 + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + +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 + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..6114a08 --- /dev/null +++ b/configure.in @@ -0,0 +1,125 @@ +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/depcomp b/depcomp new file mode 100755 index 0000000..6589965 --- /dev/null +++ b/depcomp @@ -0,0 +1,411 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 AIX compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + + tmpdepfile1="$object.d" + tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` + if test "$libtool" = yes; then + "$@" -Wc,-MD + else + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + test -z "$dashmflag" && dashmflag=-M + ( IFS=" " + case " $* " in + *" --mode=compile "*) # this is libtool, let us make it quiet + for arg + do # cycle over the arguments + case "$arg" in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + # X makedepend + ( + shift + cleared=no + for arg in "$@"; do + case $cleared in no) + set ""; shift + cleared=yes + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tail +3 "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/doc/GNUmakefile b/doc/GNUmakefile new file mode 100644 index 0000000..8fb7a6b --- /dev/null +++ b/doc/GNUmakefile @@ -0,0 +1,23 @@ +# 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 new file mode 100644 index 0000000..b62feb7 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,25 @@ +## Process this file with automake to get Makefile.in + +SUBDIRS = es + +info_TEXINFOS = tinc.texi + +dyn_MANS = +man_aux = $(dyn_MANS:.8=.x) + +man_MANS = tincd.8 tinc.conf.5 $(dyn_MANS) + +PERL = @PERL@ +HELP2MAN = help2man +MAINTAINERCLEANFILES = $(dyn_MANS) + +EXTRA_DIST = $(man_MANS) $(HELP2MAN) $(man_aux) \ + Makefile.maint GNUmakefile Makefile.summ sample-config.tar.gz + +# 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@ + +# For additional rules usually of interest only to the maintainer, +# see GNUmakefile and Makefile.maint. diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..28ae503 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,539 @@ +# 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) +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@ +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 +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +INFO_DEPS = tinc.info +DVIS = tinc.dvi +TEXINFOS = tinc.texi + +NROFF = nroff +MANS = $(man_MANS) + +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 + +.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 + +tinc.info: tinc.texi +tinc.dvi: tinc.texi + +.texi.info: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) \ + `echo $< | sed 's,.*/,,'` + +.texi.dvi: + TEXINPUTS=$(srcdir):$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2DVI) $< + +.texi: + @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9] + cd $(srcdir) \ + && $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) \ + `echo $< | sed 's,.*/,,'` + +MAKEINFO = @MAKEINFO@ +TEXI2DVI = texi2dvi +DVIPS = dvips +.dvi.ps: + $(DVIPS) $< -o $@ + +uninstall-info-am: + $(PRE_UNINSTALL) + @if (install-info --version && \ + install-info --version | fgrep -i -v debian) >/dev/null 2>&1; 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; \ + 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]; \ + else :; fi); \ + done + +dist-info: $(INFO_DEPS) + 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; \ + 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 + +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; \ + done + +man5dir = $(mandir)/man5 +install-man5: $(man5_MANS) $(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; \ + 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 +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) + @$(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; \ + 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 +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 + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) + +GTAGS: + here=`CDPATH=: && cd $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + $(mkinstalldirs) "$(distdir)/$$dir"; \ + fi; \ + if test -d $$d/$$file; then \ + cp -pR $$d/$$file $(distdir) \ + || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="${top_distdir}" distdir="$(distdir)" \ + dist-info +check-am: all-am +check: check-recursive +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 + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: $(DVIS) + +info: info-recursive + +info-am: $(INFO_DEPS) + +install-data-am: install-info-am install-man + +install-exec-am: + +install-info: install-info-recursive + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(infodir) + @list='$(INFO_DEPS)'; \ + 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; \ + else : ; fi; \ + done; \ + done + @$(POST_INSTALL) + @if (install-info --version && \ + install-info --version | fgrep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ + install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ + done; \ + else : ; fi +install-man: install-man5 install-man8 + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-aminfo \ + maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-aminfo mostlyclean-generic + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-info: uninstall-info-recursive + +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 + + +# For additional rules usually of interest only to the maintainer, +# see GNUmakefile and Makefile.maint. +# 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 new file mode 100644 index 0000000..75804f0 --- /dev/null +++ b/doc/Makefile.maint @@ -0,0 +1,38 @@ +# 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 new file mode 100644 index 0000000..a97b492 --- /dev/null +++ b/doc/Makefile.summ @@ -0,0 +1,2 @@ +# -*- makefile -*- +tincd-summary = tinc VPN daemon diff --git a/doc/es/Makefile.am b/doc/es/Makefile.am new file mode 100644 index 0000000..756d670 --- /dev/null +++ b/doc/es/Makefile.am @@ -0,0 +1,3 @@ +## 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 new file mode 100644 index 0000000..7261008 --- /dev/null +++ b/doc/es/Makefile.in @@ -0,0 +1,218 @@ +# 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 new file mode 100755 index 0000000..71778a9 --- /dev/null +++ b/doc/help2man @@ -0,0 +1,375 @@ +#!/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 <7g!&`6?Q?9@Pj<+aG#WkH-4=%Ea2?F}b zItjDCvpBXt=Xeox;v|k(6eex_dnbxIFCclI;W#Wouk8QP$KErXfhX;Mo7y{_cH8ZL z6L`4)mw9gLwLu%){;&Oy;#K~$AW4w_^^U?}6UJq!e^;rON>zUG@?zZeCwV65B(%Qv z*c_f88~87#xt1m`W_8)v%Kxyl#{V#2iQ|70Fj5WtVLtFz4uYfp&w_{iKT)QTLf2?x z8~>vyS-t-;7RHYMjleH7|NC0ZylEkCeC9DP^qAk{2L9j*SOhHYMtfb>fe<&%_pgo) z4iDb9eDWK+!~9mwbt1o4DmWE=U;%`zn{>JfBb{(fr<^`f!=tk~*9o`l9OL~(8|@>U z7u$}9{J-Mknr&>2|G|3v$Be+;{~N)aHD7xe4qpkY{I6VR-8PU~~Pi zItb1I{P=i`|8-UYxAC9FY`y*;2af-Zz~||7!tcs!r-g(+`3%AY*dCSFqV>XGUzjI| zA3GoNZR0Wi*I5O8di{?jfxG`V0$2b0xv`1=HYC(&V;le5^tVogX+W67v3>s+hwlAf zBiMnSJpn*l57jX!3vOhtU?fw~YVE+)L_i^U3TGF
c>4fzPnL~5Y?!RmT-@f zlv)g-KZD#%L~-A)z1G28cOO_7d0`ZLQR1~bWa1((j4HD}YK-y%P$|!(8q|6 z2ghQ>%hUjxZ6}G>A|>n$pQ(#p*;m2b>Oe-r=didUzN zZT#6t0&(o(Q)yf&rihUBRsbE=KuSNAb2iE5q__Z zVwL~P9|o!KjBUODx9R;)7~w{BUf5eh@oBrbuz5iu_<9`#_dFl71^7UjT&=1mF3k`G+g33PW)t z2Lc1V995?UemOh8I=MVOI6ASC&NqCA*uejCTC)m=gw(*2-?RT<<(ftPhq zJQMSq^|F~Rik{B@`kp?P0H##_efzTCp}R9)#L+lO7jitQx_ym(^h;xV7nER-I#)wD z#o-?Ij;qTKEyQ3fsyErhTWk0qJH1v!jtX$smf|n z*nP(JwFj3X6OW~EKs0OvNQ>}$eRmGM-9smLlWJd!lN+&HoOq6%A#7(&d?=wILku*-|7iy;l;q5rp^x3AU4mi&(; zY~BB}pzZR%MsQdEu?3jN>c5q*~(!%1kP%c6jqj$UbN} zR;a9gHK0u)2PT~%`%zW%Vn*=-(p-%zmz9^}iH#f?pV{a^PAi90@XGO_*Fhgd581TH zDGC*W4|!jv(#)Xy3dKL7v*vxA4@H4$R0f5p05jm49GezOOM|ZTu4ZN9(1t?Q<=jzw zt#gvt2m4}Vp(T~69J_UbILvts%0@hz|53GAsy(o)Zy|v>@3&Te3YiJ9IQrJe4Ync3Zaz{M#{&6DGAZ9Rxp!#;NzN- zhE>=U|Gn06HO&2oN{h+ZTMQnT+ld@Z?D8$@dsLKLspj3+-sI5;>sIDGT?7sYZ(kN{8s0Bv201poj5 literal 0 HcmV?d00001 diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..aa52853 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,5484 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{1999-01-05}% +% +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98 +% Free Software Foundation, Inc. +% +% This texinfo.tex 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, or (at +% your option) any later version. +% +% This texinfo.tex file is distributed in the hope that 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 texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% 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! +% +% 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 +% 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. +% +% 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: +% 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. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexi=\i +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexstar=\* +\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 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% 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 + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset +\newdimen \normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% 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. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\ifx\eTeXversion\undefined +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% +\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 +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % 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}% + % + {% + % 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. + \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 + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \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 + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\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 +\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}} + +% 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. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% 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}% + }% +} + +% 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}} + +% \argremovec{,omment} might leave us with trailing spaces, though; 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 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 +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\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. +% +\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 + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% 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 +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% 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 + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % 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 + % + % 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 + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\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 + % 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 +} + +% @br forces paragraph break + +\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 +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\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}} + +% 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}}}} + +% @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}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\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. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\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}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\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% +\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. +% +\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 +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text. +% +\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 + \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 +} +% 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'']}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \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 +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @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}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\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. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Use Computer Modern fonts at \magstephalf (11pt). +\newcount\mainmagstep +\mainmagstep=\magstephalf + +% 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} + +% 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 +\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\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\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} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% 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} + +% 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 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} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} + +% 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} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% 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} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\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 + +% 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} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\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. + +% 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). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% 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}} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% 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} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \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} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% 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. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #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 + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% 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. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \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} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @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 + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \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} + +\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 +} + +% 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 + +% 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 } + +% 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} + +% @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} + +% 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 + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\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 + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\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{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\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 +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @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{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\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{% + \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 +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\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{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\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{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\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} + +% 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}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, 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). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\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}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \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 + \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. + \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 + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \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}{}{}{}{}} + +% @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 % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\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 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% 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} +\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 + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, 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 +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\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 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @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. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\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 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \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. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \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 ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item\crcr + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}% + % + % 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 +} + +\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. +\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 +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\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. +\fi} + + +\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}} + +% \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. +% 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\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\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @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}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the 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}} + +% 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\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}}% +% +% 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 +} + +% 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}} + +% \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{...} + +\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\@{@}% +} + +% 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 + {% + \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 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\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 + \dobreak \chapheadingskip{10000}% + % + \indexfonts \rm + \tolerance = 9500 + \indexbreaks + % + % 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 + \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) + \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 + \ifeof 1 + (Index is empty) + \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 + \fi + \fi + \closein 1 +\endgroup} + +% 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 + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % 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 + % + % Do our best not to break after the initial. + \nobreak +}} + +% 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} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +% 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 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % 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 + % + % Unvbox the main output page. + \unvbox255 + \kern-\topskip \kern\baselineskip + }}% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \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. + \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 + \penalty\outputpenalty +} +\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}% +} +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \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 + % 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 +} +\def\balancecolumns{% + % Called at the end of the double column material. + \setbox0 = \vbox{\unvbox255}% 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}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/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} + \else + \numberedsubsubseczzz{#2} + \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} + \else + \appendixsubsubseczzz{#2} + \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} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + +% @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 +} + +\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 +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @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 +} + +% 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\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 +} + +\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 +} + +% 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 +} + +\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 +} + +\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 +} + +% 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 +} + +\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 +} + +\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 +} + +% 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 + +% 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{\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} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% 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) +\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 + +\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} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\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{% + \pchapsepmacro + {% + \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 + \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\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. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% 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}} + +% 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}} + + +% Print any size 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 + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\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}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak +} + + +\message{toc,} +\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. +% +\newif\iftocfileopened +\def\writetocentry#1{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + \iflinks \write\tocfile{#1{\folio}}\fi +} + +\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. +% +\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 +} + + +% 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 +} + +% 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 +} +\let\shortcontents = \summarycontents + +% 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}}% +} + +% 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 + +\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}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% 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}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\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} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% 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. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie + \catcode `\%=14 + \catcode 43=12 % plus + \catcode`\"=12 + \catcode`\==12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% 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 +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\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}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\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 +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % 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 + \parindent = 0pt + \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 + \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 +} + +% @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. +% +\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. +% 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 + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% @smalldisplay (when @smallbook): @display plus smaller fonts. +% +\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 + \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). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\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 + \let\nonarrowing = \relax + \fi +} + + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\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 + +\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 +} +% +% 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 } +% 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`\]}} + +% 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\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 +} + +% 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 +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% 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 +} + +% 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\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, +% 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} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=12\catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% 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 +% body, and then making it the \newlinechar in \scanmacro. + +\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\macroargctxt{% + \catcode`\~=12 + \catcode`\^=12 + \catcode`\_=12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \catcode`\+=12 + \catcode`\@=12 + \catcode`\\=12} + +% \mbodybackslash is the definition of \ in @macro bodies. +% 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\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \expandafter\ifx \csname macsave.\the\macname\endcsname \relax + \cslet{macsave.\the\macname}{\the\macname}% + \else + \message{Warning: redefining \the\macname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \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.}% + \else + \cslet{#1}{macsave.#1}% + \expandafter\let \csname macsave.\the\macname\endcsname \undefined + \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. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% 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. +% +% 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,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \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.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% 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 + \else + \ifcase\paramno + % 0 + \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,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\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} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + + +\message{cross references,} +\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{}}, + 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 + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \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 +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\def\anchor#1{\setref{#1}{Ynothing}} + + +% \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} +}} + +% @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\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 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}% + \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}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\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 + }% + % [mynode], + [\printednodename],\space + % page 3 + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\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 + }% +} + +% \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. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \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 +} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \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. + % + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \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`\{=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 +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % 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 + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% 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 +% the footnote is read. --karl, 16nov96. +% +\long\gdef\footnotezzz{\insert\footins\bgroup + % 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. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \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 + \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 + }% +} + +% @| 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 + }% + }% +} + +% 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} + +% @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). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +\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.} +% +% Only complain once about lack of epsf.tex. +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \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 + % If the image is by itself, center it. + \ifvmode + \nobreak\medskip + \nobreak + \centerline{\epsfbox{#1.eps}}% + \bigbreak + \else + \epsfbox{#1.eps}% + \fi +} + + +\message{paper sizes,} +% And other related parameters. + +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just 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. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = \hsize + \divide\emergencystretch by 45 + \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. +% +\def\internalpagesizes#1#2#3#4#5#6{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \setleading{13.2pt}% + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \setleading{12pt}% + % + \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \deftypemargin = 0pt + \defbodyindent = .5cm + % + \let\smalldisplay = \smalldisplayx + \let\smallexample = \smalllispx + \let\smallformat = \smallformatx + \let\smalllisp = \smalllispx +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \setleading{12pt}% + \parskip = 3pt plus 2pt minus 1pt + % + \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}% + % + \tolerance = 700 + \hfuzz = 1pt +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex{{\globaldefs = 1 + \setleading{13.6pt}% + % + \afourpaper + \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}% + % + \globaldefs = 0 +}} + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{% + \afourpaper + \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}% + % + \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} +\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}% + % + \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}% +}} + +% Set default to letter. +% +\letterpaper + +\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{+} + +% 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, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. 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, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% 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_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% 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 + +% 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} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% 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} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% 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 + +% 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} + +% 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 + +@textfonts +@rm + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d" +@c time-stamp-end: "}" +@c End: diff --git a/doc/tinc.conf.5 b/doc/tinc.conf.5 new file mode 100644 index 0000000..2dfdf07 --- /dev/null +++ b/doc/tinc.conf.5 @@ -0,0 +1,340 @@ +.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.info b/doc/tinc.info new file mode 100644 index 0000000..71dcb80 --- /dev/null +++ b/doc/tinc.info @@ -0,0 +1,79 @@ +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. + + +Indirect: +tinc.info-1: 888 +tinc.info-2: 49234 + +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 + +End Tag Table diff --git a/doc/tinc.info-1 b/doc/tinc.info-1 new file mode 100644 index 0000000..a893700 --- /dev/null +++ b/doc/tinc.info-1 @@ -0,0 +1,1317 @@ +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 new file mode 100644 index 0000000..c76d214 --- /dev/null +++ b/doc/tinc.info-2 @@ -0,0 +1,520 @@ +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 new file mode 100644 index 0000000..5ce852e --- /dev/null +++ b/doc/tinc.texi @@ -0,0 +1,1893 @@ +\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 + +@ifinfo +@dircategory Networking tools +@direntry +* tinc: (tinc). The tinc Manual. +@end direntry + +This is the info manual for tinc, 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 $ + +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. + +@end ifinfo + +@titlepage +@title tinc Manual +@subtitle Setting up a Virtual Private Network with tinc +@author Ivo Timmermans and Guus Sliepen + +@page +@vskip 0pt plus 1filll +@cindex copyright +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 $ + +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. + +@end titlepage + +@c ================================================================== +@node Top, Introduction, (dir), (dir) + +@menu +* Introduction:: Introduction +* Preparations:: +* Installation:: +* Configuration:: +* Running tinc:: +* Technical information:: +* About us:: +* Concept Index:: All used terms explained +@end menu + + +@contents + +@c ================================================================== +@node Introduction, Preparations, Top, Top +@chapter Introduction + +@cindex tinc +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:: +@end menu + +@c ================================================================== +@node VPNs, tinc, Introduction, Introduction +@section Virtual Private Networks + +@cindex VPN +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. + +@cindex private +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 @emph{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. + +@cindex virtual +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 +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. + + +@c ================================================================== +@node tinc, Supported platforms, VPNs, Introduction +@section tinc + +@cindex vpnd +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}. + +Since then, a lot has changed---to say the least. + +@cindex tincd +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 scalability +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. + + +@c ================================================================== +@node Supported platforms, , tinc, Introduction +@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 +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. + +@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. + + +@c +@c +@c +@c +@c +@c +@c Preparing your system +@c +@c +@c +@c +@c + +@c ================================================================== +@node Preparations, Installation, Introduction, Top +@chapter Preparations + +This chapter contains information on how to prepare your system to +support tinc. + +@menu +* Configuring the kernel:: +* Libraries:: +@end menu + + +@c ================================================================== +@node Configuring the kernel, Libraries, Preparations, Preparations +@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 FreeBSD kernels:: +* Configuration of OpenBSD kernels:: +* Configuration of Solaris kernels:: +@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 + +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 +Network device support + Universal tun/tap device driver support +@end example + +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}: + +@example +alias char-major-10-200 tun +@end example + + +@c ================================================================== +@node Configuration of FreeBSD kernels, Configuration of OpenBSD kernels, Configuration of Linux kernels 2.4.0 and higher, Configuring the kernel +@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. + + +@c ================================================================== +@node Configuration of OpenBSD kernels, Configuration of Solaris kernels, Configuration of FreeBSD kernels, Configuring the kernel +@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. + + +@c ================================================================== +@node Configuration of Solaris kernels, , Configuration of OpenBSD kernels, Configuring the kernel +@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. + + +@c ================================================================== +@node Libraries, , Configuring the kernel, Preparations +@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. + +@menu +* OpenSSL:: +* zlib:: +@end menu + + +@c ================================================================== +@node OpenSSL, zlib, Libraries, Libraries +@subsection OpenSSL + +@cindex 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 @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 +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. + +@example +--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) +@end example + + +@subsubheading License + +@cindex license +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): + +@quotation +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. +@end quotation + + +@c ================================================================== +@node zlib, , OpenSSL, Libraries +@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. + +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, +build and install this package are included within the package. Please +make sure you build development and runtime libraries (which is the +default). + + +@c +@c +@c +@c Installing tinc +@c +@c +@c +@c + +@c ================================================================== +@node Installation, Configuration, Preparations, Top +@chapter 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 +@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. + +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 @file{INSTALL}, which is +included in the source distribution. + +@menu +* Building and installing tinc:: +* System files:: +@end menu + + +@c ================================================================== +@node Building and installing tinc, System files, Installation, Installation +@section Building and installing tinc + +Detailed instructions on configuring the source, building tinc and installing tinc +can be found in the file called @file{INSTALL}. + +@cindex binary package +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. + + +@c ================================================================== +@node System files, , Building and installing tinc, Installation +@section 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:: +@end menu + + +@c ================================================================== +@node Device files, Other files, System files, System 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. + +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: + +@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} +@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 +@subsection Other files + +@subsubheading @file{/etc/networks} + +You may add a line to @file{/etc/networks} so that your VPN will get a +symbolic name. For example: + +@example +myvpn 10.0.0.0 +@end example + +@subsubheading @file{/etc/services} + +@cindex port numbers +You may add this line to @file{/etc/services}. The effect is that you +may supply a @samp{tinc} as a valid port number to some programs. The +number 655 is registered with the IANA. + +@example +tinc 655/tcp TINC +tinc 655/udp TINC +# Ivo Timmermans +@end example + + +@c +@c +@c +@c +@c Configuring tinc +@c +@c +@c +@c + + +@c ================================================================== +@node Configuration, Running tinc, Installation, Top +@chapter Configuration + +@menu +* Configuration introduction:: +* Multiple networks:: +* How connections work:: +* Configuration files:: +* Generating keypairs:: +* Network interfaces:: +* Example configuration:: +@end menu + +@c ================================================================== +@node Configuration introduction, Multiple networks, Configuration, Configuration +@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: +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 +@uref{http://www.linuxdoc.org/LDP/nag2/, Linux Network Administrators Guide}. + +If you have everything clearly pictured in your mind, +proceed in the following order: +First, generate the configuration files (@file{tinc.conf}, your host configuration file, @file{tinc-up} and perhaps @file{tinc-down}). +Then generate the keypairs. +Finally, distribute the host configuration files. +These steps are described in the subsections below. + + +@c ================================================================== +@node Multiple networks, How connections work, Configuration introduction, Configuration +@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. +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. + + +@c ================================================================== +@node How connections work, Configuration files, Multiple networks, Configuration +@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. +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. + +@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. + + +@c ================================================================== +@node Configuration files, Generating keypairs, How connections work, Configuration +@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/}. + +These file consists of comments (lines started with a #) or assignments +in the form of + +@example +Variable = Value. +@end example + +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 @strong{bold}. + +@menu +* Main configuration variables:: +* Host configuration variables:: +* How to configure:: +@end menu + + +@c ================================================================== +@node Main configuration variables, Host configuration variables, Configuration files, Configuration files +@subsection Main configuration variables + +@table @asis +@cindex AddressFamily +@item 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. + +@cindex BindToInterface +@item 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. + +@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. + +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. + +@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}. + +@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 +it does a lookup if your DNS server is not responding. + +This does not affect resolving hostnames to IP addresses from the +configuration file. + +@cindex Interface +@item 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. + +@cindex Mode +@item Mode = (router) +This option selects the way packets are routed to other daemons. + +@table @asis +@cindex router +@item 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. + +@cindex switch +@item 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. + +@cindex hub +@item 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. +@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 + +@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. + +@cindex PriorityInheritance +@item 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. + +@cindex PrivateKey +@item 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. + +@cindex PrivateKeyFile +@item @strong{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. + +@end table + + +@c ================================================================== +@node Host configuration variables, How to configure, Main configuration variables, Configuration files +@subsection Host configuration variables + +@table @asis +@cindex Address +@item @strong{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. + +@cindex Cipher +@item Cipher = (blowfish) +The symmetric cipher algorithm used to encrypt UDP packets. +Any cipher supported by OpenSSL is recognized. + +@cindex Compression +@item 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). + +@cindex Digest +@item 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. + +@cindex IndirectData +@item 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. + +@cindex MACLength +@item 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. + +@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. + +@cindex PublicKey +@item PublicKey = [obsolete] +This is the RSA public key for this host. + +@cindex PublicKeyFile +@item 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. + +@cindex PEM format +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 +@strong{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. + +@cindex Subnet +@item 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. + +@cindex CIDR notation +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} + +@cindex TCPonly +@item 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. +@end table + + +@c ================================================================== +@node How to configure, , Host configuration variables, Configuration files +@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}. +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 +@end example + +Then, if you know to which other tinc daemon(s) yours is going to connect, +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}. +Adapt the following example to create a host configuration file: + +@example +Address = @emph{your.real.hostname.org} +Subnet = @emph{192.168.1.0/24} +@end example + +You can also use an IP address instead of a hostname. +The `Subnet' specifies the address range that is local for @emph{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). + + +@c ================================================================== +@node Generating keypairs, Network interfaces, Configuration files, Configuration +@section Generating keypairs + +@cindex key generation +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: + +@example +tincd -n @emph{netname} -K +@end example + +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 +@section 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 (@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. + +@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. + +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. +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. +@cindex netmask +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. + + +@c ================================================================== +@node Example configuration, , Network interfaces, Configuration +@section Example configuration + + +@cindex example +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. + +@example +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 +@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 +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. + +@subsubheading For Branch A + +@emph{BranchA} would be configured like this: + +In @file{/etc/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 tap0 hw ether fe:fd:0:0:0:0 +ifconfig tap0 10.1.54.1 netmask 255.0.0.0 +ifconfig tap0 -arp +@end example + +and in @file{/etc/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: + +@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 + + +@subsubheading For Branch B + +In @file{/etc/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 tap0 hw ether fe:fd:0:0:0:0 +ifconfig tap0 10.2.1.12 netmask 255.0.0.0 +ifconfig tap0 -arp +@end example + +and in @file{/etc/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. + +On all hosts, in @file{/etc/tinc/company/hosts/BranchB}: + +@example +Subnet = 10.2.0.0/16 +Address = 2.3.4.5 + +-----BEGIN RSA PUBLIC KEY----- +... +-----END RSA PUBLIC KEY----- +@end example + + +@subsubheading For Branch C + +In @file{/etc/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 tap1 hw ether fe:fd:0:0:0:0 +ifconfig tap1 10.3.69.254 netmask 255.0.0.0 +ifconfig tap1 -arp +@end example + +and in @file{/etc/tinc/company/tinc.conf}: + +@example +Name = BranchC +ConnectTo = BranchA +Device = /dev/tap1 +@end example + +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}: + +@example +Address = 3.4.5.6 +Subnet = 10.3.0.0/16 +Port = 2000 + +-----BEGIN RSA PUBLIC KEY----- +... +-----END RSA PUBLIC KEY----- +@end example + + +@subsubheading For Branch D + +In @file{/etc/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 company hw ether fe:fd:0:0:0:0 +ifconfig company 10.4.3.32 netmask 255.0.0.0 +ifconfig company -arp +@end example + +and in @file{/etc/tinc/company/tinc.conf}: + +@example +Name = BranchD +ConnectTo = BranchC +Device = /dev/misc/net/tun +PrivateKeyFile = /etc/tinc/company/rsa_key.priv +@end example + +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 @file{/etc/tinc/company/hosts/BranchD}: + +@example +Subnet = 10.4.0.0/16 +Address = 4.5.6.7 + +-----BEGIN RSA PUBLIC KEY----- +... +-----END RSA PUBLIC KEY----- +@end example + +@subsubheading Key files + +A, B, C and D all have generated a public/private keypair with the following command: + +@example +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. +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). + +@subsubheading 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. + + +@c ================================================================== +@node Running tinc, Technical information, Configuration, Top +@chapter Running tinc + +If everything else is done, you can start tinc by typing the following command: + +@example +tincd -n @emph{netname} +@end example + +@cindex 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:: +* Error messages:: +@end menu + + +@c ================================================================== +@node Runtime options, Error messages, , Running tinc +@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}. + +@item -D, --no-detach +Don't fork and detach. +This will also disable the automatic restart mechanism for fatal errors. + +@item --version +Output version information and exit. + +@end table + + +@c ================================================================== +@node Error messages, , Runtime options, Running tinc +@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! + +@table @strong +@item Could not open /dev/tap0: No such device + +@itemize +@item You forgot to `modprobe netlink_dev' or `modprobe ethertap'. +@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 + +@itemize +@item You forgot to `modprobe tun'. +@item You forgot to compile `Universal TUN/TAP driver' in the kernel. +@end itemize + +@item Packet with destination 1.2.3.4 is looping back to us! + +@itemize +@item 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! +@item 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. +@end itemize + +@item Network doesn't work, syslog shows only packets of length 46 + +@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. +@end itemize + +@item Network address and prefix length do not match! + +@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. +@end itemize + +@item This is a bug: net.c:253: 24: Some error + +@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. +@end itemize + +@end table + +@c ================================================================== +@node Technical information, About us, Running tinc, Top +@chapter Technical information + + +@menu +* The connection:: +* The meta-protocol:: +* Security:: +@end menu + + +@c ================================================================== +@node The connection, The meta-protocol, Technical information, Technical information +@section The connection + +@cindex 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:: +@end menu + + +@c ================================================================== +@node The UDP tunnel, The meta-connection, The connection, The connection +@subsection The UDP tunnel + +@cindex virtual network device +@cindex frame type +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. + +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. + +@cindex encapsulating +@cindex UDP +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 +@emph{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. + + +@c ================================================================== +@node The meta-connection, , The UDP tunnel, The connection +@subsection 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. + +@cindex TCP +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. + +@cindex data-protocol +@cindex meta-protocol +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. + + +@c ================================================================== +@node The meta-protocol, Security, The connection, Technical information +@section 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 @ref{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. + +@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 + +origin ADD_SUBNET node 192.168.1.0/24 + | | +--> prefixlength + | +--------> IPv4 network address + +------------------> owner of this subnet +-------------------------------------------------------------------------- +@end example + +@cindex DEL_EDGE +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. + +@cindex REQ_KEY +@cindex ANS_KEY +@cindex KEY_CHANGED +@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 +-------------------------------------------------------------------------- +@end example + +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. + +@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. + + +@c ================================================================== +@node Security, , The meta-protocol, Technical information +@section About tinc's encryption and other security-related issues. + +@cindex TINC +@cindex Cabal +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. + +@cindex SVPN +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 +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:: +@end menu + + +@c ================================================================== +@node Authentication protocol, Encryption of network packets, Security, Security +@subsection Authentication protocol + +@cindex authentication +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. + +@cindex ID +@cindex META_KEY +@cindex CHALLENGE +@cindex CHAL_REPLY +@cindex ACK +@example +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 +-------------------------------------------------------------------------- +@end example + +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. + + +@c ================================================================== +@node Encryption of network packets, , Authentication protocol, Security +@subsection Encryption of network packet +@cindex encryption + +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. + +@cindex UDP +The UDP packet containing the network packet from the VPN has the following layout: + +@example +... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer + \___________________/\_____/ + | | + V +---> digest algorithm + 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 +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 +@chapter About us + + +@menu +* Contact Information:: +* Authors:: +@end menu + + +@c ================================================================== +@node Contact Information, Authors, About us, About us +@section Contact information + +@cindex website +tinc's website is at @url{http://tinc.nl.linux.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}, +and join channel #tinc. + + +@c ================================================================== +@node Authors, , Contact Information, About us +@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. + +@end table + +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 @file{THANKS} in +the source distribution. + + +@c ================================================================== +@node Concept Index, , About us, Top +@c node-name, next, previous, up +@unnumbered Concept Index + +@c ================================================================== +@printindex cp + + +@c ================================================================== +@contents +@bye diff --git a/doc/tincd.8 b/doc/tincd.8 new file mode 100644 index 0000000..831bbb1 --- /dev/null +++ b/doc/tincd.8 @@ -0,0 +1,174 @@ +.Dd 2002-03-25 +.Dt TINCD 8 +.\" Manual page created by: +.\" Ivo Timmermans +.\" Guus Sliepen +.Sh NAME +.Nm tincd +.Nd tinc VPN daemon +.Sh SYNOPSIS +.Nm +.Op Fl cdDkKn +.Op Fl -bypass-security +.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 -version +.Sh DESCRIPTION +This is the daemon of tinc, a secure virtual private network (VPN) project. +When started, +.Nm +will read it's configuration file to determine what virtual subnets it has to serve +and to what other tinc daemons it should connect. +It will connect to the ethertap or tun/tap device +and set up a socket for incoming connections. +Optionally a script will be executed to further configure the virtual device. +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. +.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 . +.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. +.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. +.It Fl -version +Output version information and exit. +.El +.Sh SIGNALS +.Bl -tag -width indent +.It ALRM +Forces +.Nm +to try to connect to all uplinks immediately. +Usually +.Nm +attempts to do this itself, +but increases the time it waits between the attempts each time it failed, +and if +.Nm +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. +.It INT +Temporarily increases debug level to 5. +Send this signal again to revert to the original level. +.It USR1 +Dumps the connection list to syslog. +.It USR2 +Dumps virtual network device statistics, all known nodes, edges and subnets to syslog. +.It WINCH +Purges all information remembered about unreachable nodes. +.El +.Sh 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: +.Bl -tag -width indent +.It 0 +This will log a message indicating +.Nm +has started along with a version number. +It will also 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. +.It 3 +This will log all requests that are exchanged with other tinc daemons. These include +authentication, key exchange and connection list updates. +.It 4 +This will log a copy of everything received on the meta socket. +.It 5 +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 +The PID of the currently running +.Nm +is stored in this file. +.El +.Sh BUGS +The +.Va BindToInterface +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. +.Sh TODO +A lot, especially security auditing. +.Sh SEE ALSO +.Xr tinc.conf 5 , +.Pa http://tinc.nl.linux.org/ , +.Pa http://www.cabal.org/ . +.Pp +The full documentation for 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 +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 +.Pp +And thanks to many others for their contributions to tinc! diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/intl/ChangeLog b/intl/ChangeLog new file mode 100644 index 0000000..84e2b37 --- /dev/null +++ b/intl/ChangeLog @@ -0,0 +1,4 @@ +2001-09-13 GNU + + * Version 0.10.40 released. + diff --git a/intl/Makefile.in b/intl/Makefile.in new file mode 100644 index 0000000..19ed4a7 --- /dev/null +++ b/intl/Makefile.in @@ -0,0 +1,313 @@ +# 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 new file mode 100644 index 0000000..cb8a01a --- /dev/null +++ b/intl/VERSION @@ -0,0 +1 @@ +GNU gettext library from gettext-0.10.40 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c new file mode 100644 index 0000000..c6a9bd1 --- /dev/null +++ b/intl/bindtextdom.c @@ -0,0 +1,369 @@ +/* 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 new file mode 100755 index 0000000..f4f2611 --- /dev/null +++ b/intl/config.charset @@ -0,0 +1,438 @@ +#! /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 new file mode 100644 index 0000000..b7c9652 --- /dev/null +++ b/intl/dcgettext.c @@ -0,0 +1,58 @@ +/* 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 new file mode 100644 index 0000000..6acde19 --- /dev/null +++ b/intl/dcigettext.c @@ -0,0 +1,1259 @@ +/* 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 new file mode 100644 index 0000000..c16af21 --- /dev/null +++ b/intl/dcngettext.c @@ -0,0 +1,60 @@ +/* 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 new file mode 100644 index 0000000..3651207 --- /dev/null +++ b/intl/dgettext.c @@ -0,0 +1,59 @@ +/* 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 new file mode 100644 index 0000000..f214e95 --- /dev/null +++ b/intl/dngettext.c @@ -0,0 +1,61 @@ +/* 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 new file mode 100644 index 0000000..2985064 --- /dev/null +++ b/intl/explodename.c @@ -0,0 +1,192 @@ +/* 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 new file mode 100644 index 0000000..2f103d5 --- /dev/null +++ b/intl/finddomain.c @@ -0,0 +1,198 @@ +/* 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 new file mode 100644 index 0000000..22a6c24 --- /dev/null +++ b/intl/gettext.c @@ -0,0 +1,64 @@ +/* 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 new file mode 100644 index 0000000..6f5d760 --- /dev/null +++ b/intl/gettext.h @@ -0,0 +1,102 @@ +/* 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 new file mode 100644 index 0000000..43de1cd --- /dev/null +++ b/intl/gettextP.h @@ -0,0 +1,252 @@ +/* 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 new file mode 100644 index 0000000..ccb7acc --- /dev/null +++ b/intl/hash-string.h @@ -0,0 +1,59 @@ +/* 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 new file mode 100644 index 0000000..0a06ce9 --- /dev/null +++ b/intl/intl-compat.c @@ -0,0 +1,166 @@ +/* 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 new file mode 100644 index 0000000..533e94b --- /dev/null +++ b/intl/l10nflist.c @@ -0,0 +1,405 @@ +/* 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 new file mode 100644 index 0000000..c5be54a --- /dev/null +++ b/intl/libgettext.h @@ -0,0 +1,49 @@ +/* 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 new file mode 100644 index 0000000..f891deb --- /dev/null +++ b/intl/libgnuintl.h @@ -0,0 +1,128 @@ +/* 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 new file mode 100644 index 0000000..b861260 --- /dev/null +++ b/intl/loadinfo.h @@ -0,0 +1,109 @@ +/* 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 new file mode 100644 index 0000000..f99ebee --- /dev/null +++ b/intl/loadmsgcat.c @@ -0,0 +1,567 @@ +/* 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 new file mode 100644 index 0000000..61f8f3e --- /dev/null +++ b/intl/localcharset.c @@ -0,0 +1,271 @@ +/* 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 new file mode 100644 index 0000000..bd7b9b3 --- /dev/null +++ b/intl/locale.alias @@ -0,0 +1,78 @@ +# 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 new file mode 100644 index 0000000..91e7acc --- /dev/null +++ b/intl/localealias.c @@ -0,0 +1,404 @@ +/* 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 new file mode 100644 index 0000000..fb3ec5a --- /dev/null +++ b/intl/ngettext.c @@ -0,0 +1,68 @@ +/* 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 new file mode 100644 index 0000000..640d43c --- /dev/null +++ b/intl/plural.c @@ -0,0 +1,1326 @@ + +/* 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 new file mode 100644 index 0000000..be049a6 --- /dev/null +++ b/intl/plural.y @@ -0,0 +1,413 @@ +%{ +/* 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 new file mode 100644 index 0000000..167374e --- /dev/null +++ b/intl/ref-add.sin @@ -0,0 +1,31 @@ +# 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 new file mode 100644 index 0000000..613cf37 --- /dev/null +++ b/intl/ref-del.sin @@ -0,0 +1,26 @@ +# 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 new file mode 100644 index 0000000..2e420ad --- /dev/null +++ b/intl/textdomain.c @@ -0,0 +1,142 @@ +/* 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 new file mode 100644 index 0000000..aa4d55a --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,15 @@ +## 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 new file mode 100644 index 0000000..0ae461d --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,338 @@ +# 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 new file mode 100644 index 0000000..d842e59 --- /dev/null +++ b/lib/README @@ -0,0 +1 @@ +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 new file mode 100644 index 0000000..10e5d65 --- /dev/null +++ b/lib/alloca.c @@ -0,0 +1,494 @@ +/* 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 new file mode 100644 index 0000000..a4f0051 --- /dev/null +++ b/lib/avl_tree.c @@ -0,0 +1,723 @@ +/* + 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 new file mode 100644 index 0000000..d1ad618 --- /dev/null +++ b/lib/avl_tree.h @@ -0,0 +1,145 @@ +/* + 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 new file mode 100644 index 0000000..66aaa31 --- /dev/null +++ b/lib/dropin.c @@ -0,0 +1,171 @@ +/* + 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 new file mode 100644 index 0000000..ad66d99 --- /dev/null +++ b/lib/dropin.h @@ -0,0 +1,38 @@ +/* + 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 new file mode 100644 index 0000000..300f86d --- /dev/null +++ b/lib/getopt.c @@ -0,0 +1,1053 @@ +/* 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 new file mode 100644 index 0000000..69256fd --- /dev/null +++ b/lib/getopt.h @@ -0,0 +1,133 @@ +/* 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/getopt1.c b/lib/getopt1.c new file mode 100644 index 0000000..6507ba1 --- /dev/null +++ b/lib/getopt1.c @@ -0,0 +1,189 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "getopt.h" + +#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__ +#include +#endif + +#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; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + 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; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + 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} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + 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; + + 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 '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"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/lib/list.c b/lib/list.c new file mode 100644 index 0000000..cb2d4d2 --- /dev/null +++ b/lib/list.c @@ -0,0 +1,197 @@ +/* + 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 new file mode 100644 index 0000000..3e1735b --- /dev/null +++ b/lib/list.h @@ -0,0 +1,82 @@ +/* + 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 new file mode 100644 index 0000000..b859e58 --- /dev/null +++ b/lib/malloc.c @@ -0,0 +1,39 @@ +/* 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 new file mode 100644 index 0000000..1226947 --- /dev/null +++ b/lib/memcmp.c @@ -0,0 +1,391 @@ +/* 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 new file mode 100644 index 0000000..a954d18 --- /dev/null +++ b/lib/pidfile.c @@ -0,0 +1,138 @@ +/* + 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/pidfile.h b/lib/pidfile.h new file mode 100644 index 0000000..19d19c1 --- /dev/null +++ b/lib/pidfile.h @@ -0,0 +1,50 @@ +/* + pidfile.h - 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. +*/ + +/* 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); + +/* 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); + +/* write_pid + * + * Writes the pid to the specified file. If that fails 0 is + * returned, otherwise the pid. + */ +int write_pid (char *pidfile); + +/* remove_pid + * + * Remove the the specified file. The result from unlink(2) + * is returned + */ +int remove_pid (char *pidfile); diff --git a/lib/realloc.c b/lib/realloc.c new file mode 100644 index 0000000..d0d3e4a --- /dev/null +++ b/lib/realloc.c @@ -0,0 +1,44 @@ +/* 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 new file mode 100644 index 0000000..d79532b --- /dev/null +++ b/lib/utils.c @@ -0,0 +1,87 @@ +/* + 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 new file mode 100644 index 0000000..0b79bfa --- /dev/null +++ b/lib/utils.h @@ -0,0 +1,57 @@ +/* + 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 new file mode 100644 index 0000000..caf0f37 --- /dev/null +++ b/lib/xalloc.h @@ -0,0 +1,26 @@ +#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 new file mode 100644 index 0000000..e1ab314 --- /dev/null +++ b/lib/xmalloc.c @@ -0,0 +1,156 @@ +/* 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 new file mode 100644 index 0000000..216417b --- /dev/null +++ b/m4/Makefile.am @@ -0,0 +1,19 @@ +## 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 new file mode 100644 index 0000000..9ee9c43 --- /dev/null +++ b/m4/Makefile.am.in @@ -0,0 +1,16 @@ +## 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 new file mode 100644 index 0000000..6c80fe3 --- /dev/null +++ b/m4/Makefile.in @@ -0,0 +1,232 @@ +# 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 new file mode 100644 index 0000000..df032df --- /dev/null +++ b/m4/README @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000..844e7d2 --- /dev/null +++ b/m4/aclocal-include.m4 @@ -0,0 +1,14 @@ +# 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/malloc.m4 b/m4/malloc.m4 new file mode 100644 index 0000000..bd3cad4 --- /dev/null +++ b/m4/malloc.m4 @@ -0,0 +1,44 @@ +#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 new file mode 100644 index 0000000..e5c0939 --- /dev/null +++ b/m4/openssl.m4 @@ -0,0 +1,49 @@ +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.")] + ) + ) +]) diff --git a/m4/perl.m4 b/m4/perl.m4 new file mode 100644 index 0000000..0cc681c --- /dev/null +++ b/m4/perl.m4 @@ -0,0 +1,39 @@ +#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 new file mode 100644 index 0000000..aba1984 --- /dev/null +++ b/m4/realloc.m4 @@ -0,0 +1,44 @@ +#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 new file mode 100644 index 0000000..0bee1ce --- /dev/null +++ b/m4/tuntap.m4 @@ -0,0 +1,39 @@ +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 new file mode 100644 index 0000000..d5fbc67 --- /dev/null +++ b/m4/zlib.m4 @@ -0,0 +1,31 @@ +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.")] + ) +]) diff --git a/missing b/missing new file mode 100755 index 0000000..0a7fb5a --- /dev/null +++ b/missing @@ -0,0 +1,283 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.3 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar ${1+"$@"} && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar ${1+"$@"} && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000..4f58503 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /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 new file mode 100644 index 0000000..c31f13f --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,28 @@ +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 new file mode 100644 index 0000000..28726a2 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,196 @@ +# 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 new file mode 100644 index 0000000..4e52a3a --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,33 @@ +# 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 new file mode 100644 index 0000000000000000000000000000000000000000..cf84ba6764e34eccd080a32f6a1d2cce3ef63195 GIT binary patch literal 26037 zcmbuH3w&I6b?0vgO|r@ZlJE)va_t~u6H9(121m}rvMt-flB`&AoH&H|YUXNmt(ki# z^N=i4o@EodO`<(MX|MNfpBR_J{Q{Nfz`6=mnq|col1P9Lug6h-sHVA&>8A0$# z@ZI1J-rxMpAb2s)cRwo#O5i8JE5Y#DL2w>82J$Mn#bF)X>L03&1Zrd<;~7=R79} z`oMmNTfmJx?*z{RV{kiI1vh}d1NMV|2CCeTL7ECKy(9=2VsI6B7(4)KT<--h1it`M zH269gf28xJqsQHUjlv*JOF+d90oT(KM0P1cYvDb7eMv*15o{(PvaB~)`J&; zH-PKF!=UKj0-pw-UI)@;a5t497%`O0dh}?V$2s4T=xH z+Ye+1OLe*!Y(U_FiSGuQ>L2P079e*-A~{5B|gdJw!E{NJGX z`aBA2{`)|^uYxZE-v;u3@KL@r-fw^^_cL$+yo|y$5sZT&n1Or2w}BepUxDiXF;H@I z)(b6NUjT|eSAnAI1gP;vAfghy8C3oEgA?G#!98Ffo$mlAKu8+g1zrulA5{KdgWJH6 z!H&3$=JB_n==YDH_;nc%XMwvx^*ajEbnto*5(OUsDH=QsYJ9%{wQirsqC5r; zf|~EIf($u$pL>1?6y5(GybA0?2zG{Ps=?MR zw*BKEQwZ(^MaTO=$=w5>#{V}i|0xIoqzN{IzXaY2if$38{@&!CKLTnT-vTAq|Ht98 z>0I;N2JQrpfa>RNP~*QBl>9shiqAiF`R77hz3&G_k8v;rn;;?_yaT)l{5Yt34}qfd zw?XxD4vXSEa4)EF-3ZlY2Yis3&0eV{JzTJ zr$EWqnJA45!2wY9ZvfTL5m5Vb1N;=v_tNM-o~zedI^BOAvcdaDK+$d2^|rrxQ0wfK z4&MVxU;QyCdHV$@`aS;!D=&LNjlTklUoBAWy%szRycZOGKMaQ8qoCyZDZ4D4H-pa# zf*=8(0lpTjfbRqmk>D4g=CyU$(se&5KF+x3yTDPNe+N{%-v^DJgIF)%dD!7`Q1xB| zif+FLUIsn{ia$RD*Ma9TS*@c%5Eci=z!C86;LE_Tf%D+yd+ombR&a{vFN2UW=%?_F zUH#Z9 zSAv)Dd?Tp&%!6w0*TBoc`@plohrzSJZ-A21M?uNo&m8taM7_Th6y2`^L$CshpKk=! z{{5iV;a9-z;297F(G6Y-iqCaWe7Fa^0{nAO*(xp+wLAv@9zL1VQ?o1%Yui% zUEswNmM_yFswP+f8FFwhD0=)e$dG~;AF}gZ0LAYQg3kee07}oDHEH>J38?2Q9bONr z-5Wv4<(;7B{XS6Z^#M@w_8o8ld_F=Hf(Jp3qY8@89|bpnUj{Y)pM$%>8xC9ky&j~A z;5}d+{2r+GUyhKf{UuQ2{Sder{30m6{~XjhylC3W#YXVOJP(2DF9sz?Zvi#$cYzzh zzjXQk0-{2LD~{N4zXH6N=huL@fxixF9sC$ndl%ni*YmaD)jS^sVOj7d@D}jvpvHaG zQOoa1Q2cF!SAy>ZC10O*_!y}9TzIpU^I`A;o)3VMqod$6z*m8&#Nh3qSq|-21ej8_zw5}tDx%tGpPQz9 zjpH703;0P;^!o=;bh-2ume0eW=u-vN-s?c|>pkGL;3vTI!JmO4c=qk=P2dKw54;O} zCHQtw^SI!+rSA?<&*z6OTinGrG!z7SOTGAR1K**$**6h9sTrPnT; zvGm*y4)Ht>J`enTFa$pfJ`?=5!=Hl}@%;3Xo!{l4`o9*GeyV_%fo}oDzxzPZ@d5Bc z@TZ{U>FlyyFV6z^@H_}g&KscUcPBUsz88EM_#II5*b>|Ibu;(^o-0bB#^$rId{s-_+NgD58kwjO09wpsD`l%lHX#S!dDkAtT z(z8gCne`-n{>(z~+u)y&S|p}pKA+|L0n$07M@avZ^mUT|h&KAnlOUa;k)HSIi;sBu zF4EgcqO<>;&5tj;2d#_ell}+kA4%UOJ&kl7NuOULJ(cwLq^FbKM*2OHK0hXXpY$UV zs?EqIU_Kw_dzkcV_R)O5hVP${{xj*_=8gTT0QZsp+P(WthqK^r_xnsxGJ*;+GS~(` zO48?5q$Scc=?_VllIBSFlWrqP7W8>G=~qZ!AU%cTKX2g2gQPc-<s^*N8Eb@?XJ z?Ie8`NykaQOVX!F`cLK;`pDrChl0N)y@&K^(tjguB^@IDK1rX?kp4X>BYlmuo%A7+ zJ})HgBE6RMLsCN8LAsjcKUeu54nG1ugLFP=ob(VWC55DKl154Qkj6;<^F@CAC20fc zMWj0E1nKjnzaxEv^j=aQ>EDpPLwYqypHG=@Y(t0Zz)8}ed#-|?BV9xK3-|8dfzp3F z-E$G%;T~QNzRvwV2~LpyHR)xf|4JGmEsz?dW2FB=x`m|AJ4yfD{IXyF;C{aZ{3FtS z_x!NKe+B*x>5oYVNM9o9b2sVR=9m4t)&0H*d@Jdbq)SNOB7KnbG1B`<`rJj@OS*z| z8A+diOFEbI>!k0I^!d02^Zg(B{tD?2NH>#ygY-Vql_Y&$LHcvjV|w5dleUmPL3#_R zpA?bwIYqkD{OWww`1wzyUnX5o`YP!r(v2klIjA3DIB;-NI51F&)3_0};(_^isd?*l zyGN&|ZVUIjmtnmn>y2cAGU4H=;gE9mC}|A#h2}FbFc(+r_IKfXZ_=z+qouGl zmo!6DB1+3)d@^ZuDlWv0W|F0aTKqiJZq?hZ(B~!TY}TknEtTuE&=)ZLl7?T((%GbP z-QLl|g=P-NQ8~0ZZRV!BSzXW!XB$~9q_jpcuvaal*+4mNMWwky1L58*y`mM;^}OlT z7BF?ns#A_<+Lc?c8ymT4Wb8IyZ!|46;;0#iCO53c3vo5f8eubTg-I)HWuYl=TA5cX z^GUUO>vdD3`zMAwtqiwXajkBOD?g0FMmtTDv=X+Gv{Wt-feEB$0&(lQiIM4v;qeha zlrY?rrD03)`X1=~^wjCEo(vb`q%uc=a-nD`sn5j?-i76)5;v6_ z)}m51PAjcBJ(RLqy%9GJJ9#X&*K9?tb~EhXa`nkDjZe1bvbs86NFt!nM^~M!G|#AM zsZiUL%@z??Q?Zq`qG~v^)QX#7k`9Go|JE&xx%fJ3w}$NN^-FPcy_m5+&DJA^b!Zcp z#o%RfvJf?rXr>x#h)JsNYLfC)4*0pDzqt_#lqDO?ww@u~=bzGLg`d)nu|t3_a+jo;AcDRq?Apeb2O$s^0Verm)_~T3IQpGO&$( zlw_LCVAzR>+NvUo<)vJ9G*QXH@&4u&;bH>Q>PeZ(2*et-mK7|OVpb877}3_E2qzKK z>Y9y`YFxI1sHj9eLP#3%9c_e#!Ik4`EPD5|daCiPI7`QFjIJHBp{1tb-Z$eo^=$;h z^?IC^)inA?1yLnUGZ?D3;>H2fg>7zGN`!*Jc7Vs$Q*1 z?}5#o9O_>^_3kDYV?WK-Qavux;E7aQbIiRP^4*S3E?kY+NV=Ut@Oa5xXyGNjTUebY zqSxBvGUPC&s+n1oPNRu`Muqy7zsG7!6oQplqYm6l6)sVq%$X&G)#{2urdzu~;Z?Em zFhUi}NGlggG>3SoFEz}LzG2VCaO*YK>=@X#Wy`j3bRi3;lUgmtx=Ptm_P5!wrm9J- zbt6j)b%cF3*f$lkz|bD1~{?Cgd+N~G zk?E1KTf&J$;nCs4hleMoZy5~3X<3E*Kii=3W;WYej2iK#K6Sg4wL=~-L#k>?ltOjW zej}OD62y{fr)6w_Qru`oX!H`haAJ(RoqcQ>xrPt-9Gbj^o!P7d8E{FJ*+7qWwQSVA z(GU>2wa5lwb;|O*UT-&}xHczF{kW~{^fso9>9abct&7%>{H+-_(Oim{28jOnd*4Q;f4OMJYDca>MBJCU#; z)-f>CS~bh&)f^P2nlq3@A722GYep3`x6FIjvhocLZ5v{@+AtdaICfC6zN{r>>VV@9 zJ7%ET4t!xZn69$sd}Pdwu6A9~rn6b>zEN29g>fy;sgK-{U=S-xyViV3D_a!oXpt4| z6)2`%PDaIwG8mC1+3d6=p(v29t3y9uU!aSsc1*rVvjr84bhX*71}X+CMLoGK5^1B; zu728S4rC*@%U=jL)2H;qO$Ho2_qtZmL!UI$7s^yEv?E6*#O!ERwwAPs*iWRRy5(-@Yvz;P^XcoYKC^; z2wPs~@x~*g)5YiMk?!IVoR^nkmZMkI6_lJybqpD?z&3A14K3V3)4>dDv6s~Mc%Kil zSL>!R^cx4yhFSH|66(dN@uCLXgvPle<&;}CRoZFPX2@wPDaml_Rl}9bJrjIzuAXwrprJnnKemr@D$K z`5bzvDn8J6cUuL+qc0fcv{|9plN)Qg5LNMD_zBNOwWPYVjz-=4Mx|YoN|mbJ8Oo~} z*4mu*W;k1iX}dO~p6_TQC~OZ5w89pKJ%;rdrQ!Ci+pvjNY0LWSR<=eX@;G4TAh(-B zN#~~U;ON-crtrwr;jQL-+otg7=)|4_o5InFX>}`+FLY(j{-T>deflxv85~0^nTTCj z%T`x-Kb5bd6RQexkdD^{V`$VA5tHL)9KVz&+$x8`U@S@7C&O3^s<7GEx2<-%x$9*U z2aLMn2-DvT9!K+HI{u8ZDeJt5@ySvgm(lmhDMLl;XkL=vV982c=U-?I8b6jt{kzGk(5|JOu?S$HTQMFMBFl)c{}x+Id2w?&)FSp zbs)m8I-8tyjzsoaqsgppeIl!SBFlN+#QT}dCeTm~Xq+qoqdGNC++@w3enaGR)q*z9 z-WFJE*t8txT`}7%v};p#we^24acHnZFf`j_4IoL9)t#cDhQwGcH!iUB&U+)xRm@oe|#qyLt(~1Xh+< zY-CUgN_zjYig19NU>hy&a)&TnldROLZrI3slIqbYh6mtJ~$PxGWbl=&UrC^9%@Ts>)) z4xEY`OvK%(K&NHJolijuGMZsOudz2TttcfC(CreXa5i;s(!pfAVSM;$Vddm63yT9q zgv6@8xifMeJD-l(UKy(s{Z2VEgEilpE!DRRfg)>Wb{Z=Z z)R*hQzfOg`cUQ{h*y~2i-l^D_2AoozE#*q$_%W+h^T$G;%BoxjGKJ3mJSDF@{^t_n zZ8tdF3W46@JYCZVHDz67Ps-SJb#;oSvn3Q=EiAFFjd5F~&onp3S%X1y`-MZ&n14kk zGOz7;Uk~bDnQhSM6wF!KqESV@R0>qGTw~iCY%Vf_Y3r#}gTb`BL9@MYfDBQ}W!tQA zyrOrFT>9Ip1Y<0mL))~|W;DwMiW)N4#Q0)I837~Ffn7J}_V^^r%-!nf^e>S{;?=1& zPDFP(8;{Efpg@|jdhoVz@Ur*hgJGfcss+g4{|I}qA`u)iw@T$9w1oFf_sGiy9LKpX z?YxdNVih`YP3p1F;Xl1Ni_bUqG3L`gIvf4113U(ZYG{MG_)By}|hP@F&cMH(T zY{Uavzs7^rk>6!!fqYFDT2)2kwNl638sSK4F1*#X<%0MrVY5cPHHOy(onlfx(q}We zsFD>nZ@6KWaT61(z7*}XDa@}7!5~8_lgNcyQ>_`meN+$sYXMM#GS`=ehvJC^XTbH2Ytd~-o{T1 zR9Pj`Yjj{#Q@(>+-D$7ch#>H1yLEwg)w{T)z#TyRqeNG7Q>xY1Xnuuc6??E_z1>Lh!hwYEf3se z1FVMZ`E%>wmVwejvv2ay^nkrL!kpZT+8qjYBRH_->VYlSgj=r~+J4QITX;jk0c?Uq zK|NjNt{T|((s1ibOu4O;8zbOgVA}ckXc;uNm0dDXf9w0~i?L=%LMODBOW7+=P^!CL&I!7b9Zvya|bW%ow%J zYRodJ)}!cjL2>)zcov@H-)6!R9pfgo%(FmNQN|*T$%s2s!&xIv4^fK&}#V zVcdz3v-xX9$Qj2}ez#?w3eB*bkqVa98arP)S6VDs2dmjo# z*tsO6Oq_>0-I;4Se!F#}Rw{8Vis*;mt47g{(1;bLawFoBkytuA>)h&;$mHR3y^41g z7$$&7PNxO-RI`GNpF^?-2{dX9;%a-|-d`e>nY;+fTF^a^DSRr^bYV={2w$_cNk3&N zLpfRLsg8|up7Lsj8%?I5F+d9%RBd>o>`HtpiPK=pYOD}nV_6}h@N0oDTn3DBMh2#I zG~AqHFoS(#G==7aYaI0S3yp^?G{eUpV==n6V7(T$sm%#AQLIH*gq`io@}Jfl=mG*c zOsfz%kF-0~Qw025M9&49Vw_5=tP6Y=akq-OV@rV2tO7%DF&zmk6j~8?cPt~+L@I!F zQ-j&vTC&DX>#5{K3h5w{;_j+Z)MD(8cwTgMw1(DAytRp8Y(1J+2&=dbuk7M84{k&U z$>?ZR5gXTyg73r+xXs9pn_IECXEw2Tt7dn)fGo?}P(&X0uI$dR z*z`A_aSh87G(zD*^fZ_}HqRErsFVD-(cqP}F?v2z8lOhG$J#8-HIfrh)2eW@8uJoG z<&ujNMXcnY>&5^=#A2hj^Mew$+F2)(ux=lG40cW6u@{ zv&LxGYGKWptl6gHfQ|jj;_4G&MLr8^6ZhAt{r^EFHy&%}6B)SMS#VM~)})Z`w%XU~ z9@IjYPVT&Qdw@3r@wjPsMb?eZQax9~Dh??a|EACZYQ)6;VV#x>MUdzx7yPFsF9jXr zmpGPSs}|I{4+1n|t?hOp(|Jw%R5dx#2?DgrzLE#-X>8%KLlb*P4u>NXqx(m~{lf|d z9389B?R8v7WTO{ai?QOz&BoVJI$cF%dU|a{ z#%3ECSX4JwtC43^Jxq%VLV`xGNUOW8THRYEm$q`{E6zKgzKs*?9;EC){4}PU;V6}L z6BZ%`ooQi1zkI%$)JU8aSu{UP5jGzmX=n(9JQm9wWCP@&lZOmyFETo#GczP77|GxJ z$ie)Dxi=`5aA#*LLBT%h%~o;()>-4tS{M>GH*#~s=*MQ(N>?4@bvHucj1%GrO@W!@ zgpq@+ZY?UiJ9n%_kI}*t?+DWIrXT}J*bs?xERrC zv?r}?D5B2#{mt&?qFIHF7<+^970BLQ%#y-o7y04m&?#UjDh*&P6ceoC#K4z@Ji2{B z-I=I;w~V?(sf;fVgR`3`tB%ebk!TM~xzlO)1XhyG&0-pLqlL7ZiZ=(BP56Af3wcG` ztY+we;7HQK91{aOk%>3Cvl|-IAH+05j(X)tM{C23F(a9pnPku}c&j+ZWZw~U7|o-h zi6rsHwV5ujtR>>NtzwL#wT9fNhNrz7uV2Gvt%bqXY zvAlQxT!B*@1GAgvYj(d%ohQYoRrmvGJ7JAI1*K5&iBH?CF57G;zL5Y&`zjA{%-?jP z9P?M5K*#)5if>KwuV_U46W$}{*5HseHy|ELu+bWHoxw8MGfbFrE0@P=*@YP_@6HBS zy5@B-md6OIuU+S6$k=?vW3aVr3o($E23qy}8FGGawn{zMOO`TD>x;@~?S^54AtOx0 zSsM(gLt9?j*bBwOLjy` zcmsMLBH>ll2+CM@1ZBPz+V?(&vh%vF8&`I2;}XL>I(<*bgYkZMq9}1A;pFQuM*cd{ z*4{P}OF8=p#;vr}Sr3nfBvIqw%#d(Pkk+ zOc7uCZrCx)d8r-W)F`f+Tv>Tr@H7Rxt!T5xCUU;ZV~Z@B2usE+{WHfO)lPImEOScp zZV^rBoH`Jp7-7kgPfOVy#58*zWXnEY&9PqFq;7(g;wMM)Lca_VBuF(|AI#VbA8~)Rk^GmRIIRwpZ&Gyp68?<7Y3G6iF z?ri9X+MT#g>Kd1&iRQ#S|3jT98)I&<-NM}%S|G)|nHNAAGr8%49`Cq{xhjZfPc zedwxo#rkhC57!055@;C~ZohOlI-U4VT@lf06JHEhLwRxbH~u{U@2Nw9aqK6^GsY)m zR7hSBX45)?$W;LzcxS*!4rk3y*yi|v&^6p3_Ec&LuI2gg$5li7{nFWG%o}qL#Bsw0hUT|19Z_SIa9@+*uI+CY z$`?)6UN<*tSw3C`uXUek71_SZA+|Fd*L=~Xc0d<-{JSRnhn?sGMG@Ovvv(Mvj`0C# zCGjUK@|f_Z>13acVH{hJ02~4mQmqwf+}xvTEH`bGU4a!l`7WbA?r73Hd}ORF<>=U_fu#Lg{;KUaaYXyNvKFy+4xOd)T%Du z(?%B8!{aM_Ow&?4=6GQu%5-Pg&32|p?CLSuH~#SJLRY;SL-9KiK^|~+8R;{m;~z%J zZ)uRP&MmbW#|91|GG>gSY;O+SDS^vhJp2T(x;=`0l1n6=A7)}LPyP8mp*y4V{9{Ns z-f2hv0lVK2=mVoDXB@jSQ&=#2y~WpM>V?k!%WWA#So4y-^6Y(y#_ZQN29OrLWUvs* z>MmAJTaa3Iv-NSUR%zR<+s<2LIvrT)Wx?NEsTz}A+FZkG&;{LcNOfV`wSSEiwY@7USGq3%X? z0C&dLV7M!sa)s&5Ojq^}fg7`{v?L}5uC*D=kyqr0!SRk6Rf;PO) z50F*@VEt;2ld9YzJ_a^+0kS$ms}mal%h|Xdm2FLOOn{aC%w9_*kAdy7Nqrcsv%(FD zFfyDI1|44uI*-mVyfPM6=N{w(%MyjjXk`6mo}{jpy@Vzr*4um%-U?@X?kkF+iGeOE z4Z&qfxl>;tu`fi&uGQf(LDWCvRqWCZrx+x=R%7{J^y^;{THch6ys`@cfpEdHK2kQ< h??GNJzW|Y^Ghj8Db5!q}jy#*CuYZ?ql?##J{{iI_iT(fp literal 0 HcmV?d00001 diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..4288fee --- /dev/null +++ b/po/nl.po @@ -0,0 +1,1288 @@ +# 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 new file mode 100644 index 0000000..9eb3a62 --- /dev/null +++ b/po/tinc.pot @@ -0,0 +1,1232 @@ +# 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 new file mode 100644 index 0000000..32aee66 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,31 @@ +## 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 = 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 + +INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl + +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)\" + +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\" $^ diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..8e07167 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,402 @@ +# 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.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 +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$(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)\" + +subdir = src +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +sbin_PROGRAMS = tincd$(EXEEXT) +PROGRAMS = $(sbin_PROGRAMS) + +am_tincd_OBJECTS = conf.$(OBJEXT) connection.$(OBJEXT) device.$(OBJEXT) \ + edge.$(OBJEXT) event.$(OBJEXT) graph.$(OBJEXT) meta.$(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) +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@ +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 +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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 +SOURCES = $(tincd_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 src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && \ + CONFIG_HEADERS= CONFIG_LINKS= \ + CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status +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 + +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 + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) + @rm -f tincd$(EXEEXT) + $(LINK) $(tincd_LDFLAGS) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +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@ + +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) + $(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; \ + 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 + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="${top_distdir}" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(sbindir) + +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-sbinPROGRAMS 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-sbinPROGRAMS + +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 uninstall-sbinPROGRAMS + +.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 + + +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/conf.c b/src/conf.c new file mode 100644 index 0000000..bc29e07 --- /dev/null +++ b/src/conf.c @@ -0,0 +1,623 @@ +/* + conf.c -- configuration code + Copyright (C) 1998 Robert van der Meulen + 1998-2002 Ivo Timmermans + 2000-2002 Guus Sliepen + 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 + 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: conf.c,v 1.9.4.55 2002/04/09 11:42:48 guus Exp $ +*/ + +#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" + +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 config_compare(config_t *a, config_t *b) +{ + int result; + + result = strcasecmp(a->variable, b->variable); + + if(result) + return result; + + result = a->line - b->line; + + if(result) + return result; + else + return strcmp(a->file, b->file); +} + +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 exit_configuration(avl_tree_t **config_tree) +{ +cp + avl_delete_tree(*config_tree); + *config_tree = NULL; +cp +} + +config_t *new_config(void) +{ + config_t *cfg; +cp + cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg)); + + return cfg; +} + +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 config_add(avl_tree_t *config_tree, config_t *cfg) +{ +cp + avl_insert(config_tree, cfg); +cp +} + +config_t *lookup_config(avl_tree_t *config_tree, char *variable) +{ + config_t cfg, *found; +cp + cfg.variable = variable; + cfg.file = ""; + cfg.line = 0; + + found = avl_search_closest_greater(config_tree, &cfg); + + if(!found) + return NULL; + + 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); + + if(node) + { + if(node->next) + { + found = (config_t *)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; + + if(!strcasecmp(cfg->value, "yes")) + { + *result = 1; + return 1; + } + else if(!strcasecmp(cfg->value, "no")) + { + *result = 0; + return 1; + } + + syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + + return 0; +} + +int get_config_int(config_t *cfg, int *result) +{ +cp + if(!cfg) + return 0; + + if(sscanf(cfg->value, "%d", result) == 1) + return 1; + + syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + return 0; +} + +int get_config_string(config_t *cfg, char **result) +{ +cp + if(!cfg) + return 0; + + *result = xstrdup(cfg->value); + return 1; +} + +int get_config_address(config_t *cfg, struct addrinfo **result) +{ + struct addrinfo *ai; +cp + if(!cfg) + return 0; + + ai = str2addrinfo(cfg->value, NULL, 0); + + if(ai) + { + *result = ai; + return 1; + } + + syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + return 0; +} + +int get_config_port(config_t *cfg, port_t *result) +{ +cp + if(!cfg) + return 0; + + if(sscanf(cfg->value, "%hu", result) == 1) + { + *result = htons(*result); + return 1; + } + + syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + return 0; +} + +int get_config_subnet(config_t *cfg, subnet_t **result) +{ + subnet_t *subnet; +cp + if(!cfg) + return 0; + + subnet = str2net(cfg->value); + + if(!subnet) + { + syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + return 0; + } + + /* 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; +} + +/* + 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. +*/ +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. */ + + 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; + } + + 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 */ + } + } + + if((buf != NULL) && (buflen != NULL)) + { + *buflen = size; + *buf = line; + } + return line; +} + +/* + 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; + +cp + if((fp = fopen (fname, "r")) == NULL) + { + syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno)); + return -3; + } + + bufsize = 100; + buffer = xmalloc(bufsize); + + for(;;) + { + if((line = readline(fp, &buffer, &bufsize)) == NULL) + { + err = -1; + break; + } + + if(feof(fp)) + { + err = 0; + break; + } + + lineno++; + + 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; +} + +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; +} + +int isadir(const char* f) +{ + struct stat s; + + if(stat(f, &s) < 0) + return 0; + else + return S_ISDIR(s.st_mode); +} + +int is_safe_path(const char *file) +{ + char *p; + const char *f; + char x; + struct stat s; + char l[MAXBUFSIZE]; + + if(*file != '/') + { + syslog(LOG_ERR, _("`%s' is not an absolute path"), file); + return 0; + } + + p = strrchr(file, '/'); + + if(p == file) /* It's in the root */ + p++; + + x = *p; + *p = '\0'; + + f = file; +check1: + if(lstat(f, &s) < 0) + { + syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); + return 0; + } + + 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; + } + + if(strlen(fn) == 0) + /* User just pressed enter. */ + fn = xstrdup(filename); + } + + 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; +} diff --git a/src/conf.h b/src/conf.h new file mode 100644 index 0000000..bf399dd --- /dev/null +++ b/src/conf.h @@ -0,0 +1,70 @@ +/* + conf.h -- header for conf.c + Copyright (C) 1998-2002 Ivo Timmermans + 2000-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: conf.h,v 1.6.4.32 2002/02/18 16:25:16 guus Exp $ +*/ + +#ifndef __TINC_CONF_H__ +#define __TINC_CONF_H__ + +#include +#include +#include + +#include +#include "net.h" +#include "subnet.h" + +typedef struct config_t { + char *variable; + char *value; + char *file; + int line; +} config_t; + +extern avl_tree_t *config_tree; + +extern int debug_lvl; +extern int pingtimeout; +extern int maxtimeout; +extern int bypass_security; +extern char *confbase; +extern char *netname; + +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 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 *); + +#endif /* __TINC_CONF_H__ */ diff --git a/src/connection.c b/src/connection.c new file mode 100644 index 0000000..391982a --- /dev/null +++ b/src/connection.c @@ -0,0 +1,137 @@ +/* + connection.c -- connection list management + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: connection.c,v 1.1.2.29 2002/03/22 13:31:18 guus Exp $ +*/ + +#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 */ + +int connection_compare(connection_t *a, connection_t *b) +{ + return a - b; +} + +void init_connections(void) +{ +cp + connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL); +cp +} + +void exit_connections(void) +{ +cp + avl_delete_tree(connection_tree); +cp +} + +connection_t *new_connection(void) +{ + connection_t *c; +cp + c = (connection_t *)xmalloc_and_zero(sizeof(connection_t)); + + if(!c) + return NULL; + + gettimeofday(&c->start, NULL); +cp + 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 connection_add(connection_t *c) +{ +cp + avl_insert(connection_tree, c); +cp +} + +void connection_del(connection_t *c) +{ +cp + avl_delete(connection_tree, c); +cp +} + +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 +} + +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; +} diff --git a/src/connection.h b/src/connection.h new file mode 100644 index 0000000..0cdcc09 --- /dev/null +++ b/src/connection.h @@ -0,0 +1,121 @@ +/* + connection.h -- header for connection.c + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: connection.h,v 1.1.2.26 2002/02/20 19:25:09 guus Exp $ +*/ + +#ifndef __TINC_CONNECTION_H__ +#define __TINC_CONNECTION_H__ + +#include + +#include +#include + +#ifdef HAVE_OPENSSL_EVP_H +# include +#else +# include +#endif + +#ifdef HAVE_OPENSSL_RSA_H +# include +#else +# include +#endif + +#include "net.h" +#include "conf.h" + +#include "node.h" +#include "edge.h" + +#define OPTION_INDIRECT 0x0001 +#define OPTION_TCPONLY 0x0002 + +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; +} connection_status_t; + +typedef struct connection_t { + 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 */ + + 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 */ + + 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 */ + + 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 */ + + time_t last_ping_time; /* last time we saw some activity from the other end */ + + avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ +} connection_t; + +extern avl_tree_t *connection_tree; + +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 void dump_connections(void); +extern int read_connection_config(connection_t *); + +#endif /* __TINC_CONNECTION_H__ */ diff --git a/src/device.c b/src/device.c new file mode 100644 index 0000000..e896f54 --- /dev/null +++ b/src/device.c @@ -0,0 +1,224 @@ +/* + 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 new file mode 100644 index 0000000..3d3aa76 --- /dev/null +++ b/src/device.h @@ -0,0 +1,36 @@ +/* + net.h -- generic header for device.c + 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.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $ +*/ + +#ifndef __TINC_DEVICE_H__ +#define __TINC_DEVICE_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); + +#endif /* __TINC_DEVICE_H__ */ diff --git a/src/edge.c b/src/edge.c new file mode 100644 index 0000000..c35af07 --- /dev/null +++ b/src/edge.c @@ -0,0 +1,211 @@ +/* + edge.c -- edge tree management + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: edge.c,v 1.1.2.10 2002/03/27 15:26:43 guus Exp $ +*/ + +#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 */ + +int edge_compare(edge_t *a, edge_t *b) +{ + int result; + + 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); +} + +/* Evil edge_compare() from a parallel universe ;) + +int edge_compare(edge_t *a, edge_t *b) +{ + int result; + + return (result = strcmp(a->from.node->name, b->from.node->name)) || (result = strcmp(a->to.node->name, b->to.node->name)), result; +} + +*/ + +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); +} + +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); +} + +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 +} + +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 +} + +/* 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; +} + +void free_edge(edge_t *e) +{ +cp + free(e); +cp +} + +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_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 +} + +edge_t *lookup_edge(node_t *from, node_t *to) +{ + edge_t v, *result; +cp + v.from.node = from; + v.to.node = to; + + result = avl_search(edge_tree, &v); + + if(result) + return result; +cp + v.from.node = to; + v.to.node = from; + + return avl_search(edge_tree, &v); +} + +void dump_edges(void) +{ + avl_node_t *node; + edge_t *e; + char *from_udp, *to_udp; +cp + syslog(LOG_DEBUG, _("Edges:")); + + 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); + } + + syslog(LOG_DEBUG, _("End of edges.")); +cp +} diff --git a/src/edge.h b/src/edge.h new file mode 100644 index 0000000..604082f --- /dev/null +++ b/src/edge.h @@ -0,0 +1,62 @@ +/* + edge.h -- header for edge.c + Copyright (C) 2001-2002 Guus Sliepen , + 2001-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: edge.h,v 1.1.2.7 2002/03/22 11:43:46 guus Exp $ +*/ + +#ifndef __TINC_EDGE_H__ +#define __TINC_EDGE_H__ + +#include + +#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; + + 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 */ +} 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 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 void dump_edges(void); + +#endif /* __TINC_EDGE_H__ */ diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..028483b --- /dev/null +++ b/src/event.c @@ -0,0 +1,110 @@ +/* + event.c -- event queue + Copyright (C) 2002 Guus Sliepen , + 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: event.c,v 1.1.4.2 2002/03/01 14:09:30 guus Exp $ +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "event.h" + +#include "system.h" + +avl_tree_t *event_tree; +extern time_t now; + +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; +} + +void init_events(void) +{ +cp + event_tree = avl_alloc_tree((avl_compare_t)event_compare, NULL); +cp +} + +void exit_events(void) +{ +cp + avl_delete_tree(event_tree); +cp +} + +event_t *new_event(void) +{ + event_t *event; +cp + event = (event_t *)xmalloc_and_zero(sizeof(*event)); +cp + return event; +} + +void free_event(event_t *event) +{ +cp + free(event); +cp +} + +void event_add(event_t *event) +{ +cp + event->id = ++id; + avl_insert(event_tree, event); +cp +} + +void event_del(event_t *event) +{ +cp + avl_delete(event_tree, event); +cp +} + +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; +} diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..7a35612 --- /dev/null +++ b/src/event.h @@ -0,0 +1,48 @@ +/* + event.h -- header for event.c + Copyright (C) 2002 Guus Sliepen , + 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: event.h,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $ +*/ + +#ifndef __TINC_EVENT_H__ +#define __TINC_EVENT_H__ + +#include +#include + +avl_tree_t *event_tree; + +typedef void (*event_handler_t)(void *); + +typedef struct { + 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 event_t *get_expired_event(void); + +#endif /* __TINC_EVENT_H__ */ diff --git a/src/freebsd/device.c b/src/freebsd/device.c new file mode 100644 index 0000000..2f5f32e --- /dev/null +++ b/src/freebsd/device.c @@ -0,0 +1,148 @@ +/* + 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/graph.c b/src/graph.c new file mode 100644 index 0000000..53152a5 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,290 @@ +/* + graph.c -- graph algorithms + Copyright (C) 2001-2002 Guus Sliepen , + 2001-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: graph.c,v 1.1.2.11 2002/03/24 16:28:27 guus Exp $ +*/ + +/* We need to generate two trees from the graph: + + 1. A minimum spanning tree for broadcasts, + 2. A single-source shortest path tree for unicasts. + + Actually, the first one alone would suffice but would make unicast packets + take longer routes than necessary. + + For the MST algorithm we can choose from Prim's or Kruskal's. I personally + favour Kruskal's, because we make an extra AVL tree of edges sorted on + weights (metric). That tree only has to be updated when an edge is added or + removed, and during the MST algorithm we just have go linearly through that + tree, adding safe edges until #edges = #nodes - 1. The implementation here + however is not so fast, because I tried to avoid having to make a forest and + merge trees. + + For the SSSP algorithm Dijkstra's seems to be a nice choice. Currently a + simple breadth-first search is presented here. + + The SSSP algorithm will also be used to determine whether nodes are directly, + indirectly or not reachable from the source. It will also set the correct + 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 "netutl.h" +#include "node.h" +#include "edge.h" +#include "connection.h" +#include "process.h" + +#include "system.h" + +/* 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; + + /* Clear MST status on connections */ + + for(node = connection_tree->head; node; node = node->next) + { + c = (connection_t *)node->data; + c->status.mst = 0; + } + + /* Do we have something to do at all? */ + + if(!edge_weight_tree->head) + return; + + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, "Running Kruskal's algorithm:"); + + /* Clear visited status on nodes */ + + for(node = node_tree->head; node; node = node->next) + { + n = (node_t *)node->data; + n->status.visited = 0; + nodes++; + } + + /* Starting point */ + + ((edge_t *)edge_weight_tree->head->data)->from.node->status.visited = 1; + + /* Add safe edges */ + + for(skipped = 0, node = edge_weight_tree->head; node; node = next) + { + next = node->next; + e = (edge_t *)node->data; + + if(e->from.node->status.visited == e->to.node->status.visited) + { + skipped = 1; + continue; + } + + e->from.node->status.visited = 1; + e->to.node->status.visited = 1; + if(e->connection) + e->connection->status.mst = 1; + + safe_edges++; + + 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(skipped) + { + next = edge_weight_tree->head; + continue; + } + } + + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(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; + + todo_tree = avl_alloc_tree(NULL, NULL); + + /* 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); + } + } + 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); + } + } + } +} + +void graph(void) +{ + mst_kruskal(); + sssp_bfs(); +} diff --git a/src/graph.h b/src/graph.h new file mode 100644 index 0000000..3c8c0d5 --- /dev/null +++ b/src/graph.h @@ -0,0 +1,25 @@ +/* + graph.h -- header for graph.c + Copyright (C) 2001-2002 Guus Sliepen , + 2001-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: graph.h,v 1.1.2.3 2002/02/10 21:57:54 guus Exp $ +*/ + +extern void graph(void); +extern void mst_kruskal(void); +extern void sssp_bfs(void); diff --git a/src/linux/device.c b/src/linux/device.c new file mode 100644 index 0000000..e896f54 --- /dev/null +++ b/src/linux/device.c @@ -0,0 +1,224 @@ +/* + 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/meta.c b/src/meta.c new file mode 100644 index 0000000..b51c64d --- /dev/null +++ b/src/meta.c @@ -0,0 +1,210 @@ +/* + meta.c -- handle the meta communication + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: meta.c,v 1.1.2.25 2002/03/01 14:09:31 guus Exp $ +*/ + +#include "config.h" +#include +#include + +#include +#include +#include +#include +/* This line must be below the rest for FreeBSD */ +#include +#include + +#include + +#include "net.h" +#include "connection.h" +#include "system.h" +#include "protocol.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); + + if(c->status.encryptout) + { + EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); + bufp = outbuf; + length = outlen; + } + else + bufp = buffer; + + 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; +} + +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 +} + +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; + } + + /* 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 = 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; +} diff --git a/src/meta.h b/src/meta.h new file mode 100644 index 0000000..d54573e --- /dev/null +++ b/src/meta.h @@ -0,0 +1,32 @@ +/* + meta.h -- header for meta.c + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: meta.h,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $ +*/ + +#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 *); + +#endif /* __TINC_META_H__ */ diff --git a/src/net.c b/src/net.c new file mode 100644 index 0000000..1df4e9e --- /dev/null +++ b/src/net.c @@ -0,0 +1,449 @@ +/* + net.c -- most of the network code + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-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: net.c,v 1.35.4.169 2002/04/01 21:28:05 guus Exp $ +*/ + +#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 + +#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 do_purge = 0; +int sighup = 0; +int sigalrm = 0; + +time_t now = 0; + +/* 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")); + + for(nnode = node_tree->head; nnode; nnode = nnext) + { + nnext = nnode->next; + n = (node_t *)nnode->data; + + if(!n->status.reachable) + { + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname); + + for(snode = n->subnet_tree->head; snode; snode = snext) + { + snext = snode->next; + s = (subnet_t *)snode->data; + + for(cnode = connection_tree->head; cnode; cnode = cnode->next) + { + c = (connection_t *)cnode->data; + if(c->status.active) + send_del_subnet(c, s); + } + + subnet_del(n, s); + } + + for(enode = n->edge_tree->head; enode; enode = enext) + { + enext = enode->next; + e = (edge_t *)enode->data; + + for(cnode = connection_tree->head; cnode; cnode = cnode->next) + { + c = (connection_t *)cnode->data; + if(c->status.active) + send_del_edge(c, e); + } + + edge_del(e); + } + + node_del(n); + } + } +cp +} + +/* + 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); + + for(node = connection_tree->head; node; node = next) + { + next = node->next; + c = (connection_t *)node->data; + + if(c->status.remove) + connection_del(c); + else + FD_SET(c->socket, fs); + } + + if(!connection_tree->head) + purge(); + + for(i = 0; i < listen_sockets; i++) + { + FD_SET(listen_socket[i].tcp, fs); + FD_SET(listen_socket[i].udp, fs); + } + + FD_SET(device_fd, fs); +cp +} + +/* + Terminate a connection: + - Close the socket + - Remove associated edge and tell other connections about it if report = 1 + - 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; + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Closing connection with %s (%s)"), + c->name, c->hostname); + + c->status.remove = 1; + c->status.active = 0; + + if(c->node) + c->node->connection = NULL; + + if(c->socket) + close(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); + } + } + + edge_del(c->edge); + + /* Run MST and SSSP algorithms */ + + graph(); + } + + /* Check if this was our outgoing connection */ + + if(c->outgoing) + { + retry_outgoing(c->outgoing); + c->outgoing = NULL; + } +cp +} + +/* + Check if the other end is active. + If we have sent packets, but didn't receive any, + then possibly the other end is dead. We send a + PING request over the meta connection. If the other + 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 +} + +/* + 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); + } + + for(node = connection_tree->head; node; node = node->next) + { + c = (connection_t *)node->data; + + if(c->status.remove) + continue; + + 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; + } + } + } + + 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 +} + +/* + 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; + + srand(now); + + for(;;) + { + now = time(NULL); + + tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ + tv.tv_usec = 0; + + build_fdset(&fset); + + 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; + } + + continue; + } + + check_network_activity(&fset); + + if(do_purge) + { + purge(); + do_purge = 0; + } + + /* Let's check if everybody is still alive */ + + if(last_ping_check + pingtimeout < now) + { + check_dead_connections(); + last_ping_check = now; + + if(routing_mode== RMODE_SWITCH) + age_mac(); + + age_past_requests(); + + /* Should we regenerate our key? */ + + if(keyexpires < now) + { + if(debug_lvl >= DEBUG_STATUS) + syslog(LOG_INFO, _("Regenerating symmetric key")); + + RAND_pseudo_bytes(myself->key, myself->keylength); + send_key_changed(myself->connection, myself); + keyexpires = now + keylifetime; + } + } + + + while((event = get_expired_event())) + { + event->handler(event->data); + free(event); + } + + if(sigalrm) + { + syslog(LOG_INFO, _("Flushing event queue")); + + while(event_tree->head) + { + event = (event_t *)event_tree->head->data; + event->handler(event->data); + event_del(event); + } + sigalrm = 0; + } + + if(sighup) + { + sighup = 0; + close_network_connections(); + exit_configuration(&config_tree); + + syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds...")); + sleep(5); + + init_configuration(&config_tree); + + if(read_server_config()) + { + syslog(LOG_ERR, _("Unable to reread configuration file, exitting.")); + exit(1); + } + + if(setup_network_connections()) + return; + + continue; + } + } +cp +} diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..922c5cf --- /dev/null +++ b/src/net.h @@ -0,0 +1,153 @@ +/* + net.h -- header for net.c + Copyright (C) 1998-2002 Ivo Timmermans + 2000-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: net.h,v 1.9.4.49 2002/03/27 15:01:36 guus Exp $ +*/ + +#ifndef __TINC_NET_H__ +#define __TINC_NET_H__ + +#include +#include +#include +#include + +#include "config.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. */ +#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. */ +#endif + +#define MAXSOCKETS 128 /* Overkill... */ + +#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */ + +typedef struct mac_t +{ + unsigned char x[6]; +} mac_t; + +typedef struct ipv4_t +{ + unsigned char 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]; +} ipv6_t; + +typedef unsigned short port_t; + +typedef short length_t; + +typedef union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; +} sockaddr_t; + +#ifdef SA_LEN +#define SALEN(s) SA_LEN(&s) +#else +#define SALEN(s) (s.sa_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)) +#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]; +} 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; +} listen_socket_t; + +extern int maxtimeout; +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 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 char *myport; +extern time_t now; + +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 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 *); + +#endif /* __TINC_NET_H__ */ diff --git a/src/net_packet.c b/src/net_packet.c new file mode 100644 index 0000000..fd2ae06 --- /dev/null +++ b/src/net_packet.c @@ -0,0 +1,431 @@ +/* + net_packet.c -- Handles in- and outgoing VPN packets + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-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: net_packet.c,v 1.1.2.13 2002/03/27 15:01:37 guus Exp $ +*/ + +#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 + +#ifndef HAVE_RAND_PSEUDO_BYTES +#define RAND_pseudo_bytes RAND_bytes +#endif + +#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 keylifetime = 0; +int keyexpires = 0; + +#define MAX_SEQNO 1073741824 + +/* VPN packet I/O */ + +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 */ + + 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; + } + } + + /* Decrypt the packet */ + + 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); + + outpkt->len = outlen + outpad; + inpkt = outpkt; + } + + /* Check the sequence number */ + + inpkt->len -= sizeof(inpkt->seqno); + inpkt->seqno = ntohl(inpkt->seqno); + + 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; + + if(n->received_seqno > MAX_SEQNO) + keyexpires = 0; + + /* Decompress the packet */ + + if(myself->compression) + { + outpkt = pkt[nextpkt++]; + + 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; + } + + receive_packet(n, inpkt); +cp +} + +void receive_tcppacket(connection_t *c, char *buffer, int len) +{ + vpn_packet_t outpkt; +cp + outpkt.len = len; + memcpy(outpkt.data, buffer, len); + + receive_packet(c->node, &outpkt); +cp +} + +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); + + route_incoming(n, packet); +cp +} + +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 */ + + 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); + + /* Since packet is on the stack of handle_tap_input(), + we have to make a copy of it first. */ + + copy = xmalloc(sizeof(vpn_packet_t)); + memcpy(copy, inpkt, sizeof(vpn_packet_t)); + + 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 +} + +/* + 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); + + if(n == myself) + { + if(debug_lvl >= DEBUG_TRAFFIC) + { + syslog(LOG_NOTICE, _("Packet is looping back to us!")); + } + + return; + } + + if(!n->status.reachable) + { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("Node %s (%s) is not reachable"), + n->name, n->hostname); + return; + } + + via = (n->via == myself)?n->nexthop:n->via; + + 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((myself->options | via->options) & OPTION_TCPONLY) + { + if(send_tcppacket(via->connection, packet)) + terminate_connection(via->connection, 1); + } + 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); + + 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 +} + +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); + + 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 +} + +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; + } + + if((pkt.len = recvfrom(sock, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 0) + { + syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); + return; + } + + sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ + + n = lookup_node_udp(&from); + + if(!n) + { + hostname = sockaddr2hostname(&from); + syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname); + free(hostname); + return; + } + + if(n->connection) + n->connection->last_ping_time = now; + + receive_udppacket(n, &pkt); +cp +} + diff --git a/src/net_setup.c b/src/net_setup.c new file mode 100644 index 0000000..b5dc727 --- /dev/null +++ b/src/net_setup.c @@ -0,0 +1,564 @@ +/* + net_setup.c -- Setup. + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-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: net_setup.c,v 1.1.2.14 2002/04/01 21:28:39 guus Exp $ +*/ + +#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 +#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" + +char *myport; + +int read_rsa_public_key(connection_t *c) +{ + FILE *fp; + char *fname; + char *key; +cp + if(!c->rsa_key) + c->rsa_key = RSA_new(); + + /* First, check for simple PublicKey statement */ + + 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; + } + + /* Else, check for PublicKeyFile statement and read it */ + + 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; + } + } + + /* Else, check if a harnessed public key is in the config file */ + + 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); + } + + free(fname); + + if(c->rsa_key) + return 0; + else + { + syslog(LOG_ERR, _("No public key for %s specified!"), c->name); + return -1; + } +} + +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; + } + + if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) + asprintf(&fname, "%s/rsa_key.priv", confbase); + + 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; + } + + free(fname); + return -1; +} + +/* + 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); + + asprintf(&myself->hostname, _("MYSELF")); + asprintf(&myself->connection->hostname, _("MYSELF")); + + myself->connection->options = 0; + myself->connection->protocol_version = PROT_CURRENT; + + if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */ + { + syslog(LOG_ERR, _("Name for tinc daemon required!")); + return -1; + } + + 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); + } + + listen_socket[listen_sockets].sa.sa = *aip->ai_addr; + listen_sockets++; + } + + freeaddrinfo(ai); + + if(listen_sockets) + syslog(LOG_NOTICE, _("Ready")); + else + { + syslog(LOG_ERR, _("Unable to create any listening socket!")); + return -1; + } +cp + return 0; +} + +/* + setup all initial network connections +*/ +int setup_network_connections(void) +{ +cp + now = time(NULL); + + init_connections(); + init_subnets(); + init_nodes(); + init_edges(); + init_events(); + init_requests(); + + if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) + { + if(pingtimeout < 1) + { + pingtimeout = 86400; + } + } + else + pingtimeout = 60; + + if(setup_device() < 0) + return -1; + + /* Run tinc-up script to further initialize the tap interface */ + execute_script("tinc-up"); + + if(setup_myself() < 0) + return -1; + + try_outgoing_connections(); +cp + return 0; +} + +/* + 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); + } + + if(myself && myself->connection) + terminate_connection(myself->connection, 0); + + for(i = 0; i < listen_sockets; i++) + { + close(listen_socket[i].tcp); + close(listen_socket[i].udp); + } + + exit_requests(); + exit_events(); + exit_edges(); + exit_subnets(); + exit_nodes(); + exit_connections(); + + execute_script("tinc-down"); + + close_device(); +cp + return; +} diff --git a/src/net_socket.c b/src/net_socket.c new file mode 100644 index 0000000..73e5fb6 --- /dev/null +++ b/src/net_socket.c @@ -0,0 +1,484 @@ +/* + net_socket.c -- Handle various kinds of sockets. + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-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: net_socket.c,v 1.1.2.11 2002/03/27 14:02:36 guus Exp $ +*/ + +#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; +int maxtimeout = 900; +int seconds_till_retry = 5; + +listen_socket_t listen_socket[MAXSOCKETS]; +int listen_sockets = 0; + +/* 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; +#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)); +#endif + +#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY) + option = IPTOS_LOWDELAY; + setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option)); +#endif + + if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface)) + { +#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; + } +#else + syslog(LOG_WARNING, _("BindToDevice not supported on this platform")); +#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(listen(nfd, 3)) + { + close(nfd); + syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); + return -1; + } +cp + 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; +#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))) + { + close(nfd); + syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno)); + 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; +} + +void retry_outgoing(outgoing_t *outgoing) +{ + event_t *event; +cp + outgoing->timeout += 5; + if(outgoing->timeout > maxtimeout) + outgoing->timeout = maxtimeout; + + event = new_event(); + event->handler = (event_handler_t)setup_outgoing_connection; + event->time = now + outgoing->timeout; + event->data = outgoing; + event_add(event); + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout); +cp +} + +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); + + 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(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(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); +cp + return 0; +} + + +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; + + send_id(c); +cp +} + +void do_outgoing_connection(connection_t *c) +{ + char *address, *port; + int option, result, flags; +cp +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(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) + asprintf(&port, "655"); + + c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); + free(address); + free(port); + + c->outgoing->aip = c->outgoing->ai; + c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); + } + + if(!c->outgoing->aip) + { + freeaddrinfo(c->outgoing->ai); + c->outgoing->ai = NULL; + goto begin; + } + + memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); + c->outgoing->aip = c->outgoing->aip->ai_next; + + if(c->hostname) + free(c->hostname); + + c->hostname = sockaddr2hostname(&c->address); + + 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; + } + + close(c->socket); + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); + + goto begin; + } + + finish_connecting(c); + return; +cp +} + +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; + } + + 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); + 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; + + 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; + } + + sockaddrunmap(&sa); + + c = new_connection(); + 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; + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection from %s"), c->hostname); + + connection_add(c); + + c->allow_request = ID; + send_id(c); +cp + return 0; +} + +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); + + if(check_id(name)) + { + syslog(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; + setup_outgoing_connection(outgoing); + } +} diff --git a/src/netutl.c b/src/netutl.c new file mode 100644 index 0000000..20d3809 --- /dev/null +++ b/src/netutl.c @@ -0,0 +1,246 @@ +/* + netutl.c -- some supporting network utility code + Copyright (C) 1998-2002 Ivo Timmermans + 2000-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: netutl.c,v 1.12.4.34 2002/04/05 09:11:38 guus Exp $ +*/ + +#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; + +/* + 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)); + + 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. */ +#endif + + *addrstr = xstrdup(address); + *portstr = xstrdup(port); +cp +} + +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)); + } + + asprintf(&str, _("%s port %s"), address, port); +cp + return str; +} + +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 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; + } +} + +/* 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; + + 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 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]; + + if(m) + { + a[i] = b[i] & (0x100 - (1 << 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; + + return 0; +} diff --git a/src/netutl.h b/src/netutl.h new file mode 100644 index 0000000..654d7ad --- /dev/null +++ b/src/netutl.h @@ -0,0 +1,46 @@ +/* + netutl.h -- header file for netutl.c + Copyright (C) 1998-2002 Ivo Timmermans + 2000-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: netutl.h,v 1.2.4.11 2002/03/17 15:59:29 guus Exp $ +*/ + +#ifndef __TINC_NETUTL_H__ +#define __TINC_NETUTL_H__ + +#include +#include +#include + +#include "net.h" + +extern int 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); + +#endif /* __TINC_NETUTL_H__ */ diff --git a/src/node.c b/src/node.c new file mode 100644 index 0000000..e4581cc --- /dev/null +++ b/src/node.c @@ -0,0 +1,173 @@ +/* + node.c -- node tree management + Copyright (C) 2001-2002 Guus Sliepen , + 2001-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: node.c,v 1.1.2.11 2002/03/22 13:31:18 guus Exp $ +*/ + +#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 */ + +node_t *myself; + +int node_compare(node_t *a, 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; +} + +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 exit_nodes(void) +{ +cp + avl_delete_tree(node_tree); + avl_delete_tree(node_udp_tree); +cp +} + +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; +} + +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 node_add(node_t *n) +{ +cp + avl_insert(node_tree, n); + avl_insert(node_udp_tree, n); +cp +} + +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); + } + + 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 +} + +node_t *lookup_node(char *name) +{ + node_t n; +cp + 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; + + return avl_search(node_udp_tree, &n); +} + +void dump_nodes(void) +{ + avl_node_t *node; + node_t *n; +cp + syslog(LOG_DEBUG, _("Nodes:")); + + 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 +} diff --git a/src/node.h b/src/node.h new file mode 100644 index 0000000..98147d3 --- /dev/null +++ b/src/node.h @@ -0,0 +1,88 @@ +/* + node.h -- header for node.c + Copyright (C) 2001-2002 Guus Sliepen , + 2001-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: node.h,v 1.1.2.13 2002/03/19 22:48:25 guus Exp $ +*/ + +#ifndef __TINC_NODE_H__ +#define __TINC_NODE_H__ + +#include + +#include "subnet.h" +#include "connection.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; +} node_status_t; + +typedef struct node_t { + char *name; /* name of this node */ + long int 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 */ + + struct node_status_t status; + + const EVP_CIPHER *cipher; /* Cipher type for UDP packets */ + char *key; /* Cipher key and iv */ + int keylength; /* Cipher key and iv length*/ + + const EVP_MD *digest; /* Digest type for MAC */ + int maclength; /* Length of MAC */ + + int compression; /* Compressionlevel, 0 = no compression */ + + list_t *queue; /* Queue for packets awaiting to be encrypted */ + + 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 */ + + 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) */ + + unsigned int sent_seqno; /* Sequence number last sent to this node */ + unsigned int received_seqno; /* Sequence number last received from this node */ +} node_t; + +extern struct node_t *myself; +extern avl_tree_t *node_tree; +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 void dump_nodes(void); + +#endif /* __TINC_NODE_H__ */ diff --git a/src/openbsd/device.c b/src/openbsd/device.c new file mode 100644 index 0000000..3d7099f --- /dev/null +++ b/src/openbsd/device.c @@ -0,0 +1,195 @@ +/* + 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/process.c b/src/process.c new file mode 100644 index 0000000..bdd81e3 --- /dev/null +++ b/src/process.c @@ -0,0 +1,507 @@ +/* + process.c -- process management functions + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: process.c,v 1.1.2.39 2002/03/26 12:00:38 guus Exp $ +*/ + +#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" + +/* If zero, don't detach from the terminal. */ +int do_detach = 1; + +extern char *identname; +extern char *pidfilename; +extern char **g_argv; + +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); +} + +/* 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; +} +#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; + } + + 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); + } +cp + return 0; +} + +/* + Detach from current terminal, write pidfile, kill parent +*/ +int detach(void) +{ +cp + setup_signals(); + + /* First check if we can open a fresh new pidfile */ + + if(write_pidfile()) + return -1; + + /* If we succeeded in doing that, detach */ + + closelog(); + + if(do_detach) + { + if(daemon(0, 0) < 0) + { + fprintf(stderr, _("Couldn't detach from terminal: %s"), strerror(errno)); + return -1; + } + + /* 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(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"); +#endif + + if(netname) + { + asprintf(&s, "NETNAME=%s", netname); + putenv(s); /* Don't free s! see man 3 putenv */ + } + + if(device) + { + asprintf(&s, "DEVICE=%s", device); + putenv(s); /* Don't free s! see man 3 putenv */ + } + + if(interface) + { + asprintf(&s, "INTERFACE=%s", interface); + putenv(s); /* Don't free s! see man 3 putenv */ + } + + chdir("/"); + + /* Close all file descriptors */ + closelog(); /* <- this means we cannot use syslog() here anymore! */ + fcloseall(); + + 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); +} + +/* + 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); + + /* First check if there is a script */ + + if(stat(scriptname, &s)) + return 0; + + if((pid = fork()) < 0) + { + syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno)); + return -1; + } + + if(pid) + { + if(debug_lvl >= DEBUG_STATUS) + syslog(LOG_INFO, _("Executing script %s"), name); + + free(scriptname); + + 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 */ + + _execute_script(scriptname); +} + + +/* + Signal handlers. +*/ + +RETSIGTYPE +sigterm_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got TERM signal")); + + cleanup_and_exit(0); +} + +RETSIGTYPE +sigquit_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got QUIT signal")); + cleanup_and_exit(0); +} + +RETSIGTYPE +fatal_signal_square(int a) +{ + syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, strsignal(a)); + cp_trace(); + exit(1); +} + +RETSIGTYPE +fatal_signal_handler(int a) +{ + struct sigaction act; + syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a)); + cp_trace(); + + if(do_detach) + { + syslog(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); + + close_network_connections(); + sleep(5); + remove_pid(pidfilename); + execvp(g_argv[0], g_argv); + } + else + { + syslog(LOG_NOTICE, _("Not restarting.")); + exit(1); + } +} + +RETSIGTYPE +sighup_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got HUP signal")); + sighup = 1; +} + +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; + } +} + +RETSIGTYPE +sigalrm_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got ALRM signal")); + sigalrm = 1; +} + +RETSIGTYPE +sigusr1_handler(int a) +{ + dump_connections(); +} + +RETSIGTYPE +sigusr2_handler(int a) +{ + dump_device_stats(); + dump_nodes(); + dump_edges(); + dump_subnets(); +} + +RETSIGTYPE +sigwinch_handler(int a) +{ + extern int do_purge; + do_purge = 1; +} + +RETSIGTYPE +unexpected_signal_handler(int a) +{ + syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); + cp_trace(); +} + +RETSIGTYPE +ignore_signal_handler(int a) +{ + if(debug_lvl >= DEBUG_SCARY_THINGS) + { + syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a)); + cp_trace(); + } +} + +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 } +}; + +void +setup_signals(void) +{ + int i; + struct sigaction act; + + 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); + } + + /* 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)); + } +} diff --git a/src/process.h b/src/process.h new file mode 100644 index 0000000..1289d2d --- /dev/null +++ b/src/process.h @@ -0,0 +1,36 @@ +/* + process.h -- header file for process.c + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: process.h,v 1.1.2.10 2002/02/10 21:57:54 guus Exp $ +*/ + +#ifndef __TINC_PROCESS_H__ +#define __TINC_PROCESS_H__ + +#include "config.h" + +extern int do_detach; + +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); + +#endif /* __TINC_PROCESS_H__ */ diff --git a/src/protocol.c b/src/protocol.c new file mode 100644 index 0000000..9b2ec91 --- /dev/null +++ b/src/protocol.c @@ -0,0 +1,244 @@ +/* + protocol.c -- handle the meta-protocol, basic 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. + + $Id: protocol.c,v 1.28.4.128 2002/03/27 15:26:43 guus Exp $ +*/ + +#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; + +int check_id(char *id) +{ + int i; + + for (i = 0; i < strlen(id); i++) + if(!isalnum(id[i]) && id[i] != '_') + return -1; + + return 0; +} + +/* 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; + +cp + /* Use vsnprintf instead of vasprintf: 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); + + 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((c->allow_request != ALL) && (c->allow_request != request)) + { + syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, c->hostname); + return -1; + } + + 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; +} + +int past_request_compare(past_request_t *a, past_request_t *b) +{ +cp + return strcmp(a->request, b->request); +} + +void free_past_request(past_request_t *r) +{ +cp + if(r->request) + free(r->request); + free(r); +cp +} + +void init_requests(void) +{ +cp + past_request_tree = avl_alloc_tree((avl_compare_t)past_request_compare, (avl_action_t)free_past_request); +cp +} + +void exit_requests(void) +{ +cp + avl_delete_tree(past_request_tree); +cp +} + +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 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 +} + +/* Jumptable for the request handlers */ + +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, +}; + +/* Request names */ + +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", +}; diff --git a/src/protocol.h b/src/protocol.h new file mode 100644 index 0000000..a4e480a --- /dev/null +++ b/src/protocol.h @@ -0,0 +1,120 @@ +/* + protocol.h -- header for protocol.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. + + $Id: protocol.h,v 1.5.4.29 2002/03/22 11:43:48 guus Exp $ +*/ + +#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 + +/* 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 struct past_request_t { + char *request; + time_t firstseen; +} past_request_t; + +/* Maximum size of strings in a request */ + +#define MAX_STRING_SIZE 2048 +#define MAX_STRING "%2048s" + +/* Basic functions */ + +extern int send_request(connection_t*, const char*, ...); +extern int receive_request(connection_t *); +extern int check_id(char *); + +extern void init_requests(void); +extern void exit_requests(void); +extern int seen_request(char *); +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 *); + +/* Request handlers */ + +extern int (*request_handlers[])(connection_t *); + +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__ */ diff --git a/src/protocol_auth.c b/src/protocol_auth.c new file mode 100644 index 0000000..074b7d1 --- /dev/null +++ b/src/protocol_auth.c @@ -0,0 +1,605 @@ +/* + protocol_auth.c -- handle the meta-protocol, authentication + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: protocol_auth.c,v 1.1.4.8 2002/03/27 15:26:44 guus Exp $ +*/ + +#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); +} + +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; + } + + /* 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; + } + + EVP_DecryptInit(c->inctx, c->incipher, + c->inkey + len - c->incipher->key_len, + c->inkey + len - c->incipher->key_len - c->incipher->iv_len); + + c->status.decryptin = 1; + } + else + { + c->incipher = NULL; + } + + 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(c->inmaclength > c->indigest->md_size || c->inmaclength < 0) + { + syslog(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, c->hostname); + return -1; + } + } + else + { + c->indigest = NULL; + } + + c->incompression = compression; + + c->allow_request = CHALLENGE; +cp + return send_challenge(c); +} + +int send_challenge(connection_t *c) +{ + char buffer[MAX_STRING_SIZE]; + int len, x; +cp + /* CHECKME: what is most reasonable value for len? */ + + 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 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; + } + + len = RSA_size(myself->connection->rsa_key); + + /* Check if the length of the challenge is all right */ + + if(strlen(buffer) != len*2) + { + syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong challenge length"); + return -1; + } + + /* Allocate buffers for the challenge */ + + if(!c->mychallenge) + c->mychallenge = xmalloc(len); + + /* Convert the challenge from hexadecimal back to binary */ + + hex2bin(buffer,c->mychallenge,len); + + c->allow_request = CHAL_REPLY; + + /* Rest is done by send_chal_reply() */ +cp + return send_chal_reply(c); +} + +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 */ + + EVP_DigestInit(&ctx, c->indigest); + EVP_DigestUpdate(&ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)); + EVP_DigestFinal(&ctx, hash, NULL); + + /* Convert the hash to a hexadecimal formatted string */ + + bin2hex(hash,hash,c->indigest->md_size); + hash[c->indigest->md_size*2] = '\0'; + + /* Send the reply */ + +cp + return send_request(c, "%d %s", CHAL_REPLY, hash); +} + +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; + } + + /* Check if the length of the hash is all right */ + + 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; + } + + /* Convert the hash to binary format */ + + hex2bin(hishash, hishash, c->outdigest->md_size); + + /* Calculate the hash from the challenge we sent */ + + EVP_DigestInit(&ctx, c->outdigest); + EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key)); + EVP_DigestFinal(&ctx, myhash, NULL); + + /* Verify the incoming hash with the calculated hash */ + + 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; + } + + /* Identity has now been positively verified. + Send an acknowledgement with the rest of the information needed. + */ + + c->allow_request = ACK; +cp + return send_ack(c); +} + +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. */ + + 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; +} + +void send_everything(connection_t *c) +{ + avl_node_t *node, *node2; + node_t *n; + subnet_t *s; + edge_t *e; + + /* Send all known subnets */ + + for(node = node_tree->head; node; node = node->next) + { + n = (node_t *)node->data; + + for(node2 = n->subnet_tree->head; node2; node2 = node2->next) + { + s = (subnet_t *)node2->data; + send_add_subnet(c, s); + } + } + + /* Send all known edges */ + + for(node = edge_tree->head; node; node = node->next) + { + e = (edge_t *)node->data; + + if(e == c->edge) + continue; + + send_add_edge(c, e); + } +} + +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; + } + + /* 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. */ + 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; + + /* Create an edge_t for this connection */ + + 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); + + /* Activate this connection */ + + c->allow_request = ALL; + c->status.active = 1; + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname); + +cp + /* Send him everything we know */ + + send_everything(c); + + /* Notify others of this connection */ + + for(node = connection_tree->head; node; node = node->next) + { + other = (connection_t *)node->data; + + if(other->status.active && other != c) + send_add_edge(other, c->edge); + } + + /* Run MST and SSSP algorithms */ + + graph(); +cp + return 0; +} diff --git a/src/protocol_edge.c b/src/protocol_edge.c new file mode 100644 index 0000000..0d3218e --- /dev/null +++ b/src/protocol_edge.c @@ -0,0 +1,298 @@ +/* + protocol_edge.c -- handle the meta-protocol, edges + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: protocol_edge.c,v 1.1.4.7 2002/03/27 15:26:44 guus Exp $ +*/ + +#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; +} + +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; + } + + /* Check if names are valid */ + + 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; + } + + 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(seen_request(c->buffer)) + return 0; + + /* Lookup nodes */ + + from = lookup_node(from_name); + + if(!from) + { + from = new_node(); + from->name = xstrdup(from_name); + node_add(from); + } + + to = lookup_node(to_name); + + if(!to) + { + to = new_node(); + to->name = xstrdup(to_name); + node_add(to); + } + + /* Convert addresses */ + + from_udpaddress = str2sockaddr(from_address, from_udpport); + to_udpaddress = str2sockaddr(to_address, to_udpport); + + /* 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; + } + + 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 */ + + 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); + } + + /* Run MST before or after we tell the rest? */ + + graph(); +cp + return 0; +} + +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); +} + +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; + } + + /* Check if names are valid */ + + 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; + } + + 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(seen_request(c->buffer)) + return 0; + + /* 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; + } + + 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; + } + + /* 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(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; + } + + /* Tell the rest about the deleted edge */ + + 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); + } + + /* Delete the edge */ + + edge_del(e); + + /* Run MST before or after we tell the rest? */ + + graph(); +cp + return 0; +} diff --git a/src/protocol_key.c b/src/protocol_key.c new file mode 100644 index 0000000..016fbff --- /dev/null +++ b/src/protocol_key.c @@ -0,0 +1,286 @@ +/* + protocol_key.c -- handle the meta-protocol, key exchange + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: protocol_key.c,v 1.1.4.6 2002/03/22 13:31:18 guus Exp $ +*/ + +#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; + +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. + */ + + if(n == myself && !mykeyused) + return 0; + + 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; +} + +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; + } + + if(seen_request(c->buffer)) + return 0; + + n = lookup_node(name); + + 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(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; +} diff --git a/src/protocol_misc.c b/src/protocol_misc.c new file mode 100644 index 0000000..9f1a5fb --- /dev/null +++ b/src/protocol_misc.c @@ -0,0 +1,198 @@ +/* + protocol_misc.c -- handle the meta-protocol, miscellaneous functions + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: protocol_misc.c,v 1.1.4.3 2002/03/23 20:21:10 guus Exp $ +*/ + +#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 */ + +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 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; +} + +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); +} + +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; + } + + if(debug_lvl >= DEBUG_ERROR) + { + syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"), + c->name, c->hostname, strerror(err), errorstring); + } + + terminate_connection(c, c->status.active); +cp + return 0; +} + +int send_termreq(connection_t *c) +{ +cp + return send_request(c, "%d", TERMREQ); +} + +int termreq_h(connection_t *c) +{ +cp + terminate_connection(c, c->status.active); +cp + return 0; +} + +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; +} + +/* Sending and receiving packets via TCP */ + +int send_tcppacket(connection_t *c, vpn_packet_t *packet) +{ + int x; +cp + /* Evil hack. */ + + x = send_request(c, "%d %hd", PACKET, packet->len); + + if(x) + return x; +cp + return send_meta(c, packet->data, packet->len); +} + +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; + } + + /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */ + + c->tcplen = len; +cp + return 0; +} + +/* Status strings */ + +char (*status_text[]) = { + "Warning", +}; + +/* Error strings */ + +char (*error_text[]) = { + "Error", +}; diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c new file mode 100644 index 0000000..7f6cfc1 --- /dev/null +++ b/src/protocol_subnet.c @@ -0,0 +1,237 @@ +/* + protocol_subnet.c -- handle the meta-protocol, subnets + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-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: protocol_subnet.c,v 1.1.4.3 2002/03/22 13:31:18 guus Exp $ +*/ + +#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; +} + +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; + } + + /* Check if owner name is a valid */ + + 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 subnet string is valid */ + + 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; + } + + if(seen_request(c->buffer)) + return 0; + + /* Check if the owner of the new subnet is in the connection list */ + + owner = lookup_node(name); + + if(!owner) + { + owner = new_node(); + owner->name = xstrdup(name); + node_add(owner); + } + + /* Check if we already know this subnet */ + + if(lookup_subnet(owner, s)) + { + free_subnet(s); + return 0; + } + + /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */ + + 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 everything is correct, add the subnet to the list of the owner */ + + subnet_add(owner, s); + + /* 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; +} + +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; +} + +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; + } + + /* Check if owner name is a valid */ + + 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 the owner of the new subnet is in the connection list */ + + 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 */ + + 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 0; + + /* If everything is correct, delete the subnet from the list of the owner */ + + s->owner = owner; + + find = lookup_subnet(owner, s); + + free_subnet(s); + + 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; + } + + /* 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); + } + + /* Finally, delete it. */ + + subnet_del(owner, find); + +cp + return 0; +} diff --git a/src/route.c b/src/route.c new file mode 100644 index 0000000..dcf43e4 --- /dev/null +++ b/src/route.c @@ -0,0 +1,493 @@ +/* + route.c -- routing + Copyright (C) 2000-2002 Ivo Timmermans , + 2000-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: route.c,v 1.1.2.37 2002/03/19 00:08:23 guus Exp $ +*/ + +#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; +int macexpire = 600; +subnet_t mymac; + +void learn_mac(mac_t *address) +{ + subnet_t *subnet; + avl_node_t *node; + connection_t *c; +cp + subnet = lookup_subnet_mac(address); + + /* 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); + + /* 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); + } + } + + subnet->net.mac.lastseen = now; +} + +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); + } + } +cp +} + +node_t *route_mac(vpn_packet_t *packet) +{ + subnet_t *subnet; +cp + /* Learn source address */ + + 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; + } + 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; + } +} + +void route_incoming(node_t *source, vpn_packet_t *packet) +{ + switch(routing_mode) + { + case RMODE_ROUTER: + { + node_t *n = NULL; + unsigned short int type; + + 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; + 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; + } +} diff --git a/src/route.h b/src/route.h new file mode 100644 index 0000000..d188af2 --- /dev/null +++ b/src/route.h @@ -0,0 +1,41 @@ +/* + route.h -- header file for route.c + Copyright (C) 2000-2002 Ivo Timmermans + 2000-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: route.h,v 1.1.2.7 2002/03/01 14:09:31 guus Exp $ +*/ + +#ifndef __TINC_ROUTE_H__ +#define __TINC_ROUTE_H__ + +enum +{ + RMODE_HUB = 0, + RMODE_SWITCH, + RMODE_ROUTER, +}; + +extern int routing_mode; +extern int 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 *); + +#endif /* __TINC_ROUTE_H__ */ diff --git a/src/solaris/device.c b/src/solaris/device.c new file mode 100644 index 0000000..758068d --- /dev/null +++ b/src/solaris/device.c @@ -0,0 +1,196 @@ +/* + device.c -- Interaction with Solaris 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.7 2002/02/18 16:25:19 guus Exp $ +*/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_DEVICE "/dev/tun" + +#include +#include "conf.h" +#include "net.h" +#include "subnet.h" + +#include "system.h" + +int device_fd = -1; +int device_type; +char *device = NULL; +char *interface = NULL; +char ifrname[IFNAMSIZ]; +char *device_info = NULL; + +int device_total_in = 0; +int device_total_out = 0; + +subnet_t mymac; + +int setup_device(void) +{ + int ip_fd = -1, if_fd = -1; + int ppa; + char *ptr; + +cp + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_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 + ppa = 0; + + ptr = device; + while(*ptr && !isdigit((int)*ptr)) ptr++; + ppa = atoi(ptr); + + if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){ + syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno)); + return -1; + } + + /* 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( (if_fd = open(device, O_RDWR, 0)) < 0){ + syslog(LOG_ERR, _("Could not open %s twice: %s"), device, strerror(errno)); + return -1; + } + + if(ioctl(if_fd, I_PUSH, "ip") < 0){ + syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno)); + return -1; + } + + /* 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; + } + + if(ioctl(ip_fd, I_LINK, if_fd) < 0){ + syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno)); + return -1; + } + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + asprintf(&interface, "tun%d", ppa); + + device_info = _("Solaris tun device"); + + /* 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; + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); +cp + return 0; +} + +void close_device(void) +{ +cp + close(device_fd); +} + +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; + } + + 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; + + packet->len = lenin + 14; + + 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 + 14, packet->len - 14) < 0) + { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, 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/subnet.c b/src/subnet.c new file mode 100644 index 0000000..0320957 --- /dev/null +++ b/src/subnet.c @@ -0,0 +1,394 @@ +/* + subnet.c -- handle subnet lookups and lists + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: subnet.c,v 1.1.2.34 2002/04/09 11:42:48 guus Exp $ +*/ + +#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" + +/* lists type of subnet */ + +avl_tree_t *subnet_tree; + +/* 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)); +} + +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; + + return a->net.ipv4.prefixlength - b->net.ipv4.prefixlength; +} + +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; + + return a->net.ipv6.prefixlength - b->net.ipv6.prefixlength; +} + +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); + } + + 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 exit_subnets(void) +{ +cp + avl_delete_tree(subnet_tree); +cp +} + +avl_tree_t *new_subnet_tree(void) +{ +cp + return avl_alloc_tree((avl_compare_t)subnet_compare, NULL); +cp +} + +void free_subnet_tree(avl_tree_t *subnet_tree) +{ +cp + avl_delete_tree(subnet_tree); +cp +} + +/* Allocating and freeing space for subnets */ + +subnet_t *new_subnet(void) +{ +cp + return (subnet_t *)xmalloc(sizeof(subnet_t)); +} + +void free_subnet(subnet_t *subnet) +{ +cp + free(subnet); +} + +/* Adding and removing subnets */ + +void subnet_add(node_t *n, subnet_t *subnet) +{ +cp + subnet->owner = n; + + avl_insert(subnet_tree, subnet); +cp + avl_insert(n->subnet_tree, subnet); +cp +} + +void subnet_del(node_t *n, subnet_t *subnet) +{ +cp + avl_delete(n->subnet_tree, subnet); +cp + avl_delete(subnet_tree, subnet); +cp +} + +/* 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; + } + + 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; + } + + 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; + } + + free(subnet); + return NULL; +} + +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; +} + +/* 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_mac(mac_t *address) +{ + subnet_t subnet, *p; +cp + subnet.type = SUBNET_MAC; + memcpy(&subnet.net.mac.address, address, sizeof(mac_t)); + + p = (subnet_t *)avl_search(subnet_tree, &subnet); +cp + return p; +} + +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; + + do + { + /* Go find subnet */ + + p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet); + + /* Check if the found subnet REALLY matches */ +cp + if(p) + { + if(p->type != SUBNET_IPV4) + { + p = NULL; + break; + } + + 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 */ + + 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; +} + +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); + + /* Check if the found subnet REALLY matches */ + +cp + if(p) + { + if(p->type != SUBNET_IPV6) + return NULL; + + 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 */ + + 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; +} + +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 +} diff --git a/src/subnet.h b/src/subnet.h new file mode 100644 index 0000000..be20315 --- /dev/null +++ b/src/subnet.h @@ -0,0 +1,88 @@ +/* + subnet.h -- header for subnet.c + Copyright (C) 2000,2001 Guus Sliepen , + 2000,2001 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: subnet.h,v 1.1.2.18 2002/04/09 11:42:48 guus Exp $ +*/ + +#ifndef __TINC_SUBNET_H__ +#define __TINC_SUBNET_H__ + +#include "net.h" + +enum +{ + SUBNET_MAC = 0, + SUBNET_IPV4, + SUBNET_IPV6, + SUBNET_TYPES /* Guardian */ +}; + +typedef struct subnet_mac_t +{ + mac_t address; + time_t lastseen; +} subnet_mac_t; + +typedef struct subnet_ipv4_t +{ + ipv4_t address; + int prefixlength; +} subnet_ipv4_t; + +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 */ + + int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ + + /* And now for the actual subnet: */ + + 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 *); +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 void dump_subnets(void); + +#endif /* __TINC_SUBNET_H__ */ diff --git a/src/tincd.c b/src/tincd.c new file mode 100644 index 0000000..b8b2959 --- /dev/null +++ b/src/tincd.c @@ -0,0 +1,400 @@ +/* + tincd.c -- the main file for tincd + Copyright (C) 1998-2002 Ivo Timmermans + 2000-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: tincd.c,v 1.10.4.58 2002/03/11 11:23:04 guus Exp $ +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_IOCTL_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "conf.h" +#include "net.h" +#include "netutl.h" +#include "process.h" +#include "protocol.h" +#include "subnet.h" + +#include "system.h" + +/* The name this program was run with. */ +char *program_name; + +/* If nonzero, display usage information and exit. */ +int show_help; + +/* If nonzero, print the version on standard output and exit. */ +int show_version; + +/* If nonzero, it will attempt to kill a running tincd and exit. */ +int kill_tincd = 0; + +/* If nonzero, generate public/private keypair for this host/net. */ +int generate_keys = 0; + +/* If nonzero, use null ciphers and skip all key exchanges. */ +int bypass_security = 0; + +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 */ + +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 } +}; + +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); +} + +void +parse_options(int argc, char **argv, char **envp) +{ + int r; + int option_index = 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; + } + } +} + +/* 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, "?"); + } +} + +/* + 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; + + fprintf(stderr, _("Generating %d bits keys:\n"), bits); + rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL); + + if(!rsa_key) + { + fprintf(stderr, _("Error during key generation!\n")); + return -1; + } + else + fprintf(stderr, _("Done.\n")); + + get_config_string(lookup_config(config_tree, "Name"), &name); + + if(name) + asprintf(&filename, "%s/hosts/%s", confbase, name); + else + asprintf(&filename, "%s/rsa_key.pub", confbase); + + if((f = ask_and_safe_open(filename, _("public RSA key"), "a")) == NULL) + return -1; + + if(ftell(f)) + fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + + PEM_write_RSAPublicKey(f, rsa_key); + fclose(f); + free(filename); + + asprintf(&filename, "%s/rsa_key.priv", confbase); + if((f = ask_and_safe_open(filename, _("private RSA key"), "a")) == NULL) + return -1; + + if(ftell(f)) + fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + + PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(f); + free(filename); + + return 0; +} + +/* + 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 */ +#endif + + g_argv = argv; + + make_names(); + init_configuration(&config_tree); + + /* Slllluuuuuuurrrrp! */ +cp + RAND_load_file("/dev/urandom", 1024); + +#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(kill_tincd) + exit(kill_other(kill_tincd)); + + 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); + } + } +} diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000..e69de29 diff --git a/system.h b/system.h new file mode 100644 index 0000000..51adca0 --- /dev/null +++ b/system.h @@ -0,0 +1,52 @@ +/* + 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__ */ +