summaryrefslogtreecommitdiff
authorplurSKI <black.gavin@gmail.com>2010-10-25 02:37:16 (GMT)
committer plurSKI <black.gavin@gmail.com>2010-10-25 02:37:16 (GMT)
commitce42485dd539f0aeb71fee7f590d24b235ddb160 (patch)
treea9c229e54c34a581709a13c3f86dae237078029a
downloadcheaTorrent-master.zip
cheaTorrent-master.tar.gz
Initial Commitmaster
-rw-r--r--COPYING340
-rw-r--r--INSTALL38
-rw-r--r--Makefile588
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in586
-rw-r--r--UserGuide577
-rw-r--r--aclocal.m41020
-rw-r--r--bencode.cpp255
-rw-r--r--bencode.h37
-rw-r--r--bencode.obin0 -> 17272 bytes
-rw-r--r--bitfield.cpp365
-rw-r--r--bitfield.h55
-rw-r--r--bitfield.obin0 -> 32560 bytes
-rw-r--r--btconfig.cpp49
-rw-r--r--btconfig.h60
-rw-r--r--btconfig.obin0 -> 5500 bytes
-rw-r--r--btcontent.cpp1619
-rw-r--r--btcontent.h198
-rw-r--r--btcontent.obin0 -> 142684 bytes
-rw-r--r--btfiles.cpp815
-rw-r--r--btfiles.h81
-rw-r--r--btfiles.obin0 -> 61400 bytes
-rw-r--r--btrequest.cpp651
-rw-r--r--btrequest.h92
-rw-r--r--btstream.cpp195
-rw-r--r--btstream.h66
-rw-r--r--bttime.h9
-rw-r--r--bufio.cpp177
-rw-r--r--bufio.h58
-rw-r--r--cheatorrent.cpp445
-rw-r--r--cheatorrent.h0
-rw-r--r--compat.c158
-rw-r--r--compat.h65
-rw-r--r--config.h322
-rw-r--r--config.h.in321
-rwxr-xr-xconfigure10686
-rw-r--r--configure.ac154
-rw-r--r--connect_nonb.cpp15
-rw-r--r--connect_nonb.h17
-rw-r--r--console.cpp1441
-rw-r--r--console.h142
-rw-r--r--ctcs.cpp876
-rw-r--r--ctcs.h95
-rw-r--r--def.h43
-rwxr-xr-xdepcomp411
-rw-r--r--downloader.cpp138
-rw-r--r--downloader.h6
-rw-r--r--httpencode.cpp156
-rw-r--r--httpencode.h15
-rwxr-xr-xinstall-sh251
-rw-r--r--iplist.cpp47
-rw-r--r--iplist.h38
-rwxr-xr-xmissing283
-rwxr-xr-xmkinstalldirs40
-rw-r--r--msgencode.h24
-rw-r--r--peer.cpp1410
-rw-r--r--peer.h222
-rw-r--r--peerlist.cpp1607
-rw-r--r--peerlist.h127
-rw-r--r--rate.cpp334
-rw-r--r--rate.h71
-rw-r--r--setnonblock.cpp25
-rw-r--r--setnonblock.h17
-rw-r--r--sha1.c251
-rw-r--r--sha1.h37
-rw-r--r--sigint.cpp68
-rw-r--r--sigint.h18
-rw-r--r--stamp-h.in1
-rw-r--r--stamp-h11
-rw-r--r--tracker.cpp669
-rw-r--r--tracker.h118
-rw-r--r--version.m45
72 files changed, 29103 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ 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
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..a7729ac
--- a/dev/null
+++ b/INSTALL
@@ -0,0 +1,38 @@
+How to install:
+
+$ ./configure
+$ make install
+$ hash
+$ cheatorrent -h
+
+If SSL support is not found, the public-domain SHA1 code will be used.
+To force the use of this code, specify:
+ --with-ssl=no
+as a parameter to the configure script.
+To give configure a hint about where to find SSL on your system, specify:
+ --with-ssl=DIR
+where DIR is the common directory under which sha.h and the SSL libraries
+are located. For example, if the files are located at:
+ /opt/include/openssl/sha.h
+ /opt/lib/libcrypto.a
+use:
+ --with-ssl=/opt
+There are several combinations of subdirectories that will be tried by
+the configure script. If all else fails, create symbolic links for
+sha.h and the applicable library (libssl.a, libcrypto.a, libcrypt.a, or
+libmd.a) in a single directory and specify that.
+
+Or set the CPPFLAGS environment variable to "-Idir" (where "dir" is the
+directory in which sha.h resides) and the LDFLAGS environment variable
+to "-Ldir" (where "dir" is the directory in which the library containing
+SHA1 support resides), then re-run configure.
+
+Check the documentation or man page for your shell to determine how to
+set an environment variable.
+Example using csh/tcsh:
+ setenv CPPFLAGS "-I/usr/local/include"
+
+Hint: You can use the "strings" command to help determine whether SHA1
+support is present in a library, as in:
+ strings libcrypto.a | grep SHA1_Init
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d6de430
--- a/dev/null
+++ b/Makefile
@@ -0,0 +1,588 @@
+# Makefile.in generated by automake 1.9.1 from Makefile.am.
+# Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004 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.
+
+
+
+SOURCES = $(cheatorrent_SOURCES)
+
+srcdir = .
+top_srcdir = .
+
+pkgdatadir = $(datadir)/cheatorrent
+pkglibdir = $(libdir)/cheatorrent
+pkgincludedir = $(includedir)/cheatorrent
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+bin_PROGRAMS = cheatorrent$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ depcomp install-sh missing mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/version.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_cheatorrent_OBJECTS = bencode.$(OBJEXT) bitfield.$(OBJEXT) \
+ btconfig.$(OBJEXT) btcontent.$(OBJEXT) btfiles.$(OBJEXT) \
+ btrequest.$(OBJEXT) btstream.$(OBJEXT) bufio.$(OBJEXT) \
+ compat.$(OBJEXT) connect_nonb.$(OBJEXT) console.$(OBJEXT) \
+ ctcs.$(OBJEXT) cheatorrent.$(OBJEXT) downloader.$(OBJEXT) \
+ httpencode.$(OBJEXT) iplist.$(OBJEXT) peer.$(OBJEXT) \
+ peerlist.$(OBJEXT) rate.$(OBJEXT) setnonblock.$(OBJEXT) \
+ sigint.$(OBJEXT) tracker.$(OBJEXT) sha1.$(OBJEXT)
+cheatorrent_OBJECTS = $(am_cheatorrent_OBJECTS)
+cheatorrent_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(cheatorrent_SOURCES)
+DIST_SOURCES = $(cheatorrent_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run aclocal-1.9
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run tar
+AUTOCONF = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run automake-1.9
+AWK = mawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPPFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LDFLAGS =
+LIBOBJS =
+LIBS = -lrt
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /home/rdeveloper/cheattorrent/cheatorrent_v1.0/missing --run makeinfo
+OBJEXT = o
+PACKAGE = cheatorrent
+PACKAGE_BUGREPORT = lol
+PACKAGE_NAME = CheaTorrent
+PACKAGE_STRING = CheaTorrent
+PACKAGE_TARNAME = cheatorrent
+PACKAGE_VERSION = v1.0
+PATH_SEPARATOR = :
+POW_LIB =
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = v1.0
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE =
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE =
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build_alias =
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host_alias =
+includedir = ${prefix}/include
+infodir = ${prefix}/share/info
+install_sh = /home/rdeveloper/cheattorrent/cheatorrent_v1.0/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/share/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+prefix = /usr/local
+program_transform_name = s,x,x,
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias =
+cheatorrent_SOURCES = bencode.cpp bitfield.cpp btconfig.cpp btcontent.cpp btfiles.cpp btrequest.cpp btstream.cpp bufio.cpp compat.c connect_nonb.cpp console.cpp ctcs.cpp cheatorrent.cpp downloader.cpp httpencode.cpp iplist.cpp peer.cpp peerlist.cpp rate.cpp setnonblock.cpp sigint.cpp tracker.cpp sha1.c bencode.h bitfield.h btconfig.h btcontent.h btfiles.h btrequest.h btstream.h bttime.h bufio.h compat.h connect_nonb.h console.h ctcs.h def.h downloader.h httpencode.h iplist.h msgencode.h peer.h peerlist.h rate.h setnonblock.h sigint.h tracker.h sha1.h
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
+ cd $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+cheatorrent$(EXEEXT): $(cheatorrent_OBJECTS) $(cheatorrent_DEPENDENCIES)
+ @rm -f cheatorrent$(EXEEXT)
+ $(CXXLINK) $(cheatorrent_LDFLAGS) $(cheatorrent_OBJECTS) $(cheatorrent_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/bencode.Po
+include ./$(DEPDIR)/bitfield.Po
+include ./$(DEPDIR)/btconfig.Po
+include ./$(DEPDIR)/btcontent.Po
+include ./$(DEPDIR)/btfiles.Po
+include ./$(DEPDIR)/btrequest.Po
+include ./$(DEPDIR)/btstream.Po
+include ./$(DEPDIR)/bufio.Po
+include ./$(DEPDIR)/compat.Po
+include ./$(DEPDIR)/connect_nonb.Po
+include ./$(DEPDIR)/console.Po
+include ./$(DEPDIR)/ctcs.Po
+include ./$(DEPDIR)/cheatorrent.Po
+include ./$(DEPDIR)/downloader.Po
+include ./$(DEPDIR)/httpencode.Po
+include ./$(DEPDIR)/iplist.Po
+include ./$(DEPDIR)/peer.Po
+include ./$(DEPDIR)/peerlist.Po
+include ./$(DEPDIR)/rate.Po
+include ./$(DEPDIR)/setnonblock.Po
+include ./$(DEPDIR)/sha1.Po
+include ./$(DEPDIR)/sigint.Po
+include ./$(DEPDIR)/tracker.Po
+
+.c.o:
+ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(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
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(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; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(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 "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || 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-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) config.h
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+ clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \
+ dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \
+ distclean-compile distclean-generic distclean-hdr \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ 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/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..d498e84
--- a/dev/null
+++ b/Makefile.am
@@ -0,0 +1,2 @@
+bin_PROGRAMS = cheatorrent
+cheatorrent_SOURCES = bencode.cpp bitfield.cpp btconfig.cpp btcontent.cpp btfiles.cpp btrequest.cpp btstream.cpp bufio.cpp compat.c connect_nonb.cpp console.cpp ctcs.cpp cheatorrent.cpp downloader.cpp httpencode.cpp iplist.cpp peer.cpp peerlist.cpp rate.cpp setnonblock.cpp sigint.cpp tracker.cpp sha1.c bencode.h bitfield.h btconfig.h btcontent.h btfiles.h btrequest.h btstream.h bttime.h bufio.h compat.h connect_nonb.h console.h ctcs.h def.h downloader.h httpencode.h iplist.h msgencode.h peer.h peerlist.h rate.h setnonblock.h sigint.h tracker.h sha1.h
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..ee12056
--- a/dev/null
+++ b/Makefile.in
@@ -0,0 +1,586 @@
+# Makefile.in generated by automake 1.9.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004 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@
+
+SOURCES = $(cheatorrent_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+bin_PROGRAMS = cheatorrent$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ depcomp install-sh missing mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_cheatorrent_OBJECTS = bencode.$(OBJEXT) bitfield.$(OBJEXT) \
+ btconfig.$(OBJEXT) btcontent.$(OBJEXT) btfiles.$(OBJEXT) \
+ btrequest.$(OBJEXT) btstream.$(OBJEXT) bufio.$(OBJEXT) \
+ compat.$(OBJEXT) connect_nonb.$(OBJEXT) console.$(OBJEXT) \
+ ctcs.$(OBJEXT) cheatorrent.$(OBJEXT) downloader.$(OBJEXT) \
+ httpencode.$(OBJEXT) iplist.$(OBJEXT) peer.$(OBJEXT) \
+ peerlist.$(OBJEXT) rate.$(OBJEXT) setnonblock.$(OBJEXT) \
+ sigint.$(OBJEXT) tracker.$(OBJEXT) sha1.$(OBJEXT)
+cheatorrent_OBJECTS = $(am_cheatorrent_OBJECTS)
+cheatorrent_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(cheatorrent_SOURCES)
+DIST_SOURCES = $(cheatorrent_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POW_LIB = @POW_LIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+cheatorrent_SOURCES = bencode.cpp bitfield.cpp btconfig.cpp btcontent.cpp btfiles.cpp btrequest.cpp btstream.cpp bufio.cpp compat.c connect_nonb.cpp console.cpp ctcs.cpp cheatorrent.cpp downloader.cpp httpencode.cpp iplist.cpp peer.cpp peerlist.cpp rate.cpp setnonblock.cpp sigint.cpp tracker.cpp sha1.c bencode.h bitfield.h btconfig.h btcontent.h btfiles.h btrequest.h btstream.h bttime.h bufio.h compat.h connect_nonb.h console.h ctcs.h def.h downloader.h httpencode.h iplist.h msgencode.h peer.h peerlist.h rate.h setnonblock.h sigint.h tracker.h sha1.h
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
+ cd $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+cheatorrent$(EXEEXT): $(cheatorrent_OBJECTS) $(cheatorrent_DEPENDENCIES)
+ @rm -f cheatorrent$(EXEEXT)
+ $(CXXLINK) $(cheatorrent_LDFLAGS) $(cheatorrent_OBJECTS) $(cheatorrent_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bencode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitfield.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btconfig.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btcontent.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btfiles.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btrequest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btstream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufio.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_nonb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctcs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cheatorrent.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/downloader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpencode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iplist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peerlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setnonblock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tracker.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(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
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(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; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(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 "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || 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-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) config.h
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+ clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \
+ dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \
+ distclean-compile distclean-generic distclean-hdr \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ 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/UserGuide b/UserGuide
new file mode 100644
index 0000000..b90a72f
--- a/dev/null
+++ b/UserGuide
@@ -0,0 +1,577 @@
+
+ Enhanced CheaTorrent User's Guide
+
+ This guide is presented to offer additional information related to
+ using [1]Enhanced CheaTorrent.
+
+ This document is not an introduction to BitTorrent--for that, try
+ [2]this, [3]this, or an Internet search.
+
+ Contents
+
+ * Options
+ + [4]General
+ + [5]Downloading
+ + [6]Create Torrent
+ * [7]Examples
+ * [8]Runtime Commands
+ + [9]Operator Menu
+ * Usage Notes
+ + [10]Bandwidth Limits
+ + [11]Startup
+ + [12]Status Line
+ + [13]Stopping CheaTorrent
+
+ Options Index
+ [14]-a [15]-A [16]-b [17]-c [18]-c [19]-C [20]-d [21]-D [22]-e [23]-E
+ [24]-f [25]-i [26]-I [27]-l [28]-m [29]-M [30]-n [31]-p [32]-p [33]-P
+ [34]-s [35]-s [36]-S [37]-t [38]-T [39]-u [40]-u [41]-U [42]-v [43]-x
+ [44]-X [45]-z
+ _________________________________________________________________
+
+ Options
+ ___________________________________
+
+ General Options
+
+
+-x Decode metainfo (torrent) file only, don't download
+
+ Displays the torrent information and contents from the metainfo
+ (.torrent) file. No piece checking or downloading is performed.
+ This option is normally used alone.
+
+
+-c Check pieces only, don't download
+
+ Hash-checks all pieces of the torrent to verify completion
+ status and exits. Use this when you want to verify that you've
+ successfully downloaded the complete torrent, or to make sure
+ the files are intact after a system crash. This option is
+ normally used alone, but can be used with -X for an automated
+ completion check.
+
+
+-v Verbose output (for debugging)
+
+ Generates [a lot of] extra output while CTorrrent is running.
+ ___________________________________
+
+ Downloading Options
+
+
+-e int Exit while seed <int> hours later (default 72 hours)
+
+ Indicate how long (in hours) you want to "seed" (continue
+ uploading) after download has completed. It is considered
+ polite and fair (and required by some tracker sites) to seed
+ for some time after downloading.
+
+
+-E num Exit after seeding to <num> ratio (UL:DL)
+
+ Specify a desired "seed ratio". After downloading completes,
+ the client will continue seeding (uploading) until your total
+ upload volume divided by your download volume equals this
+ number. Fractional values (such as 1.5) are allowed. It is
+ considered polite and fair (and required by some tracker sites)
+ to seed until your ratio is at least 1:1.
+
+
+-i ip Listen for connections on specific IP address (default all/any)
+
+ Specify the IP address on which you want to listen for incoming
+ connections. This is only useful if your system has multiple
+ network interfaces and you want to restrict access or run
+ multiple clients on different interfaces.
+
+
+-p port Listen port (default 2706 -> 2106)
+
+ Specify the TCP port number on which to listen for incoming
+ connections. By default, CheaTorrent starts at 2706 and searches
+ for an available port in decreasing order until it finds one or
+ exhausts all ports down through 2106. The behavior with this
+ option is similar, but starting at the specified port number.
+
+
+-I ip Specify public/external IP address for peer connections
+
+ Specify the IP address which the tracker should give out to
+ peer clients in order to connect to you. This is normally
+ needed only if you are behind a NAT and on the tracker's local
+ network.
+
+
+-u num or URL Alternate announce (tracker) URL
+
+ Specify an alternate tracker announce URL. The parameter can be
+ the actual URL or the number from the list of alternates
+ printed when starting the client or using -x.
+
+
+-s filename Download ("save as") to a different file or directory
+
+ Download to a different filename or top-level directory name
+ than what is given in the metainfo file.
+
+
+-C cache_size Cache size, unit MB (default 16MB)
+
+ Specify the maximum amount of memory to use for caching
+ downloaded slices. The program may use less than this; the
+ cache size is dynamically tuned based on the download and
+ upload rates. You may need to use this option if running on a
+ memory-constrained system such as a router or SAN device. If
+ you use a value of 0, no memory cache will be used but the
+ process will be more disk-intensive.
+
+
+-f Force saved bitfield or seed mode (skip hash check at startup)
+
+ Perform a fast startup by skipping the initial (or background)
+ hash verification of the files. This option is not generally
+ recommended since the client now performs initial hash checking
+ in the background. Use this option only if CheaTorrent was shut
+ down cleanly when last downloading this torrent and you are
+ absolutely certain that the bitfield (if download is not
+ complete) and data files are intact and correct. To emulate the
+ old behavior of hash-checking all pieces before beginning
+ download or seeding, use -f along with the -c option.
+
+
+-b filename Specify bitfield save file (default is torrent+".bf")
+
+ Piece completion status is saved to a bitfield file on exit if
+ download has not completed. On startup the file is read to
+ determine (and check) available pieces. The -b option can be
+ used to specify a filename other than the default. Be
+ consistent and careful with this option; it is generally not
+ needed.
+
+
+-M max_peers Max peers count (default 100)
+
+ Set the maximum allowable number of peer connections. If this
+ number is reached, no new connections will be initiated or
+ accepted. If memory or upload bandwidth are constrained, you
+ may want to use this option to specify a lower value.
+
+
+-m min_peers Min peers count (default 1)
+
+ Set the desired minimum number of peer connections. If the
+ number falls below this value, the client will contact the
+ tracker to request more peers.
+
+
+-z slice_size Download slice/block size, unit KB (default 16, max 128)
+
+ Sets the size of the basic unit of download. For greatest
+ compatibility with other peer clients, use the default. This
+ value can also affect the precision with which bandwidth is
+ managed.
+
+
+-n file_list Specify file number(s) to download
+
+ Specify a priority order for downloading files in the torrent.
+ A comma-separated list of file numbers and groups can be
+ specified; the file numbers can be seen with the -x option. The
+ client will preferentially request pieces of the
+ highest-priority files, requesting a piece from a
+ lower-priority group if a peer has no such pieces.
+ A group may consist of:
+
+ + a file number
+ + a range of file numbers (x-y)
+ + a combination of file numbers and ranges separated with plus
+ (+) signs
+ + an asterisk (*) or 3-dot ellipsis (...)
+
+ If an asterisk (remember to quote it on the command line!) or
+ ellipsis is used, the client will download and seed the
+ remainder of the torrent once the prioritized files are
+ completed; this is similar to the previous behavior of the
+ option. If no such specification is given, the client will
+ download and seed only the indicated files.
+ Examples:
+
+ -n 3
+ Download and seed only file 3.
+
+ -n 3+5+7,8-11
+ Download files 3, 5, and 7 simultaneously, then download
+ files 8 through 11 simultaneously, then stop downloading
+ and seed all downloaded files.
+
+ -n 3-4,...
+ Download files 3 and 4 simultaneously, then download and
+ seed all remaining content.
+
+
+-D rate Max bandwidth down (unit KB/s)
+
+ Specify a download bandwidth limit for this torrent. The client
+ will maintain its short-term average download rate at or below
+ this value.
+
+
+-U rate Max bandwidth up (unit KB/s)
+
+ Specify an upload bandwidth limit for this torrent. The client
+ will maintain its short-term average upload rate at or below
+ this value.
+
+
+-P peer_id Set Peer ID prefix. (default "-CD0301-")
+
+ Specify an alternate peer ID prefix. This can be useful if a
+ tracker is set up to only allow client programs that it
+ recognizes. (The admin may not even realize it, so you may want
+ to try contacting them to request that they change their
+ configuration or add Enhanced CheaTorrent to the list.) If you
+ receive a tracker warning message that your client is out of
+ date, try using this option with the prefix of another
+ well-known client program (such as "-AZ2304-").
+
+
+-A user_agent Set User-Agent header. (default "Enhanced-CheaTorrent/dnh3.1")
+
+ Specify an alternate user-agent header. This can be useful if a
+ tracker is set up to only allow client programs that it
+ recognizes.
+
+
+-S host:port Use CTCS server at host:port
+
+ Maintain a connection to CTCS for status reporting, bandwidth
+ control, and client management. Using a colon at the end of the
+ parameter (as in "-S localhost:2780:") will cause the client to
+ prompt for a password to send to CTCS when connecting.
+
+
+-a Preallocate files on disk
+
+ Use this if you are concerned about file fragmentation or
+ out-of-order block storage. This option is only effective when
+ initially creating the files and will cause startup to take
+ longer as each entire file is written in order to reserve
+ physical disk space. Note that all files will be created and
+ preallocated even if the "-n" option is used to download a
+ particular file.
+
+
+-T Convert foreign filenames to printable text
+
+ Substitutes a hex representation of any non-printable
+ characters in filenames; an underscore will be inserted between
+ any such sequences and regular text. This applies to printing
+ the name of the file as well as accessing it on disk, so you
+ need to use it (or not) consistently across multiple runs of
+ the same torrent. It does not apply to names specified with the
+ "-s" option.
+
+
+-X command Run command upon download completion ("user exit")
+
+ Specifies a "user exit" command to run upon download
+ completion. The string parameter will be passed to the sh shell
+ for execution; see the system() man page for further
+ clarification. You will need to quote this string on the
+ command line in order to identify it as a single parameter and
+ prevent special characters from being interpreted. Some
+ substitution sequences beginning with ampersand (&) are
+ available; note that it's a good idea to quote the sequence
+ within the string so that the substituted names will be quoted
+ in the final command.
+
+ + &d will be replaced by the name of the directory or filename
+ that contains the downloaded data.
+ + &t will be replaced by the name of the torrent metainfo file
+ (with path, if it was specified that way to cheatorrent).
+ + &w will be replaced by the client's working directory.
+
+ Note that the fork() and system() system/library functions are
+ used for best portability. As a result, significant extra
+ memory may be used while the specified command is running. Be
+ advised to use this feature as a trigger mechanism to update a
+ file or run a short script that kicks off a background task
+ rather than for executing a longer task directly.
+ This option can also be used together with -c as an automated
+ completion check. Normally the completion command will be run
+ only if data has been downloaded; this case is the exception.
+
+
+-d Daemon mode (fork to background)
+
+ The client will detach itself from the terminal session and
+ become a background process, closing stdin, stdout, and stderr.
+ There is no way to bring it back into the foreground of a
+ session later; if you want to monitor or manage the client then
+ either use the CTCS option (-S) as well or run the client under
+ [46]screen instead of using -d.
+ If this option is specified twice (-dd) then redirected
+ standard I/O descriptors will not be closed.
+ ___________________________________
+
+ Options for Creating a New Torrent
+
+
+-t Create a new torrent file
+
+ Indicates that you want to create a new torrent. This must be
+ the first option specified when creating a torrent.
+
+
+-s filename Specify metainfo file name
+
+ (Required) Give the name of the file to be created.
+
+
+-u URL Tracker's URL
+
+ (Required) Specify the tracker's announce URL. This usually
+ looks similar to "http://tracker.example.com:port/announce".
+
+
+-l piece_len Piece length (default 262144)
+
+ Specify the piece size for your torrent. This will also
+ determine the number of pieces in the torrent.
+
+
+-p Private (disable peer exchange)
+
+ Disable the use of DHT, PEX, or other trackerless peer-exchange
+ methods by other clients when sharing this torrent.
+
+
+-c comment Include a comment/description
+
+ Include a comment field in the torrent file.
+ _________________________________________________________________
+
+ Examples
+
+ List the contents of a torrent:
+
+cheatorrent -x example.torrent
+
+ Verify download completion status (takes a little time):
+
+cheatorrent -c example.torrent
+
+ Download or seed a torrent using default options:
+
+cheatorrent example.torrent
+
+ Download with a limit of 100KB/s, upload limit of 10KB/s, and seed
+ until a ratio of 1.5:1 is achieved:
+
+cheatorrent -D 100 -U 10 -E 1.5 example.torrent
+
+ Create a torrent:
+
+cheatorrent -t -u "http://tracker.example.com:6969/announce" -s example.torrent fi
+le_or_dir_to_upload
+ _________________________________________________________________
+
+ Runtime Commands
+
+ Several commands are available during upload/download; a list is
+ available by pressing ? or h:
+Available commands:
+ [Esc/0] Operator menu m[+/-] Adjust min peers count
+ d[+/-] Adjust download limit M[+/-] Adjust max peers count
+ u[+/-] Adjust upload limit C[+/-] Adjust max cache size
+ n Download specific file S Set/change CTCS server
+ e[+/-] Adjust seed exit time v Toggle verbose mode
+ E[+/-] Adjust seed exit ratio Q Quit
+ X Completion command
+
+ Command keys are case-sensitive. When a command key is pressed, a
+ prompt or current value is displayed. Prompts will suspend display of
+ the status line while waiting for input, though the client continues
+ to run normally. Toggle and numeric commands briefly suspend the
+ status line display.
+
+ Commands shown with [+/-] following the key are numeric options and
+ can be adjusted by pressing + or - repeatedly after the command key.
+ The increment is increased after five presses; to reset it, press the
+ command key again.
+
+ Most commands use the same letter as the corresponding command-line
+ option. Note that the bandwidth limit commands use the same letters
+ but opposite case.
+
+ Operator Menu
+
+ The 0 or Esc command key displays an operator menu with more advanced
+ (or less routine) options. All options on and beneath this menu
+ require pressing Enter to submit the input. Pressing Enter alone will
+ exit the menu.
+Operator Menu
+ Output Channels:
+ 1) Normal/status: stdout
+ 2) Interactive: stdout
+ 3) Error/warning: stderr
+ 4) Debug/verbose: stderr
+ 5) Input: stdin
+ Status Line Formats:
+ 6) \ 0/6/18 [700/700] 0MB,11127MB | 0,15K/s | 0,0K E:0,405
+ *7) | S:0/10 L:6/7 C:0 R=15.92 D=0 U=16 K/s seeding 48:57
+ Other options:
+ 8) View detailed status
+ 9) Pause (suspend upload/download)
+ 10) Become daemon (fork to background)
+ 11) Update tracker stats & get peers
+ 12) Restart (recover) the tracker session
+Enter selection:
+
+ The first set of options allow redirection of the client's various
+ types of console output (or even input--use carefully!). Of particular
+ use is the debug/verbose channel, which can be directed to a file to
+ create a debug log (be sure to also enable verbose output with the "v"
+ command key or CTCS).
+
+ The second set of options is used to select the status line format.
+ Since the actual client status is used to generate the menu options,
+ the operator menu display can also be used just to view the alternate
+ status information. An asterisk (*) indicates the currently selected
+ format.
+
+ The next two options provide a means to view more detailed current
+ status and statistics or to pause uploading and downloading (more or
+ less immediately, unlike the previous CTCS pause function).
+
+ Note that there is no "recovery" from daemon mode. Use CTCS (with
+ daemon mode) and/or "screen" if you want the client to run in the
+ background but need to manage or monitor it.
+
+ The next two options are the same as the corresponding actions in
+ CTCS. The first performs an early tracker update. The second restarts
+ the tracker session as if you had exited and restarted the client.
+ This can be used to recover if the tracker appears to have suffered a
+ failure and does not recognize your client session.
+ _________________________________________________________________
+
+ Usage Notes
+
+ Bandwidth Limits
+
+ You should always specify an upload bandwidth limit. With the most
+ recent changes in the program, this "option" is not just a limit to
+ stay under, but an advisement to the client as well. Enhanced CheaTorrent
+ now tunes its upload performance based on the limit. Without a limit,
+ the client has no idea how much bandwidth your line can support and so
+ cannot perform this tuning. It is now possible to achieve better
+ upload rates with a limit than without. Due to the tit-for-tat nature
+ of bittorrent, this can also indirectly increase your download
+ performance. If you just want the client to use as much upload
+ bandwidth as possible, then choose a limit that is 10% or so less than
+ the available upload capacity of your line. ("Available" means not
+ typically in use by other applications.)
+
+ Note that limits are specified in KB/s (kilobytes per second), where
+ 1KB = 1024 bytes (8192 bits). Your ISP likely measures in "kilobits"
+ (Kb, where 1Kb = 1000 bits or 125 bytes) or "megabits" (1Mb = 1000000
+ bits or 122KB). Some of that [to the tune of 20% in some cases] is
+ used by the line protocol and thus not available to you at all.
+
+ Startup
+
+ If you have previously started the torrent, CheaTorrent will perform a
+ hash-check of all pieces (or pieces indicated by the bitfield file if
+ present) while beginning the upload/download process. This does not
+ mean that it is starting over--quite the opposite! This is how the
+ client determines which pieces it already has so that they will not be
+ downloaded again (and can be offered for uploading). This process
+ confirms the pieces that you have even if the files have been altered
+ or recovered after a system crash.
+
+ Status Line
+
+ The status line that is output by the client has changed since the
+ original and deserves some explanation.
+
+ / 0/33/110 [672/672] 0MB,1130MB | 0,20K/s | 0,0K P:4/10
+ - - -- --- --- --- --- ------ - -- - - ----
+ A B C D E F H I J K L M P
+
+ A: Ticker; this character changes to indicate that the client is
+ running.
+ B: Number of seeders (complete peers) to which you are connected.
+ C: Number of leechers (incomplete peers) to which you are connected.
+ D: Total number of peers in the swarm, as last reported by the
+ tracker.
+ E: Number of pieces of the torrent that you have completed.
+ F: Total number of pieces in the torrent.
+ peers.
+ H: Total amount of data you have downloaded.
+ I: Total amount of data you have uploaded.
+ J: Your current download rate (20 second average).
+ K: Your current upload rate (20 second average).
+ L: Amount of data downloaded since the last status line update.
+ M: Amount of data uploaded since the last status line update.
+ P: Completion ratio of current fileset (when -n is used).
+
+ Additional information such as tracker connection status may be
+ displayed at the end of the status line when appropriate.
+
+ Alternate Status Line
+
+ A new status line format is also available via the operator menu.
+
+ / S:4/8 L:4/5 C:1 R=5.85 D=42 U=16 K/s 79/100% 49:47 P:40/100% 2:41
+ - - - - - - ---- -- -- -- ---- ----- ------- ----
+ A B C D E F G H I J K L M N
+
+ A: Ticker; this character changes to indicate that the client is
+ running.
+ B: Number of seeders (complete peers) to which you are connected.
+ C: Number of seeders in the swarm (excluding yourself), as last
+ reported by the tracker.
+ D: Number of leechers (incomplete peers) to which you are connected.
+ E: Number of leechers in the swarm (excluding yourself), as last
+ reported by the tracker.
+ F: Number of peer connection attempts in progress.
+ G: Your upload/download ratio.
+ H: Your current download rate (20 second average).
+ I: Your current upload rate (20 second average).
+ J: Percent of the torrent that you have completed.
+ K: Percent of the torrent currently available from you and your
+ connected peers.
+ If you have the complete torrent, "seeding" is displayed instead
+ of these percentages.
+ L: Estimated download or seed time remaining, in hours and minutes.
+ M: Completion and availability of current fileset (when -n is used).
+ N: Time remaining to complete the current fileset (when -n is used).
+
+ Additional information such as tracker connection status may be
+ displayed at the end of the status line when appropriate.
+
+ Stopping CheaTorrent
+
+ Besides the Q command key (equivalent to Ctrl-C but a nicer user
+ interface), CheaTorrent can be stopped before completing download or
+ seeding by pressing Ctrl-C or sending the TERM signal ("kill pid").
+ This will tell the client to contact the tracker to send its final
+ statistics and advise that it is leaving the torrent. Note that this
+ could take a couple of minutes if the tracker is down or very busy.
+ (Only one attempt is made, so the client will exit even if the
+ connection fails.)
+
+ If Ctrl-C or kill is used a second time, the client closes all peer
+ connections and exits without waiting for the tracker connection. This
+ means that other peers may still attempt to contact you for a while,
+ and the tracker may not accept you back into the torrent until your
+ original session expires. (This could take up to a couple of hours,
+ depending on the tracker.)
+
+ In either case, this is a clean shutdown of CheaTorrent. All downloaded
+ data is written to disk before exiting. (Though only complete pieces
+ really count if the torrent is restarted, as there is no way to know
+ which blocks are missing from partial pieces.)
+ _________________________________________________________________
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..64fd963
--- a/dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1020 @@
+# generated automatically by aclocal 1.9.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+# 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.
+
+# -*- Autoconf -*-
+# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+# Generated from amversion.in; do not edit by hand.
+
+# 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
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+ [AM_AUTOMAKE_VERSION([1.9.1])])
+
+# AM_AUX_DIR_EXPAND
+
+# Copyright (C) 2001, 2003 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.
+
+# 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],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004 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.
+
+# serial 6
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# serial 7 -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+# 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.
+
+
+# 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", "GCJ", 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
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/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=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --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])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+# 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.
+
+#serial 2
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. 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 "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/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=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. 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_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# 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.
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+# 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.
+
+# serial 11
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# 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_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [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
+])
+])
+
+
+# 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. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $1 | $1:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+
+# Copyright (C) 2001, 2003 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.
+
+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)])
+
+# -*- Autoconf -*-
+# Copyright (C) 2003 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.
+
+# serial 1
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003 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.
+
+# serial 2
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+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 | grep -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
+])
+
+# -*- Autoconf -*-
+
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003 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.
+
+# serial 3
+
+# 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=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+
+# Copyright (C) 2003, 2004 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.
+
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake. There are at least two reasons why we must not
+# use `-m 0755':
+# - it causes special bits like SGID to be ignored,
+# - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out. Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003 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.
+
+# serial 2
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003 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.
+
+# 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)])
+
+# AM_PROG_INSTALL_STRIP
+
+# Copyright (C) 2001, 2003 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.
+
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004 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.
+
+# serial 1
+
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/bencode.cpp b/bencode.cpp
new file mode 100644
index 0000000..5143b19
--- a/dev/null
+++ b/bencode.cpp
@@ -0,0 +1,255 @@
+#include "./def.h"
+
+#include "bencode.h"
+
+#ifndef WINDOWS
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <limits.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef HAVE_SNPRINTF
+#include "compat.h"
+#endif
+
+static const char* next_key(const char *keylist)
+{
+ for(;*keylist && *keylist != KEY_SP; keylist++);
+ if(*keylist) keylist++;
+ return keylist;
+}
+
+static size_t compare_key(const char *key,size_t keylen,const char *keylist)
+{
+ for(;keylen && *keylist && *key==*keylist;keylen--,key++,keylist++) ;
+ if(!keylen) if(*keylist && *keylist!=KEY_SP) return 1;
+ return keylen;
+}
+
+size_t buf_long(const char *b,size_t len,char beginchar,char endchar,int64_t *pi)
+{
+ const char *p = b;
+ const char *psave;
+
+ if(2 > len) return 0; /* buffer too small */
+
+ if( beginchar ){
+ if(*p != beginchar) return 0;
+ p++; len--;
+ }
+
+ for(psave = p; len && isdigit(*p); p++,len--) ;
+
+ if(!len || MAX_INT_SIZ < (p - psave) || *p != endchar) return 0;
+
+ if( pi ){
+ if( beginchar ) *pi = strtoll(b + 1,(char**) 0,10);
+ else *pi=strtoll(b,(char**) 0,10);
+ }
+ return (size_t)( p - b + 1 );
+}
+
+size_t buf_int(const char *b,size_t len,char beginchar,char endchar,size_t *pi)
+{
+ size_t r;
+
+ if( pi ){
+ int64_t pl;
+ r = buf_long(b,len,beginchar,endchar,&pl);
+ *pi = (size_t) pl;
+ }else{
+ r = buf_long(b,len,beginchar,endchar,(int64_t*) 0);
+ }
+ return r;
+}
+
+size_t buf_str(const char *b,size_t len,const char **pstr,size_t* slen)
+{
+ size_t rl,sl;
+
+ rl = buf_int(b,len,0,':',&sl);
+
+ if( !rl ) return 0;
+
+ if(len < rl + sl) return 0;
+ if(pstr) *pstr = b + rl;
+ if(slen) *slen = sl;
+
+ return( rl + sl );
+}
+
+size_t decode_int(const char *b,size_t len)
+{
+ return(buf_long(b,len,'i','e',(int64_t*) 0));
+}
+
+size_t decode_str(const char *b,size_t len)
+{
+ return (buf_str(b,len,(const char**) 0,(size_t*) 0));
+}
+
+size_t decode_dict(const char *b,size_t len,const char *keylist)
+{
+ size_t rl,dl,nl;
+ const char *pkey;
+ dl = 0;
+ if(2 > len || *b != 'd') return 0;
+
+ dl++; len--;
+ for(;len && *(b + dl) != 'e';){
+ rl = buf_str(b + dl,len,&pkey,&nl);
+
+ if( !rl || KEYNAME_SIZ < nl) return 0;
+ dl += rl;
+ len -= rl;
+
+ if(keylist && compare_key(pkey,nl,keylist) == 0){
+ pkey = next_key(keylist);
+ if(! *pkey ) return dl;
+ rl = decode_dict(b + dl,len, pkey);
+ if( !rl ) return 0;
+ return dl + rl;
+ }
+
+ rl = decode_rev(b + dl,len,(const char*) 0);
+ if( !rl ) return 0;
+
+ dl += rl;len -= rl;
+ }
+ if( !len || keylist) return 0;
+ return dl + 1; /* add the last char 'e' */
+}
+
+size_t decode_list(const char *b,size_t len,const char *keylist)
+{
+ size_t ll,rl;
+ ll = 0;
+ if(2 > len || *b != 'l') return 0;
+ len--; ll++;
+ for(;len && *(b + ll) != 'e';){
+ rl = decode_rev(b + ll,len,keylist);
+ if( !rl ) return 0;
+
+ ll += rl; len -= rl;
+ }
+ if( !len ) return 0;
+ return ll + 1; /* add last char 'e' */
+}
+
+size_t decode_rev(const char *b,size_t len,const char *keylist)
+{
+ if( !b ) return 0;
+ switch( *b ){
+ case 'i': return decode_int(b,len);
+ case 'd': return decode_dict(b,len,keylist);
+ case 'l': return decode_list(b,len,keylist);
+ default: return decode_str(b,len);
+ }
+}
+
+size_t decode_query(const char *b,size_t len,const char *keylist,const char **ps,size_t *pi,int64_t *pl,int method)
+{
+ size_t pos;
+ char kl[KEYNAME_LISTSIZ];
+ strcpy(kl,keylist);
+ pos = decode_rev(b, len, kl);
+ if( !pos ) return 0;
+ switch(method){
+ case QUERY_STR: return(buf_str(b + pos,len - pos, ps, pi));
+ case QUERY_INT: return(buf_int(b + pos,len - pos, 'i', 'e', pi));
+ case QUERY_POS:
+ if(pi) *pi = decode_rev(b + pos, len - pos, (const char*) 0);
+ return pos;
+ case QUERY_LONG: return(buf_long(b + pos,len - pos, 'i', 'e', pl));
+ default: return 0;
+ }
+}
+
+size_t bencode_buf(const char *buf,size_t len,FILE *fp)
+{
+ char slen[MAX_INT_SIZ];
+
+ if( MAX_INT_SIZ <= snprintf(slen, MAX_INT_SIZ, "%d:", (int)len) ) return 0;
+ if( fwrite( slen, strlen(slen), 1, fp) != 1) return 0;
+ if( fwrite(buf, len, 1, fp) != 1 ) return 0;
+ return 1;
+}
+
+size_t bencode_str(const char *str, FILE *fp)
+{
+ return bencode_buf(str, strlen(str), fp);
+}
+
+size_t bencode_int(const uint64_t integer, FILE *fp)
+{
+ char buf[MAX_INT_SIZ];
+ if( EOF == fputc('i', fp)) return 0;
+ if( MAX_INT_SIZ <=
+ snprintf(buf, MAX_INT_SIZ, "%llu", (unsigned long long)integer) )
+ return 0;
+ if( fwrite(buf, strlen(buf), 1, fp) != 1 ) return 0;
+ return (EOF == fputc('e', fp)) ? 0: 1;
+}
+
+size_t bencode_begin_dict(FILE *fp)
+{
+ return (EOF == fputc('d',fp)) ? 0 : 1;
+}
+
+size_t bencode_begin_list(FILE *fp)
+{
+ return (EOF == fputc('l',fp)) ? 0 : 1;
+}
+
+size_t bencode_end_dict_list(FILE *fp)
+{
+ return (EOF == fputc('e',fp)) ? 0 : 1;
+}
+
+size_t bencode_path2list(const char *pathname, FILE *fp)
+{
+ const char *pn;
+ const char *p = pathname;
+
+ if( bencode_begin_list(fp) != 1 ) return 0;
+
+ for(; *p;){
+ pn = strchr(p, PATH_SP);
+ if( pn ){
+ if( bencode_buf(p, pn - p, fp) != 1) return 0;
+ p = pn + 1;
+ }else{
+ if( bencode_str(p, fp) != 1) return 0;
+ break;
+ }
+ }
+
+ return bencode_end_dict_list(fp);
+}
+
+size_t decode_list2path(const char *b, size_t n, char *pathname)
+{
+ const char *pb = b;
+ const char *s = (char *) 0;
+ size_t r,q;
+
+ if( 'l' != *pb ) return 0;
+ pb++;
+ n--;
+ if( !n ) return 0;
+ for(; n;){
+ if(!(r = buf_str(pb, n, &s, &q)) ) return 0;
+ memcpy(pathname, s, q);
+ pathname += q;
+ pb += r; n -= r;
+ if( 'e' != *pb ){*pathname = PATH_SP, pathname++;} else break;
+ }
+ *pathname = '\0';
+ return (pb - b + 1);
+}
diff --git a/bencode.h b/bencode.h
new file mode 100644
index 0000000..c728285
--- a/dev/null
+++ b/bencode.h
@@ -0,0 +1,37 @@
+#ifndef BENCODE_H
+#define BENCODE_H
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+#define KEY_SP '|' //the keyname list's delimiters
+#define KEYNAME_SIZ 32
+#define KEYNAME_LISTSIZ 256
+
+#define MAX_INT_SIZ 64
+
+#define QUERY_STR 0
+#define QUERY_INT 1
+#define QUERY_POS 2
+#define QUERY_LONG 3
+
+size_t buf_long(const char *b,size_t len,char beginchar,char endchar,int64_t *pi);
+size_t buf_int(const char *b,size_t len,char beginchar,char endchar,size_t *pi);
+size_t buf_str(const char *b,size_t len,const char **pstr,size_t* slen);
+size_t decode_int(const char *b,size_t len);
+size_t decode_str(const char *b,size_t len);
+size_t decode_dict(const char *b,size_t len,const char *keylist);
+size_t decode_list(const char *b,size_t len,const char *keylist);
+size_t decode_rev(const char *b,size_t len,const char *keylist);
+size_t decode_query(const char *b,size_t len,const char *keylist,const char **ps,size_t *pi,int64_t *pl,int method);
+size_t decode_list2path(const char *b, size_t n, char *pathname);
+size_t bencode_buf(const char *str,size_t len,FILE *fp);
+size_t bencode_str(const char *str, FILE *fp);
+size_t bencode_int(const uint64_t integer, FILE *fp);
+size_t bencode_begin_dict(FILE *fp);
+size_t bencode_begin_list(FILE *fp);
+size_t bencode_end_dict_list(FILE *fp);
+size_t bencode_path2list(const char *pathname, FILE *fp);
+
+#endif
diff --git a/bencode.o b/bencode.o
new file mode 100644
index 0000000..aeac7e2
--- a/dev/null
+++ b/bencode.o
Binary files differ
diff --git a/bitfield.cpp b/bitfield.cpp
new file mode 100644
index 0000000..8def167
--- a/dev/null
+++ b/bitfield.cpp
@@ -0,0 +1,365 @@
+#include "config.h"
+#include "bitfield.h"
+
+#ifdef WINDOWS
+#include <io.h>
+#include <memory.h>
+#else
+#include <unistd.h>
+#include <sys/param.h>
+#endif
+
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef HAVE_RANDOM
+#include "compat.h"
+#endif
+
+const unsigned char BIT_HEX[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
+
+#define _isset(idx) (b[(idx) / 8 ] & BIT_HEX[(idx) % 8])
+#define _isempty() (nset == 0)
+#define _isempty_sp(sp) ((sp).nset == 0)
+#define _isfull() (nset >= nbits)
+#define _isfull_sp(sp) ((sp).nset >= nbits)
+
+size_t BitField::nbytes = 0;
+size_t BitField::nbits = 0;
+
+BitField::BitField()
+{
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+
+ memset(b, 0, nbytes);
+ nset = 0;
+}
+
+BitField::BitField(size_t npcs)
+{
+ nbits = npcs;
+ nbytes = nbits / 8;
+ if( nbits % 8 ) nbytes++;
+
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+
+ memset(b, 0, nbytes);
+ nset = 0;
+}
+
+BitField::BitField(const BitField &bf)
+{
+ nset = bf.nset;
+ if( _isfull_sp(bf) ) b = (unsigned char *) 0;
+ else{
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ memcpy(b, bf.b, nbytes);
+ }
+}
+
+void BitField::operator=(const BitField &bf)
+{
+ nset = bf.nset;
+ if( _isfull_sp(bf) ){
+ if( b ) { delete []b; b = (unsigned char*) 0; }
+ }else{
+ if( !b ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ }
+ memcpy(b, bf.b, nbytes);
+ }
+}
+
+// _set() sets the bit but doesn't increment nset or set the isfull case.
+// Use instead of Set() when you know nset is incorrect and will be corrected
+// afterward (as in Invert or by _recalc),
+// and either bitfield won't get full or you'll _recalc() afterward to fix it.
+inline void BitField::_set(size_t idx)
+{
+ if( idx < nbits && !_isfull() && !_isset(idx) )
+ b[idx / 8] |= BIT_HEX[idx % 8];
+}
+
+inline void BitField::_setall(unsigned char *buf)
+{
+ size_t i;
+
+ memset(buf,0xFF,nbytes - 1);
+
+ if( nbits % 8 ){
+ buf[nbytes - 1] = ~(BIT_HEX[nbits % 8 - 1] - 1);
+ }else
+ buf[nbytes - 1] = (unsigned char) 0xFF;
+}
+
+inline void BitField::_recalc()
+{
+ // 重新计算 nset 的值
+ static unsigned char BITS[256] = {0xff};
+ size_t i;
+
+ if( BITS[0] ){ // initialize bitcounts
+ size_t j, exp, x;
+ BITS[0] = 0;
+ x = 0;
+ for(i=0; i<8; i++){
+ exp = 1<<i;
+ for(j=0; j < exp; j++)
+ BITS[++x] = BITS[j] + 1;
+ }
+ }
+
+ for(nset = 0, i = 0; i < nbytes; i++)
+ nset += BITS[b[i]];
+ if( _isfull() && b ){ delete []b; b = (unsigned char*) 0;}
+}
+
+void BitField::SetAll()
+{
+ if( b ){
+ delete []b;
+ b = (unsigned char*) 0;
+ }
+ nset = nbits;
+}
+
+void BitField::Clear()
+{
+ if( _isfull() ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ }
+ memset(b, 0, nbytes);
+ nset = 0;
+}
+
+int BitField::IsSet(size_t idx) const
+{
+ if( idx >= nbits ) return 0;
+ return _isfull() ? 1 : _isset(idx);
+}
+
+void BitField::Set(size_t idx)
+{
+ if(idx >= nbits) return;
+
+ if( !_isfull() && !_isset(idx) ){
+ b[idx / 8] |= BIT_HEX[idx % 8];
+ nset++;
+ if( _isfull() && b){ delete []b; b = (unsigned char*) 0;}
+ }
+}
+
+void BitField::UnSet(size_t idx)
+{
+ if( idx >= nbits ) return;
+
+ if( _isfull() ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ _setall(b);
+ b[idx / 8] &= (~BIT_HEX[idx % 8]);
+ nset = nbits - 1;
+ }else{
+ if( _isset(idx) ){
+ b[idx / 8] &= (~BIT_HEX[idx % 8]);
+ nset--;
+ }
+ }
+}
+
+void BitField::Invert()
+{
+ if( _isempty() ){
+ SetAll();
+ }else if( _isfull() ){
+ Clear();
+ }else{
+ size_t i = 0;
+ size_t s = nset;
+ for( ; i < nbytes - 1; i++ ) b[i] = ~b[i];
+
+ if( nbits % 8 ){
+ for( i = 8 * (nbytes - 1); i < nbits; i++ ){
+ if( _isset(i) ) UnSet(i);
+ else _set(i);
+ }
+ }else b[nbytes - 1] = ~b[nbytes - 1];
+
+ nset = nbits - s;
+ }
+}
+
+// Combine (Logical "OR")
+void BitField::Comb(const BitField &bf)
+{
+ size_t i;
+ if( !_isempty_sp(bf) && !_isfull() ){
+ if( _isfull_sp(bf) ){
+ SetAll();
+ }else if( _isempty() ){
+ memcpy(b, bf.b, nbytes);
+ nset = bf.nset;
+ }else{
+ for(i = 0; i < nbytes; i++) b[i] |= bf.b[i];
+ _recalc();
+ }
+ }
+}
+
+void BitField::Except(const BitField &bf)
+{
+ size_t i;
+
+ if( !_isempty_sp(bf) && !_isempty() ){
+ if( _isfull_sp(bf) ){
+ Clear();
+ }else{
+ if( _isfull() ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ _setall(b);
+ }
+ for(i = 0; i < nbytes; i++) b[i] &= ~bf.b[i];
+ _recalc();
+ }
+ }
+}
+
+void BitField::And(const BitField &bf)
+{
+ size_t i;
+
+ if( !_isfull_sp(bf) && !_isempty() ){
+ if( _isempty_sp(bf) ){
+ Clear();
+ }else{
+ if( _isfull() ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ memcpy(b, bf.b, nbytes);
+ nset = bf.nset;
+ }else{
+ for(i = 0; i < nbytes; i++) b[i] &= bf.b[i];
+ _recalc();
+ }
+ }
+ }
+}
+
+size_t BitField::Random() const
+{
+ size_t idx;
+
+ if( _isfull() ) idx = random() % nbits;
+ else{
+ size_t i;
+ i = random() % nset + 1;
+ for(idx = 0; idx < nbits && i; idx++)
+ if( _isset(idx) ) i--;
+ idx--;
+ }
+ return idx;
+}
+
+void BitField::SetReferBuffer(char *buf)
+{
+ if( !b ){
+ b = new unsigned char[nbytes];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ }
+ memcpy((char*)b,buf,nbytes);
+ if( nbits % 8 )
+ b[nbytes - 1] &= ~(BIT_HEX[nbits % 8 - 1] - 1);
+ _recalc();
+}
+
+void BitField::WriteToBuffer(char *buf)
+{
+ if(_isfull())
+ _setall((unsigned char*)buf);
+ else
+ memcpy(buf,(char*)b,nbytes);
+}
+
+int BitField::SetReferFile(const char *fname)
+{
+ FILE *fp;
+ struct stat sb;
+ char *bitbuf = (char*) 0;
+
+ if(stat(fname, &sb) < 0) return -1;
+ if( sb.st_size != nbytes ) return -1;
+
+ fp = fopen(fname, "r");
+ if( !fp ) return -1;
+
+ bitbuf = new char[nbytes];
+#ifndef WINDOWS
+ if( !bitbuf ) goto fclose_err;
+#endif
+
+ if( fread(bitbuf, nbytes, 1, fp) != 1 ) goto fclose_err;
+
+ fclose(fp);
+
+ SetReferBuffer(bitbuf);
+
+ delete []bitbuf;
+ return 0;
+ fclose_err:
+ if( bitbuf ) delete []bitbuf;
+ fclose(fp);
+ return -1;
+}
+
+int BitField::WriteToFile(const char *fname)
+{
+ FILE *fp;
+ char *bitbuf = (char*) 0;
+
+ fp = fopen(fname, "w");
+ if( !fp ) return -1;
+
+ bitbuf = new char[nbytes];
+#ifndef WINDOWS
+ if( !bitbuf ) goto fclose_err;
+#endif
+
+ WriteToBuffer(bitbuf);
+
+ if( fwrite(bitbuf, nbytes, 1, fp) != 1 ) goto fclose_err;
+
+ delete []bitbuf;
+ fclose(fp);
+ return 0;
+ fclose_err:
+ if( bitbuf ) delete []bitbuf;
+ fclose(fp);
+ return -1;
+}
+
diff --git a/bitfield.h b/bitfield.h
new file mode 100644
index 0000000..477046c
--- a/dev/null
+++ b/bitfield.h
@@ -0,0 +1,55 @@
+#ifndef BITFIELD_H
+#define BITFIELD_H
+
+#include <sys/types.h>
+
+class BitField
+{
+ private:
+ static size_t nbits;
+ static size_t nbytes;
+
+ unsigned char *b;
+ size_t nset;
+
+ void _recalc();
+ void _setall(unsigned char* buf);
+ void _set(size_t idx);
+
+ public:
+ BitField();
+ BitField(size_t n_bits);
+ BitField(const BitField &bf);
+ ~BitField(){ if(b) delete []b; }
+
+ void operator=(const BitField &bf);
+
+ void SetAll();
+ void Clear();
+ void Set(size_t idx);
+ void UnSet(size_t idx);
+
+ int IsSet(size_t idx) const;
+ int IsFull() const { return (nset >= nbits) ? 1 : 0; }
+ int IsEmpty() const { return (nset == 0) ? 1 : 0; }
+
+ size_t Count() const { return nset;}
+ size_t NBytes() const { return nbytes; }
+ size_t NBits() const { return nbits; }
+ size_t Random() const;
+
+ void Comb(const BitField &bf);
+ void Comb(const BitField *pbf) { if(pbf) Comb(*pbf); }
+ void Except(const BitField &bf);
+ void Except(const BitField *pbf) { if(pbf) Except(*pbf); }
+ void And(const BitField &bf);
+ void And(const BitField *pbf) { if(pbf) And(*pbf); }
+ void Invert();
+
+ void SetReferBuffer(char *buf);
+ void WriteToBuffer(char *buf);
+ int SetReferFile(const char *fname);
+ int WriteToFile(const char *fname);
+};
+
+#endif
diff --git a/bitfield.o b/bitfield.o
new file mode 100644
index 0000000..6e95632
--- a/dev/null
+++ b/bitfield.o
Binary files differ
diff --git a/btconfig.cpp b/btconfig.cpp
new file mode 100644
index 0000000..e01301e
--- a/dev/null
+++ b/btconfig.cpp
@@ -0,0 +1,49 @@
+#include <sys/types.h>
+#include "btconfig.h"
+
+size_t cfg_req_slice_size = DEFAULT_SLICE_SIZE;
+size_t cfg_req_queue_length = 74;
+
+size_t cfg_cache_size = 16;
+
+size_t cfg_max_peers = 100;
+size_t cfg_min_peers = 1;
+
+unsigned long cfg_listen_ip = 0;
+int cfg_listen_port = 0;
+int cfg_max_listen_port = 2706;
+int cfg_min_listen_port = 2106;
+char *cfg_public_ip = (char *) 0;
+
+int cfg_max_bandwidth_down = 0;
+int cfg_max_bandwidth_up = 0;
+
+time_t cfg_seed_hours = 72;
+double cfg_seed_ratio = 0;
+
+// arguments global value
+char *arg_metainfo_file = (char*) 0;
+char *arg_bitfield_file = (char*) 0;
+char *arg_save_as = (char*) 0;
+char *arg_user_agent = (char*) 0;
+
+unsigned char arg_flg_force_seed_mode = 0;
+unsigned char arg_flg_check_only = 0;
+unsigned char arg_flg_exam_only = 0;
+unsigned char arg_flg_make_torrent = 0;
+unsigned char arg_flg_private = 0;
+unsigned char arg_flg_convert_filenames = 0;
+char *arg_file_to_download = (char *)0;
+unsigned char arg_verbose = 0;
+unsigned char arg_allocate = 0;
+unsigned char arg_daemon = 0;
+
+size_t arg_piece_length = 262144;
+char *arg_announce = (char*) 0;
+char *arg_comment = (char*) 0;
+
+char *arg_ctcs = (char*) 0;
+char *arg_completion_exit = (char*) 0;
+
+char *cfg_user_agent = (char*) 0;
+
diff --git a/btconfig.h b/btconfig.h
new file mode 100644
index 0000000..7c4aa66
--- a/dev/null
+++ b/btconfig.h
@@ -0,0 +1,60 @@
+#ifndef BTCONFIG_H
+#define BTCONFIG_H
+
+#include <time.h>
+
+extern size_t cfg_req_slice_size;
+
+#define MAX_METAINFO_FILESIZ (4*1024*1024)
+#define DEFAULT_SLICE_SIZE (16*1024)
+// According to specs the max slice size is 128K. While most clients now do
+// not accept a value that large, we want max compatibility.
+#define cfg_max_slice_size (128*1024)
+extern size_t cfg_req_queue_length;
+#define MAX_PF_LEN 8
+#define PEER_ID_LEN 20
+#define PEER_PFX "-CD0303-"
+
+extern char *cfg_user_agent; // HTTP header
+
+extern size_t cfg_cache_size;
+
+extern size_t cfg_max_peers;
+extern size_t cfg_min_peers;
+
+extern unsigned long cfg_listen_ip;
+extern int cfg_listen_port;
+extern int cfg_max_listen_port;
+extern int cfg_min_listen_port;
+extern char *cfg_public_ip;
+
+extern time_t cfg_seed_hours;
+extern double cfg_seed_ratio;
+
+extern int cfg_max_bandwidth_down;
+extern int cfg_max_bandwidth_up;
+
+// arguments global value
+extern char *arg_metainfo_file;
+extern char *arg_bitfield_file;
+extern char *arg_save_as;
+extern char *arg_user_agent; // BT peer ID, not HTTP header
+
+extern unsigned char arg_flg_force_seed_mode;
+extern unsigned char arg_flg_check_only;
+extern unsigned char arg_flg_exam_only;
+extern unsigned char arg_flg_make_torrent;
+extern unsigned char arg_flg_private;
+extern unsigned char arg_flg_convert_filenames;
+extern char *arg_file_to_download;
+extern unsigned char arg_verbose;
+extern unsigned char arg_allocate;
+extern unsigned char arg_daemon;
+
+extern size_t arg_piece_length;
+extern char *arg_announce;
+extern char *arg_comment;
+
+extern char *arg_ctcs;
+extern char *arg_completion_exit;
+#endif
diff --git a/btconfig.o b/btconfig.o
new file mode 100644
index 0000000..70ed561
--- a/dev/null
+++ b/btconfig.o
Binary files differ
diff --git a/btcontent.cpp b/btcontent.cpp
new file mode 100644
index 0000000..1f5a02a
--- a/dev/null
+++ b/btcontent.cpp
@@ -0,0 +1,1619 @@
+#include "btcontent.h"
+
+#ifdef WINDOWS
+#include <direct.h>
+#include <io.h>
+#include <memory.h>
+// include windows sha1 header here.
+
+#else
+#include <unistd.h>
+#include <sys/param.h>
+
+#if defined(USE_STANDALONE_SHA1)
+#include "sha1.h"
+#elif defined(HAVE_OPENSSL_SHA_H)
+#include <openssl/sha.h>
+#elif defined(HAVE_SSL_SHA_H)
+#include <ssl/sha.h>
+#elif defined(HAVE_SHA_H)
+#include <sha.h>
+#endif
+
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "btconfig.h"
+#include "bencode.h"
+#include "peer.h"
+#include "httpencode.h"
+#include "tracker.h"
+#include "peerlist.h"
+#include "ctcs.h"
+#include "console.h"
+#include "bttime.h"
+
+#ifndef HAVE_RANDOM
+#include "compat.h"
+#endif
+
+#define meta_str(keylist,pstr,pint) decode_query(b,flen,(keylist),(pstr),(pint),(int64_t*) 0,QUERY_STR)
+#define meta_int(keylist,pint) decode_query(b,flen,(keylist),(const char**) 0,(pint),(int64_t*) 0,QUERY_INT)
+#define meta_pos(keylist) decode_query(b,flen,(keylist),(const char**) 0,(size_t*) 0,(int64_t*) 0,QUERY_POS)
+
+// Does "ca" overlap the data that lies from roff to rlen?
+#define CACHE_FIT(ca,roff,rlen) \
+(max_uint64_t((ca)->bc_off,(roff)) <= \
+ min_uint64_t(((ca)->bc_off + (ca)->bc_len - 1),(roff + rlen - 1)))
+
+
+btContent BTCONTENT;
+
+static void Sha1(char *ptr,size_t len,unsigned char *dm)
+{
+#if defined(USE_STANDALONE_SHA1)
+ SHA1_CTX context;
+ SHA1Init(&context);
+ SHA1Update(&context,(unsigned char*)ptr,len);
+ SHA1Final(dm,&context);
+#else
+#ifdef WINDOWS
+ ;
+#else
+ SHA_CTX context;
+ SHA1_Init(&context);
+ SHA1_Update(&context,(unsigned char*)ptr,len);
+ SHA1_Final(dm,&context);
+#endif
+#endif
+}
+
+btContent::btContent()
+{
+ m_announce = global_piece_buffer = (char*) 0;
+ global_buffer_size = 0;
+ memset(m_announcelist, 0, 9*sizeof(char *));
+ m_hash_table = (unsigned char *) 0;
+ m_create_date = m_seed_timestamp = (time_t) 0;
+ m_private = 0;
+ m_comment = m_created_by = (char *)0;
+
+ pBF = (BitField*) 0;
+ pBMasterFilter = (BitField*) 0;
+ pBRefer = (BitField*) 0;
+ pBChecked = (BitField*) 0;
+ pBMultPeer = (BitField*) 0;
+ time(&m_start_timestamp);
+ m_cache_oldest = m_cache_newest = (BTCACHE *)0;
+ m_cache_size = m_cache_used = 0;
+ m_flush_failed = m_flush_tried = (time_t) 0;
+ m_check_piece = 0;
+ m_flushq = (BTFLUSH *)0;
+ m_filters = m_current_filter = (BFNODE *)0;
+ m_prevdlrate = 0;
+}
+
+int btContent::CreateMetainfoFile(const char *mifn)
+{
+ FILE *fp;
+ fp = fopen(mifn, "r");
+ if( fp ){
+ CONSOLE.Warning(1, "error, file \"%s\" already exists.", mifn);
+ return -1;
+ }else if( ENOENT != errno ){
+ CONSOLE.Warning(1, "error, couldn't create \"%s\".", mifn);
+ return -1;
+ }
+
+ fp = fopen(mifn, "w");
+
+ if( !fp ){
+ CONSOLE.Warning(1, "error, open \"%s\" failed: %s", mifn, strerror(errno));
+ return -1;
+ }
+ if( bencode_begin_dict(fp) != 1 ) goto err;
+
+ // Entries in dictionary must be sorted by key!
+
+ // announce
+ if( bencode_str("announce", fp) != 1 ) goto err;
+ if( bencode_str(m_announce, fp) != 1 ) goto err;
+
+ // comment
+ if( arg_comment ){
+ if( bencode_str("comment", fp) != 1 ) goto err;
+ if( bencode_str(arg_comment, fp) != 1 ) goto err;
+ }
+
+ // created by
+ if( bencode_str("created by", fp) != 1 ) goto err;
+ if( bencode_str(cfg_user_agent, fp) != 1 ) goto err;
+
+ // creation date
+ if( bencode_str("creation date", fp) != 1 ) goto err;
+ if( bencode_int(m_create_date, fp) != 1 ) goto err;
+
+ // info dict
+ if( bencode_str("info", fp) != 1 ) goto err;
+ if( bencode_begin_dict(fp) != 1 ) goto err;
+
+ { // Entries in dictionary must be sorted by key!
+ // files & name, or length & name
+ if( m_btfiles.FillMetaInfo(fp) != 1 ) goto err;
+
+ // piece length
+ if( bencode_str("piece length", fp) != 1 ) goto err;
+ if( bencode_int(m_piece_length, fp) != 1 ) goto err;
+
+ // pieces (hash table)
+ if( bencode_str("pieces", fp) != 1 ) goto err;
+ if( bencode_buf((const char*) m_hash_table, m_hashtable_length, fp) != 1 )
+ goto err;
+
+ // private
+ if( arg_flg_private ){
+ if( bencode_str("private", fp) != 1 ) goto err;
+ if( bencode_int(1, fp) != 1 ) goto err;
+ }
+
+ if( bencode_end_dict_list(fp) != 1 ) goto err; // end info
+ }
+
+ if( bencode_end_dict_list(fp) != 1 ) goto err; // end torrent
+
+ fclose(fp);
+ return 0;
+ err:
+ if( fp ) fclose(fp);
+ return -1;
+}
+
+int btContent::InitialFromFS(const char *pathname, char *ann_url, size_t piece_length)
+{
+ size_t n, percent;
+
+ // piece length
+ m_piece_length = piece_length;
+ if( m_piece_length % 65536 ){
+ m_piece_length /= 65536;
+ m_piece_length *= 65536;
+ }
+
+ // This is really just a sanity check on the piece length to create.
+ if( !m_piece_length || m_piece_length > 4096*1024 )
+ m_piece_length = 262144;
+
+ m_announce = ann_url;
+ m_create_date = time((time_t*) 0);
+
+ if(m_btfiles.BuildFromFS(pathname) < 0) return -1;
+
+ global_piece_buffer = new char[m_piece_length];
+#ifndef WINDOWS
+ if( !global_piece_buffer ) return -1;
+#endif
+ global_buffer_size = m_piece_length;
+
+ // n pieces
+ m_npieces = m_btfiles.GetTotalLength() / m_piece_length;
+ if( m_btfiles.GetTotalLength() % m_piece_length ) m_npieces++;
+
+ // create hash table.
+ m_hashtable_length = m_npieces * 20;
+ m_hash_table = new unsigned char[m_hashtable_length];
+#ifndef WINDOWS
+ if( !m_hash_table ) return -1;
+#endif
+
+ percent = m_npieces / 100;
+ if( !percent ) percent = 1;
+
+ CONSOLE.Interact_n("");
+ for( n = 0; n < m_npieces; n++ ){
+ if( GetHashValue(n, m_hash_table + n * 20) < 0 ) return -1;
+ if( n % percent == 0 || n == m_npieces-1 ){
+ CONSOLE.InteractU("Create hash table: %d/%d", (int)n+1, (int)m_npieces);
+ }
+ }
+ return 0;
+}
+
+int btContent::PrintOut()
+{
+ CONSOLE.Print("META INFO");
+ CONSOLE.Print("Announce: %s", m_announce);
+ if( m_announcelist[0] ){
+ CONSOLE.Print("Alternates:");
+ for( int n=0; n < 9 && m_announcelist[n]; n++ )
+ CONSOLE.Print(" %d. %s", n+1, m_announcelist[n]);
+ }
+ if( m_create_date ){
+ char s[42];
+#ifdef HAVE_CTIME_R_3
+ ctime_r(&m_create_date, s, sizeof(s));
+#else
+ ctime_r(&m_create_date, s);
+#endif
+ if( s[strlen(s)-1] == '\n' ) s[strlen(s)-1] = '\0';
+ CONSOLE.Print("Created On: %s", s);
+ }
+ CONSOLE.Print("Piece length: %lu", (unsigned long)m_piece_length);
+ if( m_private ) CONSOLE.Print("Private: %s", m_private ? "Yes" : "No");
+ if( m_comment ){
+ char *s = new char[strlen(m_comment)+1];
+ if(s){
+ strcpy(s, m_comment);
+ for(char *t=s; *t; t++)
+ if( !isprint(*t) && !strchr("\t\r\n", *t) ) *t = '?';
+ CONSOLE.Print("Comment: %s", s);
+ delete []s;
+ }
+ }
+ if( m_created_by ) CONSOLE.Print("Created with: %s", m_created_by);
+ m_btfiles.PrintOut();
+ return 0;
+}
+
+int btContent::PrintFiles()
+{
+ m_btfiles.PrintOut();
+ return 0;
+}
+
+int btContent::InitialFromMI(const char *metainfo_fname,const char *saveas)
+{
+#define ERR_RETURN() {if(b) delete []b; return -1;}
+ unsigned char *ptr = m_shake_buffer;
+ char *b;
+ const char *s;
+ size_t flen, q, r;
+ int tmp;
+
+ m_cache_hit = m_cache_miss = m_cache_pre = 0;
+ time(&m_cache_eval_time);
+
+ b = _file2mem(metainfo_fname,&flen);
+ if ( !b ) return -1;
+
+ // announce
+ if( !meta_str("announce",&s,&r) ) ERR_RETURN();
+ if( r > MAXPATHLEN ) ERR_RETURN();
+ m_announce = new char [r + 1];
+ memcpy(m_announce, s, r);
+ m_announce[r] = '\0';
+
+ // announce-list
+ if( r = meta_pos("announce-list") ){
+ const char *sptr;
+ size_t slen, n=0;
+ if( q = decode_list(b+r, flen-r, (char *)0) ){
+ int alend = r + q;
+ r++; // 'l'
+ for( ; r < alend && *(b+r) != 'e' && n < 9; ){ // each list
+ if( !(q = decode_list(b+r, alend-r, (char *)0)) ) break;
+ r++; // 'l'
+ for( ; r < alend && n < 9; ){ // each value
+ if( !(q = buf_str(b+r, alend-r, &sptr, &slen)) )
+ break; // next list
+ r += q;
+ if( strncasecmp(m_announce, sptr, slen) ){
+ m_announcelist[n] = new char[slen+1];
+ memcpy(m_announcelist[n], sptr, slen);
+ (m_announcelist[n])[slen] = '\0';
+ n++;
+ }
+ }
+ r++; // 'e'
+ }
+ }
+ }
+
+ if( meta_int("creation date", &r) ) m_create_date = (time_t) r;
+ if( meta_str("comment", &s, &r) && r ){
+ if( m_comment = new char[r + 1] ){
+ memcpy(m_comment, s, r);
+ m_comment[r] = '\0';
+ }
+ }
+ if( meta_str("created by", &s, &r) && r ){
+ if( m_created_by = new char[r + 1] ){
+ memcpy(m_created_by, s, r);
+ m_created_by[r] = '\0';
+ }
+ }
+
+ // infohash
+ if( !(r = meta_pos("info")) ) ERR_RETURN();
+ if( !(q = decode_dict(b + r, flen - r, (char *) 0)) ) ERR_RETURN();
+ Sha1(b + r, q, m_shake_buffer + 28);
+
+ // private flag
+ if( meta_int("info|private", &r) ) m_private = r;
+
+ // hash table
+ if( !meta_str("info|pieces",&s,&m_hashtable_length) ||
+ m_hashtable_length % 20 != 0 ) ERR_RETURN();
+
+ if( !arg_flg_exam_only ){
+ m_hash_table = new unsigned char[m_hashtable_length];
+#ifndef WINDOWS
+ if( !m_hash_table ) ERR_RETURN();
+#endif
+ memcpy(m_hash_table, s, m_hashtable_length);
+ }
+
+ if( !meta_int("info|piece length",&m_piece_length) ) ERR_RETURN();
+ m_npieces = m_hashtable_length / 20;
+
+ if( m_piece_length < cfg_req_slice_size )
+ cfg_req_slice_size = m_piece_length;
+
+ cfg_req_queue_length = (m_piece_length / cfg_req_slice_size) * 2 - 1;
+
+ if( m_btfiles.BuildFromMI(b, flen, saveas) < 0 ) ERR_RETURN();
+
+ delete []b;
+ b = (char *)0;
+
+ if( arg_flg_exam_only ){
+ PrintOut();
+ return 0;
+ }else{
+ arg_flg_exam_only = 1;
+ PrintOut();
+ arg_flg_exam_only = 0;
+ }
+
+ if( (tmp = m_btfiles.CreateFiles()) < 0 ) ERR_RETURN();
+ r = tmp;
+
+ if( !arg_flg_exam_only ){
+ global_piece_buffer = new char[DEFAULT_SLICE_SIZE];
+#ifndef WINDOWS
+ if( !global_piece_buffer ) ERR_RETURN();
+#endif
+ global_buffer_size = DEFAULT_SLICE_SIZE;
+
+ pBF = new BitField(m_npieces);
+#ifndef WINDOWS
+ if( !pBF ) ERR_RETURN();
+#endif
+
+ pBRefer = new BitField(m_npieces);
+#ifndef WINDOWS
+ if( !pBRefer ) ERR_RETURN();
+#endif
+
+ pBChecked = new BitField(m_npieces);
+#ifndef WINDOWS
+ if( !pBChecked ) ERR_RETURN();
+#endif
+
+ pBMultPeer = new BitField(m_npieces);
+#ifndef WINDOWS
+ if( !pBMultPeer ) ERR_RETURN();
+#endif
+
+ //create the file filter
+ pBMasterFilter = new BitField(m_npieces);
+#ifndef WINDOWS
+ if( !pBMasterFilter ) ERR_RETURN();
+#endif
+ if( arg_file_to_download ) SetFilter();
+ }
+
+ m_left_bytes = m_btfiles.GetTotalLength() / m_piece_length;
+ if( m_btfiles.GetTotalLength() % m_piece_length ) m_left_bytes++;
+ if( m_left_bytes != m_npieces ) ERR_RETURN();
+
+ m_left_bytes = m_btfiles.GetTotalLength();
+
+ if( arg_flg_check_only ){
+ struct stat sb;
+ if( stat(arg_bitfield_file, &sb) == 0 ){
+ if( remove(arg_bitfield_file) < 0 ){
+ CONSOLE.Warning(2, "warn, couldn't delete bit field file \"%s\": %s",
+ arg_bitfield_file, strerror(errno));
+ }
+ }
+ if( r ){
+ if( CheckExist() < 0 ) ERR_RETURN();
+ if( !pBF->IsEmpty() )
+ m_btfiles.PrintOut(); // show file completion
+ }
+ CONSOLE.Print("Already/Total: %d/%d (%d%%)", (int)(pBF->Count()),
+ (int)m_npieces, (int)(100 * pBF->Count() / m_npieces));
+ if( !arg_flg_force_seed_mode ){
+ SaveBitfield();
+ if( arg_completion_exit ) CompletionCommand();
+ exit(0);
+ }
+ }else if( r ){ // files exist already
+ if( pBRefer->SetReferFile(arg_bitfield_file) < 0 ){
+ if( !arg_flg_force_seed_mode ){
+ CONSOLE.Warning(2,
+ "warn, couldn't set bit field refer file \"%s\": %s",
+ arg_bitfield_file, strerror(errno));
+ CONSOLE.Warning(2, "This is normal if you are seeding.");
+ }
+ pBRefer->SetAll(); // need to check all pieces
+ }else{
+ CONSOLE.Interact("Found bit field file; %s previous state.",
+ arg_flg_force_seed_mode ? "resuming download from" : "verifying");
+ if( unlink(arg_bitfield_file) < 0 ){
+ CONSOLE.Warning(2, "warn, couldn't delete bit field file \"%s\": %s",
+ arg_bitfield_file, strerror(errno));
+ }
+ // Mark missing pieces as "checked" (eligible for download).
+ *pBChecked = *pBRefer;
+ pBChecked->Invert();
+ }
+ }
+ if( !r ){ // don't hash-check if the files were just created
+ m_check_piece = m_npieces;
+ pBChecked->SetAll();
+ if( arg_flg_force_seed_mode ){
+ CONSOLE.Warning(2, "Files were not present; overriding force mode!");
+ }
+ }else if( arg_flg_force_seed_mode && !arg_flg_check_only ){
+ size_t idx = 0;
+ *pBF = *pBRefer;
+ if( pBF->IsFull() ){
+ CONSOLE.Interact("Skipping hash checks and forcing seed mode.");
+ CONSOLE.Interact(
+ "-----> STOP NOW if you have not downloaded the whole torrent! <-----");
+ m_left_bytes = 0;
+ }else for( ; idx < m_npieces; idx++ ){
+ if( pBF->IsSet(idx) )
+ m_left_bytes -= GetPieceLength(idx);
+ }
+ m_check_piece = m_npieces;
+ pBChecked->SetAll();
+ }
+ delete pBRefer;
+
+ m_cache = new BTCACHE *[m_npieces];
+ if( !m_cache ){
+ CONSOLE.Warning(1, "error, allocate cache index failed");
+ ERR_RETURN();
+ }
+ memset(m_cache, 0, m_npieces * sizeof(BTCACHE*));
+ CacheConfigure();
+
+ *ptr = (unsigned char) 19; ptr++; // protocol string length
+ memcpy(ptr,"BitTorrent protocol",19); ptr += 19; // protocol string
+ memset(ptr,0,8); // reserved set zero.
+
+ { // peer id
+ char *sptr = arg_user_agent;
+ char *dptr = (char *)m_shake_buffer + 48;
+ char *eptr = dptr + PEER_ID_LEN;
+ while (*sptr) *dptr++ = *sptr++;
+ while (dptr < eptr) *dptr++ = (unsigned char)random();
+ }
+
+ if( arg_announce ){
+ int n;
+ delete []m_announce;
+ if( (n = atoi(arg_announce)) && n <= 9 && m_announcelist[n-1] )
+ m_announce = m_announcelist[n-1];
+ else m_announce = arg_announce;
+ CONSOLE.Print("Using announce URL: %s", m_announce);
+ }
+
+ return 0;
+}
+
+btContent::~btContent()
+{
+ if(m_hash_table) delete []m_hash_table;
+ if(m_announce) delete []m_announce;
+ if(global_piece_buffer) delete []global_piece_buffer;
+ if(pBF) delete pBF;
+}
+
+void btContent::_Set_InfoHash(unsigned char buf[20])
+{
+ memcpy(m_shake_buffer + 28, buf, 20);
+}
+
+// returns <0 if error; if using cache: 1 if read from disk, 0 otherwise
+ssize_t btContent::ReadSlice(char *buf,size_t idx,size_t off,size_t len)
+{
+ ssize_t retval = 0;
+ uint64_t offset = (uint64_t)idx * (uint64_t)m_piece_length + off;
+
+ if( !m_cache_size ) return buf ? m_btfiles.IO(buf, offset, len, 0) : 0;
+ else{
+ size_t len2;
+ BTCACHE *p;
+
+ p = m_cache[idx];
+ while( len && p ){
+ while( p && offset + len > p->bc_off && !CACHE_FIT(p, offset, len) ){
+ p = p->bc_next;
+ }
+ if( !p || !CACHE_FIT(p, offset, len) ) break;
+ if( offset < p->bc_off ){
+ len2 = p->bc_off - offset;
+ if( CacheIO(buf, offset, len2, 0) < 0 ) return -1;
+ retval = 1;
+ if(buf) m_cache_miss += len2 / DEFAULT_SLICE_SIZE +
+ ((len2 % DEFAULT_SLICE_SIZE) ? 1 : 0);
+ else m_cache_pre += len2 / DEFAULT_SLICE_SIZE +
+ ((len2 % DEFAULT_SLICE_SIZE) ? 1 : 0);
+ p = m_cache[idx]; // p may not be valid after CacheIO
+ }else{
+ char *src;
+ if( offset > p->bc_off ){
+ len2 = p->bc_off + p->bc_len - offset;
+ if( len2 > len ) len2 = len;
+ src = p->bc_buf + offset - p->bc_off;
+ }else{
+ len2 = (len > p->bc_len) ? p->bc_len : len;
+ src = p->bc_buf;
+ }
+ if( buf ){
+ memcpy(buf, src, len2);
+ m_cache_hit += len2 / DEFAULT_SLICE_SIZE +
+ ((len2 % DEFAULT_SLICE_SIZE) ? 1 : 0);
+ }else{ // prefetch only, update the age
+ if( m_cache_newest != p ){
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ p->age_next->age_prev = p->age_prev;
+ m_cache_newest->age_next = p;
+ p->age_next = (BTCACHE *)0;
+ p->age_prev = m_cache_newest;
+ m_cache_newest = p;
+ }
+ }
+ p = p->bc_next;
+ }
+
+ if( buf ) buf += len2;
+ offset += len2;
+ len -= len2;
+ }// end for;
+
+ if( len ){
+ if(buf) m_cache_miss += len / DEFAULT_SLICE_SIZE +
+ ((len % DEFAULT_SLICE_SIZE) ? 1 : 0);
+ else m_cache_pre += len / DEFAULT_SLICE_SIZE +
+ ((len % DEFAULT_SLICE_SIZE) ? 1 : 0);
+ retval = CacheIO(buf, offset, len, 0);
+ return (retval < 0) ? retval : 1;
+ }
+ }
+ return retval;
+}
+
+void btContent::CacheClean(size_t need)
+{
+ BTCACHE *p, *pnext;
+ int f_flush = 0;
+
+ if( m_flush_failed ) FlushCache(); // try again
+
+ again:
+ for( p=m_cache_oldest; p && m_cache_size < m_cache_used + need; p=pnext ){
+ pnext = p->age_next;
+ if( f_flush ){
+ if(arg_verbose)
+ CONSOLE.Debug("Flushing %d/%d/%d", (int)(p->bc_off / m_piece_length),
+ (int)(p->bc_off % m_piece_length), (int)(p->bc_len));
+ FlushEntry(p);
+ }
+ if( !p->bc_f_flush ){
+ if(arg_verbose)
+ CONSOLE.Debug("Expiring %d/%d/%d", (int)(p->bc_off / m_piece_length),
+ (int)(p->bc_off % m_piece_length), (int)(p->bc_len));
+
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ if( m_cache_newest == p ) m_cache_newest = p->age_prev;
+ else p->age_next->age_prev = p->age_prev;
+
+ if( p->bc_prev ) p->bc_prev->bc_next = p->bc_next;
+ else m_cache[p->bc_off / m_piece_length] = p->bc_next;
+ if( p->bc_next ) p->bc_next->bc_prev = p->bc_prev;
+
+ m_cache_used -= p->bc_len;
+ delete []p->bc_buf;
+ delete p;
+ }
+ }
+ if( m_cache_size < m_cache_used + need ){ // still not enough
+ if( m_cache_size < cfg_cache_size*1024*1024 ){ // can alloc more
+ m_cache_size = (m_cache_used + need > cfg_cache_size*1024*1024) ?
+ cfg_cache_size*1024*1024 : (m_cache_used + need);
+ }
+ if( m_cache_size < m_cache_used + need && m_cache_used && !f_flush ){
+ if(arg_verbose) CONSOLE.Debug("CacheClean flushing to obtain space");
+ f_flush = 1;
+ goto again;
+ } // else we tried...
+ }
+}
+
+// Don't call this function if cfg_cache_size==0 !
+void btContent::CacheEval()
+{
+ BTCACHE *p = m_cache_oldest;
+ size_t interval;
+ size_t unflushed = 0, dlnext, upadd = 0, upmax = 0, upmin = 0, total;
+
+ size_t rateup = Self.RateUL();
+ size_t ratedn = Self.RateDL();
+ size_t unchoked = WORLD.GetUnchoked();
+
+ // Time until next cache size eval: unchoke interval or time to dl a piece.
+ if( ratedn ){
+ interval = m_piece_length / ratedn;
+ if( interval > WORLD.GetUnchokeInterval() )
+ interval = WORLD.GetUnchokeInterval();
+ else if( 0==interval ) interval = 1;
+ }else interval = WORLD.GetUnchokeInterval();
+
+ // Download: total unflushed data + data to dl before next eval
+ // Hold the first piece a bit to let uploading begin.
+ if( pBF->IsFull() ) dlnext = 0;
+ else{
+ if( pBF->Count() < 2 ) unflushed = m_cache_used;
+ else for( ; p; p = p->age_next )
+ if( p->bc_f_flush ) unflushed += p->bc_len;
+ // Make sure we can read back and check a completed piece.
+ // But free some cache if download has completely stalled.
+ dlnext = ratedn ? (ratedn * interval + m_piece_length) : 0;
+ }
+
+ // Upload: need enough to hold read/dl'd data until it can be sent
+ upmin = DEFAULT_SLICE_SIZE * unchoked;
+ upmax = cfg_cache_size*1024*1024;
+ if( pBF->IsFull() ){
+ // Seed mode. All cache data is prefetched, and we don't normally need to
+ // keep prefetched data longer than 2.5 unchoke intervals.
+ if( rateup && unchoked ){
+ // A very slow peer can't possibly benefit from cache--don't grow for it.
+ size_t slowest = (size_t)( 1 + DEFAULT_SLICE_SIZE /
+ ((double)cfg_cache_size*1024*1024 / rateup) );
+ // Lead cache: data we need to cache to keep the slowest up's data cached
+ // Add a slice per up for timing uncertainty
+ if( slowest = WORLD.GetSlowestUp(slowest) )
+ upadd = DEFAULT_SLICE_SIZE * ( rateup / slowest + unchoked-1 );
+ else upadd = DEFAULT_SLICE_SIZE * unchoked;
+
+ upmin = DEFAULT_SLICE_SIZE * unchoked;
+ upmax = (size_t)( DEFAULT_SLICE_SIZE * (unchoked-1) +
+ rateup * 2.5 * WORLD.GetUnchokeInterval() );
+ }
+ }else{
+ if( rateup > ratedn ){
+ size_t slowest = (size_t)( 1 +
+ cfg_req_slice_size * ((double)ratedn / cfg_cache_size*1024*1024) +
+ DEFAULT_SLICE_SIZE * ((double)rateup / cfg_cache_size*1024*1024) );
+ if( slowest = WORLD.GetSlowestUp(slowest) )
+ // lead cache is how much we'll use while uploading a slice to slowest
+ // (default_slice_size / slowest) * (ratedn + rateup)
+ upadd = (size_t)( ((double)DEFAULT_SLICE_SIZE / slowest) *
+ (ratedn + rateup + 1) );
+ else upadd = m_piece_length * unchoked;
+ }
+ else if( rateup ){
+ // same as m_piece_length / (cfg_cache_size*1024*1024 / (double)ratedn)
+ size_t slowest = (size_t)( 1 +
+ ratedn * ((double)m_piece_length / (cfg_cache_size*1024*1024)) );
+ if( slowest = WORLD.GetSlowestUp(slowest) ){
+ // m_piece_length / (double)slowest * ratedn
+ // optimize, then round up a piece and add a piece
+ upadd = m_piece_length * (ratedn / slowest + 2);
+ }else{ // gimme 10 seconds worth (unchoke interval)
+ // Can't keep pieces in cache long enough to upload them.
+ // Rely on prefetching slices from disk instead.
+ upadd = ratedn * WORLD.GetUnchokeInterval() +
+ DEFAULT_SLICE_SIZE * unchoked;
+ }
+ }
+ }
+
+ if( upadd < upmin ) upadd = upmin;
+
+ // Add a slice to round up
+ total = unflushed + dlnext + upadd + cfg_req_slice_size;
+
+ // Limit to max configured size
+ if( total > cfg_cache_size*1024*1024 ) total = cfg_cache_size*1024*1024;
+
+ // Don't decrease cache size if flush failed.
+ if( !m_flush_failed || total > m_cache_size ) m_cache_size = total;
+
+ if(arg_verbose)
+ CONSOLE.Debug("DL need: %dK UL need: %dK Cache: %dK Used: %dK",
+ (int)((unflushed+dlnext)/1024), (int)(upadd/1024),
+ (int)(m_cache_size/1024), (int)(m_cache_used/1024));
+ m_cache_eval_time = now + interval;
+}
+
+void btContent::CacheConfigure()
+{
+ if( cfg_cache_size ){
+ if( cfg_cache_size > GetTotalFilesLength()/1024/1024 )
+ cfg_cache_size = (GetTotalFilesLength()+1024*1024-1)/1024/1024;
+ CacheEval();
+ }else m_cache_size = 0;
+
+ if( m_cache_size < m_cache_used && !m_flush_failed ) CacheClean(0);
+}
+
+int btContent::NeedFlush() const
+{
+ if( m_flush_failed ){
+ if( now > m_flush_tried ) return 1;
+ }else
+ return (m_flushq ||
+ (m_cache_oldest && m_cache_oldest->bc_f_flush &&
+ m_cache_used >= cfg_cache_size*1024*1024-cfg_req_slice_size+1)) ?
+ 1 : 0;
+}
+
+void btContent::FlushCache()
+{
+ if(arg_verbose) CONSOLE.Debug("Flushing all cache");
+ for( int i=0; i < m_npieces; i++ ){
+ if( m_cache[i] ) FlushPiece(i);
+ if( m_flush_failed ) break;
+ }
+}
+
+void btContent::FlushPiece(size_t idx)
+{
+ BTCACHE *p;
+
+ p = m_cache[idx];
+
+ for( ; p; p = p->bc_next ){
+ // Update the age if piece is complete, as this should mean we've just
+ // completed the piece and made it available.
+ if( pBF->IsSet(idx) && m_cache_newest != p ){
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ p->age_next->age_prev = p->age_prev;
+ m_cache_newest->age_next = p;
+ p->age_next = (BTCACHE *)0;
+ p->age_prev = m_cache_newest;
+ m_cache_newest = p;
+ }
+ if( p->bc_f_flush ) FlushEntry(p);
+ }
+}
+
+void btContent::FlushEntry(BTCACHE *p)
+{
+ if( p->bc_f_flush ){
+ if( m_btfiles.IO(p->bc_buf, p->bc_off, p->bc_len, 1) < 0 ){
+ m_flush_tried = now;
+ if( now >= m_flush_failed + 300 ){
+ if( !m_flush_failed )
+ m_cache_size += cfg_req_slice_size * WORLD.GetDownloads() * 2;
+ CONSOLE.Warning(1, "warn, write file failed while flushing cache.");
+ CONSOLE.Warning(1,
+ "You need to have at least %llu bytes free on this filesystem!",
+ (unsigned long long)(m_left_bytes + m_cache_used));
+ CONSOLE.Warning(1,
+ "This could also be caused by a conflict or disk error.");
+ if( !IsFull() ||
+ (!m_flush_failed && m_cache_size > cfg_cache_size*1024*1024) ){
+ CONSOLE.Warning(1, "Temporarily %s%s...",
+ IsFull() ? "" : "suspending download",
+ (!m_flush_failed && m_cache_size > cfg_cache_size*1024*1024) ?
+ (IsFull() ? " and increasing cache" : "increasing cache") : "");
+ }
+ m_flush_failed = now;
+ WORLD.StopDownload();
+ }
+ }else{
+ p->bc_f_flush = 0;
+ if( Seeding() ){
+ for( size_t n=1; n <= m_btfiles.GetNFiles(); n++ )
+ m_btfiles.CloseFile(n); // files will reopen read-only
+ }
+ if(m_flush_failed){
+ m_flush_failed = 0;
+ CONSOLE.Warning(3, "Flushing cache succeeded%s.",
+ Seeding() ? "" : "; resuming download");
+ CacheConfigure();
+ WORLD.CheckInterest();
+ }
+ }
+ }
+}
+
+void btContent::Uncache(size_t idx)
+{
+ BTCACHE *p, *pnext;
+
+ p = m_cache[idx];
+ for( ; p; p = pnext ){
+ pnext = p->bc_next;
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ if( m_cache_newest == p ) m_cache_newest = p->age_prev;
+ else p->age_next->age_prev = p->age_prev;
+
+ m_cache_used -= p->bc_len;
+ delete []p->bc_buf;
+ delete p;
+ }
+ m_cache[idx] = (BTCACHE *)0;
+}
+
+void btContent::FlushQueue()
+{
+ if( m_flushq ){
+ if(arg_verbose)
+ CONSOLE.Debug("Writing piece #%d to disk", (int)(m_flushq->idx));
+ FlushPiece(m_flushq->idx);
+ if( !m_flush_failed ){
+ BTFLUSH *goner = m_flushq;
+ m_flushq = m_flushq->next;
+ delete goner;
+ }
+ }else{
+ if(arg_verbose) CONSOLE.Debug("Flushing %d/%d/%d",
+ (int)(m_cache_oldest->bc_off / m_piece_length),
+ (int)(m_cache_oldest->bc_off % m_piece_length),
+ (int)(m_cache_oldest->bc_len));
+ FlushEntry(m_cache_oldest);
+ }
+}
+
+/* Prepare for prefetching a whole piece.
+ return -1: do not prefetch (problem or not needed)
+ return 0: already ready (no time used)
+ return 1: data was flushed (time used)
+*/
+int btContent::CachePrep(size_t idx)
+{
+ int retval = 0;
+ BTCACHE *p, *pnext;
+ size_t need = GetPieceLength(idx);
+
+ if( m_cache_size < m_cache_used + need ){
+ for( p=m_cache[idx]; p; p=p->bc_next ) need -= p->bc_len;
+ if( 0==need ) retval = -1; // don't need to prefetch
+ for( p=m_cache_oldest; p && m_cache_size < m_cache_used + need; p=pnext ){
+ pnext = p->age_next;
+ if( p->bc_off / m_piece_length == idx ) continue;
+ if( p->bc_f_flush ){
+ if(arg_verbose)
+ CONSOLE.Debug("Flushing %d/%d/%d", (int)(p->bc_off / m_piece_length),
+ (int)(p->bc_off % m_piece_length), (int)(p->bc_len));
+ FlushEntry(p);
+ retval = 1;
+ }
+ if(arg_verbose)
+ CONSOLE.Debug("Expiring %d/%d/%d", (int)(p->bc_off / m_piece_length),
+ (int)(p->bc_off % m_piece_length), (int)(p->bc_len));
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ if( m_cache_newest == p ) m_cache_newest = p->age_prev;
+ else p->age_next->age_prev = p->age_prev;
+
+ if( p->bc_prev ) p->bc_prev->bc_next = p->bc_next;
+ else m_cache[p->bc_off / m_piece_length] = p->bc_next;
+ if( p->bc_next ) p->bc_next->bc_prev = p->bc_prev;
+
+ m_cache_used -= p->bc_len;
+ delete []p->bc_buf;
+ delete p;
+ }
+ }
+ return retval;
+}
+
+ssize_t btContent::WriteSlice(char *buf,size_t idx,size_t off,size_t len)
+{
+ uint64_t offset = (uint64_t)idx * (uint64_t)m_piece_length + off;
+
+ //CONSOLE.Debug("Offset-write: %llu - Piece:%lu",
+ // (unsigned long long)offset, (unsigned long)idx);
+
+ if( !m_cache_size ) return m_btfiles.IO(buf, offset, len, 1);
+ else{
+ size_t len2;
+ BTCACHE *p;
+
+ p = m_cache[idx];
+ while( len && p ){
+ while( p && offset + len > p->bc_off && !CACHE_FIT(p, offset, len) ){
+ p = p->bc_next;
+ }
+ if( !p || !CACHE_FIT(p, offset, len) ) break;
+ if( offset < p->bc_off ){
+ len2 = p->bc_off - offset;
+ if( CacheIO(buf, offset, len2, 1) < 0 ) return -1;
+ p = m_cache[idx]; // p may not be valid after CacheIO
+ }else{
+ if( offset > p->bc_off ){
+ len2 = p->bc_off + p->bc_len - offset;
+ if( len2 > len ) len2 = len;
+ memcpy(p->bc_buf + (offset - p->bc_off), buf, len2);
+ }else{
+ len2 = (len > p->bc_len) ? p->bc_len : len;
+ memcpy(p->bc_buf, buf, len2);
+ }
+ p->bc_f_flush = 1;
+ // re-received this data, make it new again
+ if( m_cache_newest != p ){
+ if( m_cache_oldest == p ) m_cache_oldest = p->age_next;
+ else p->age_prev->age_next = p->age_next;
+ p->age_next->age_prev = p->age_prev;
+ m_cache_newest->age_next = p;
+ p->age_next = (BTCACHE *)0;
+ p->age_prev = m_cache_newest;
+ m_cache_newest = p;
+ }
+ p = p->bc_next;
+ }
+
+ buf += len2;
+ offset += len2;
+ len -= len2;
+ }// end for;
+
+ if( len ) return CacheIO(buf, offset, len, 1);
+ }
+ return 0;
+}
+
+ssize_t btContent::CacheIO(char *buf, uint64_t off, size_t len, int method)
+{
+ BTCACHE *p;
+ BTCACHE *pp = (BTCACHE*) 0;
+ BTCACHE *pnew = (BTCACHE*) 0;
+
+ if( len >= cfg_cache_size*1024*768 ){ // 75% of cache limit
+ if( buf ) return m_btfiles.IO(buf, off, len, method);
+ else return 0;
+ }
+
+ if(arg_verbose && 0==method)
+ CONSOLE.Debug("Read to %s %d/%d/%d", buf?"buffer":"cache",
+ (int)(off / m_piece_length), (int)(off % m_piece_length), (int)len);
+
+ if( m_cache_size < m_cache_used + len ) CacheClean(len);
+ // Note, there is no failure code from CacheClean(). If nothing can be done
+ // to increase the cache size, we allocate what we need anyway.
+
+ if( 0==method && buf && m_btfiles.IO(buf, off, len, method) < 0 ) return -1;
+
+ pnew = new BTCACHE;
+#ifndef WINDOWS
+ if( !pnew )
+ return (method && buf) ? m_btfiles.IO(buf, off, len, method) : 0;
+#endif
+
+ pnew->bc_buf = new char[len];
+#ifndef WINDOWS
+ if( !(pnew->bc_buf) ){
+ delete pnew;
+ return (method && buf) ? m_btfiles.IO(buf, off, len, method) : 0;
+ }
+#endif
+
+ if( buf ) memcpy(pnew->bc_buf, buf, len);
+ else if( 0==method && m_btfiles.IO(pnew->bc_buf, off, len, method) < 0 ){
+ delete []pnew->bc_buf;
+ delete pnew;
+ return -1;
+ }
+ pnew->bc_off = off;
+ pnew->bc_len = len;
+ pnew->bc_f_flush = method;
+ m_cache_used += len;
+ pnew->age_next = (BTCACHE *)0;
+ if( m_cache_newest ){
+ pnew->age_prev = m_cache_newest;
+ m_cache_newest->age_next = pnew;
+ }else{
+ pnew->age_prev = (BTCACHE *)0;
+ m_cache_oldest = pnew;
+ }
+ m_cache_newest = pnew;
+
+ // find insert point: after pp, before p.
+ size_t idx = off / m_piece_length;
+ p = m_cache[idx];
+ if( p ) pp = p->bc_prev;
+ for( ; p && off > p->bc_off; pp = p, p = pp->bc_next );
+
+ pnew->bc_next = p;
+ pnew->bc_prev = pp;
+ if( pp ) pp->bc_next = pnew;
+ if( p ) p->bc_prev = pnew;
+ if( !m_cache[idx] || off < m_cache[idx]->bc_off )
+ m_cache[idx] = pnew;
+
+ return 0;
+}
+
+ssize_t btContent::ReadPiece(char *buf,size_t idx)
+{
+ return ReadSlice(buf, idx, 0, GetPieceLength(idx));
+}
+
+size_t btContent::GetPieceLength(size_t idx)
+{
+ // Slight optimization to avoid division in every call. The second test is
+ // still needed in case the torrent size is exactly n pieces.
+ return (idx == m_npieces - 1 &&
+ idx == m_btfiles.GetTotalLength() / m_piece_length) ?
+ (size_t)(m_btfiles.GetTotalLength() % m_piece_length) :
+ m_piece_length;
+}
+
+int btContent::CheckExist()
+{
+ size_t idx = 0;
+ size_t percent = GetNPieces() / 100;
+ unsigned char md[20];
+
+ if( !percent ) percent = 1;
+
+ CONSOLE.Interact_n("");
+ for( ; idx < m_npieces; idx++ ){
+ if( GetHashValue(idx, md) < 0 ){
+ CONSOLE.Warning(1, "Error while checking piece %d of %d",
+ (int)idx+1, (int)m_npieces);
+ return -1;
+ }
+ if( memcmp(md, m_hash_table + idx * 20, 20) == 0 ){
+ m_left_bytes -= GetPieceLength(idx);
+ pBF->Set(idx);
+ }
+ if( idx % percent == 0 || idx == m_npieces-1 )
+ CONSOLE.InteractU("Check exist: %d/%d", idx+1, m_npieces);
+ }
+ m_check_piece = m_npieces;
+ pBChecked->SetAll();
+ return 0;
+}
+
+int btContent::CheckNextPiece()
+{
+ size_t idx = m_check_piece;
+ unsigned char md[20];
+ int f_checkint = 0;
+
+ if( idx >= m_npieces ) return 0;
+ if( pBChecked->IsSet(idx) ){
+ while( idx < m_npieces && pBChecked->IsSet(idx) ){
+ if(arg_verbose) CONSOLE.Debug("Check: %u skipped", idx);
+ pBChecked->Set(idx);
+ ++idx;
+ }
+ f_checkint = 1;
+ m_check_piece = idx;
+ }
+ if( idx < m_npieces ){
+ // Don't use the cache for this (looks a bit ugly but helps performance).
+ size_t tmp_cache_size = m_cache_size;
+ m_cache_size = 0;
+ int r = GetHashValue(idx, md);
+ m_cache_size = tmp_cache_size;
+ if( r < 0 ) return -1;
+
+ pBChecked->Set(idx); // need to set before CheckInterest below
+ if( memcmp(md, m_hash_table + idx * 20, 20) == 0 ){
+ if(arg_verbose) CONSOLE.Debug("Check: %u ok", idx);
+ m_left_bytes -= GetPieceLength(idx);
+ pBF->Set(idx);
+ WORLD.Tell_World_I_Have(idx);
+ }else{
+ if(arg_verbose) CONSOLE.Debug("Check: %u failed", idx);
+ f_checkint = 1;
+ }
+ m_check_piece = idx + 1;
+ }
+ if( f_checkint ) WORLD.CheckInterest();
+
+ if( m_check_piece >= m_npieces ){
+ CONSOLE.Print("Checking completed.");
+ if( !pBF->IsEmpty() )
+ m_btfiles.PrintOut(); // show file completion
+ if( pBF->IsFull() ){
+ WORLD.CloseAllConnectionToSeed();
+ }
+ }
+ return 0;
+}
+
+char* btContent::_file2mem(const char *fname, size_t *psiz)
+{
+ char *b = (char*) 0;
+ struct stat sb;
+ FILE* fp;
+ fp = fopen(fname,"r");
+ if( !fp ){
+ CONSOLE.Warning(1, "error, open \"%s\" failed: %s",fname,strerror(errno));
+ return (char*) 0;
+ }
+
+ if(stat(fname,&sb) < 0){
+ CONSOLE.Warning(1, "error, stat \"%s\" failed: %s",fname,strerror(errno));
+ return (char*) 0;
+ }
+
+ if( sb.st_size > MAX_METAINFO_FILESIZ ){
+ CONSOLE.Warning(1, "error, \"%s\" is really a metainfo file???",fname);
+ return (char*) 0;
+ }
+
+ b = new char[sb.st_size];
+#ifndef WINDOWS
+ if( !b ) return (char*) 0;
+#endif
+
+ if(fread(b, sb.st_size, 1, fp) != 1){
+ if( ferror(fp) ){
+ delete []b;
+ return (char*) 0;
+ }
+ }
+ fclose(fp);
+
+ if(psiz) *psiz = sb.st_size;
+ return b;
+}
+
+int btContent::APieceComplete(size_t idx)
+{
+ unsigned char md[20];
+ if(pBF->IsSet(idx)) return 1;
+ if( GetHashValue(idx, md) < 0 ){
+ // error reading data
+ Uncache(idx);
+ return -1;
+ }
+
+ if( memcmp(md,(m_hash_table + idx * 20), 20) != 0 ){
+ CONSOLE.Warning(3, "warn, piece %d hash check failed.", idx);
+ Uncache(idx);
+ CountHashFailure();
+ return 0;
+ }
+
+ pBF->Set(idx);
+ m_left_bytes -= GetPieceLength(idx);
+ Tracker.CountDL(GetPieceLength(idx));
+
+ // Add the completed piece to the flush queue.
+ if( cfg_cache_size ){
+ if( IsFull() ){
+ FlushCache();
+ for( size_t n=1; n <= m_btfiles.GetNFiles(); n++ )
+ m_btfiles.CloseFile(n); // files will reopen read-only
+ }
+ if( !IsFull() || m_flush_failed ){
+ BTFLUSH *last = m_flushq;
+ BTFLUSH *node = new BTFLUSH;
+ if( !node ) FlushPiece(idx);
+ else{
+ node->idx = idx;
+ node->next = (BTFLUSH *)0;
+ if( last ){
+ for( ; last->next; last = last->next);
+ last->next = node;
+ }else m_flushq = node;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int btContent::GetHashValue(size_t idx,unsigned char *md)
+{
+ if( global_buffer_size < m_piece_length ){
+ delete []global_piece_buffer;
+ global_piece_buffer = new char[m_piece_length];
+ global_buffer_size = global_piece_buffer ? m_piece_length : 0;
+ }
+ if( ReadPiece(global_piece_buffer,idx) < 0 ) return -1;
+ Sha1(global_piece_buffer,GetPieceLength(idx),md);
+ return 0;
+}
+
+// This is btcontent's "IntervalCheck()"
+int btContent::SeedTimeout()
+{
+ uint64_t dl;
+ size_t oldrate = m_prevdlrate;
+
+ if( Seeding() && (!m_flush_failed || IsFull()) ){
+ if( !m_seed_timestamp ){
+ if( IsFull() ){
+ Tracker.Reset(15);
+ ReleaseHashTable();
+ }
+ Self.ResetDLTimer(); // set/report dl rate = 0
+ m_prevdlrate = 0;
+ m_seed_timestamp = now;
+ for( size_t n=1; n <= m_btfiles.GetNFiles(); n++ )
+ m_btfiles.CloseFile(n); // files will reopen read-only
+ // Free global buffer prior to CompletionCommand fork (reallocate after).
+ delete []global_piece_buffer;
+ global_piece_buffer = (char *)0;
+ if( Self.TotalDL() > 0 ){
+ CONSOLE.Print("Download complete.");
+ CONSOLE.Print("Total time used: %ld minutes.",
+ (long)((now - m_start_timestamp) / 60));
+ if(arg_verbose) CONSOLE.cpu();
+ if( arg_completion_exit )
+ CompletionCommand();
+ }
+ // Reallocate global buffer for uploading.
+ global_piece_buffer = new char[DEFAULT_SLICE_SIZE];
+ global_buffer_size = global_piece_buffer ? DEFAULT_SLICE_SIZE : 0;
+ if(arg_ctcs) CTCS.Send_Status();
+ exit(0);
+ }else if( now < m_seed_timestamp ) m_seed_timestamp = now;
+ dl = (Self.TotalDL() > 0) ? Self.TotalDL() : GetTotalFilesLength();
+ if( (cfg_seed_ratio == 0 && cfg_seed_hours == 0) ||
+ (cfg_seed_hours > 0 &&
+ (now - m_seed_timestamp) >= (cfg_seed_hours * 60 * 60)) ||
+ (cfg_seed_ratio > 0 &&
+ cfg_seed_ratio <= (double) Self.TotalUL() / dl) ){
+ if( m_flush_failed ){
+ if( !WORLD.IsPaused() ){
+ CONSOLE.Warning(1,
+ "Seeding completed but cache flush failed; pausing...");
+ WORLD.Pause();
+ }
+ }else return 1;
+ }
+ }else{
+ m_prevdlrate = Self.RateDL();
+ if( m_prevdlrate == 0 && oldrate > 0 &&
+ global_buffer_size > DEFAULT_SLICE_SIZE ){
+ delete []global_piece_buffer;
+ global_piece_buffer = new char[DEFAULT_SLICE_SIZE];
+ global_buffer_size = global_piece_buffer ? DEFAULT_SLICE_SIZE : 0;
+ }
+ }
+ if( (cfg_cache_size && now >= m_cache_eval_time) ||
+ (oldrate == 0 && m_prevdlrate > 0) ){
+ CacheEval();
+ }
+ return 0;
+}
+
+
+void btContent::CompletionCommand()
+{
+ char *pt, *pd, *pw, *cmdstr;
+ int nt=0, nd=0, nw=0;
+
+ pt = pd = pw = arg_completion_exit;
+ while( pt = strstr(pt, "&t") ){ nt++; pt+=2; }
+ while( pd = strstr(pd, "&d") ){ nd++; pd+=2; }
+ while( pw = strstr(pw, "&w") ){ nw++; pw+=2; }
+
+ if( nt || nd || nw ){
+ char wd[MAXPATHLEN], *ptmp, *parg = arg_completion_exit;
+ if( nw && !getcwd(wd, MAXPATHLEN) ){
+ CONSOLE.Warning(2, "warn, couldn't get working directory: %s",
+ strerror(errno));
+ return;
+ }
+ cmdstr = new char[1 + strlen(arg_completion_exit) +
+ nt * (strlen(arg_metainfo_file) - 2) +
+ nd * (strlen(m_btfiles.GetDataName()) - 2) +
+ nw * (strlen(wd) - 2)];
+ if( !cmdstr ){
+ CONSOLE.Warning(2,
+ "warn, failed to allocate memory for completion command");
+ return;
+ }
+ strcpy(cmdstr, arg_completion_exit);
+
+ pt = strstr(cmdstr, "&t");
+ pd = strstr(cmdstr, "&d");
+ pw = strstr(cmdstr, "&w");
+ while( pt || pd || pw ){
+ if( pt && (!pd || pt < pd) && (!pw || pt < pw) ){
+ strcpy(pt, arg_metainfo_file);
+ ptmp = cmdstr + strlen(cmdstr);
+ parg = strstr(parg, "&t") + 2;
+ strcat(pt, parg);
+ pt = strstr(ptmp, "&t");
+ if( pd ) pd = strstr(ptmp, "&d");
+ if( pw ) pw = strstr(ptmp, "&w");
+ }
+ if( pd && (!pt || pd < pt) && (!pw || pd < pw) ){
+ strcpy(pd, m_btfiles.GetDataName());
+ ptmp = cmdstr + strlen(cmdstr);
+ parg = strstr(parg, "&d") + 2;
+ strcat(pd, parg);
+ pd = strstr(ptmp, "&d");
+ if( pt ) pt = strstr(ptmp, "&t");
+ if( pw ) pw = strstr(ptmp, "&w");
+ }
+ if( pw && (!pt || pw < pt) && (!pd || pw < pd) ){
+ strcpy(pw, wd);
+ ptmp = cmdstr + strlen(cmdstr);
+ parg = strstr(parg, "&w") + 2;
+ strcat(pw, parg);
+ pw = strstr(ptmp, "&w");
+ if( pt ) pt = strstr(ptmp, "&t");
+ if( pd ) pd = strstr(ptmp, "&d");
+ }
+ }
+ }
+ else cmdstr = arg_completion_exit;
+ if(arg_verbose) CONSOLE.Debug("Executing: %s", cmdstr);
+#ifdef HAVE_WORKING_FORK
+ if( cfg_cache_size ){ // maybe free some cache before forking
+ CacheEval();
+ if( m_cache_size < m_cache_used && !m_flush_failed ) CacheClean(0);
+ }
+ pid_t r;
+ if( (r = fork()) < 0 ){
+ CONSOLE.Warning(2,"warn, fork failed running completion command: %s",
+ strerror(errno));
+ }else if( r==0 ){
+ if( m_cache_used ){ // free the cache in the child process
+ BTCACHE *p, *pnext;
+ for( p=m_cache_oldest; p; p=pnext ){
+ pnext = p->age_next;
+ delete []p->bc_buf;
+ delete p;
+ }
+ }
+#endif
+ if( system(cmdstr) < 0 )
+ CONSOLE.Warning(2, "warn, failure running completion command: %s",
+ strerror(errno));
+#ifdef HAVE_WORKING_FORK
+ exit(EXIT_SUCCESS);
+ }
+#endif
+ if( cmdstr != arg_completion_exit ) delete []cmdstr;
+}
+
+
+void btContent::CheckFilter()
+{
+ BitField tmpBitfield;
+ BFNODE *original = m_current_filter;
+
+ if( !m_filters ) return;
+ if( !m_current_filter ) m_current_filter = m_filters;
+
+ while( m_current_filter ){
+ tmpBitfield = *pBF; // what I have...
+ tmpBitfield.Comb(GetFilter()); // ...plus what I don't want
+ if( !tmpBitfield.IsFull() ) break;
+ m_current_filter = m_current_filter->next;
+ }
+
+ if( !m_current_filter ){
+ if( !IsFull() ) CONSOLE.Print("End of download files list.");
+ for( BFNODE *goner=m_filters; goner; goner=m_current_filter ){
+ m_current_filter = goner->next;
+ delete goner;
+ }
+ m_filters = (BFNODE *)0;
+ }
+
+ if( m_current_filter != original ){
+ if( m_current_filter ){
+ size_t last;
+ tmpBitfield = *GetFilter();
+ tmpBitfield.Invert(); // what I want...
+ tmpBitfield.Except(*pBF); // ...that I don't have
+ last = tmpBitfield.IsSet(m_npieces-1) ? 1 : 0;
+ if( GetFilter()->IsEmpty() )
+ CONSOLE.Print("Downloading remaining files");
+ else CONSOLE.Print("Downloading file(s): %s", m_current_filter->name);
+ CONSOLE.Print( "Pieces: %d (%llu bytes)", (int)(tmpBitfield.Count()),
+ (unsigned long long)
+ ((tmpBitfield.Count() - last) * (uint64_t)m_piece_length +
+ (last ? GetPieceLength(m_npieces-1) : 0)) );
+ }
+ }
+
+ if( m_seed_timestamp && m_current_filter ){
+ // was seeding, now downloading again
+ m_seed_timestamp = (time_t)0;
+ }
+}
+
+
+void btContent::SetFilter()
+{
+ // Set up filter list
+ char *list=(char *)0, *tok, *dash, *plus;
+ size_t start, end;
+ BitField tmpFilter, *pfilter;
+ BFNODE *node=m_filters, *pnode=(BFNODE *)0;
+
+ if( arg_file_to_download ){
+ pBMasterFilter->SetAll();
+ list = new char[strlen(arg_file_to_download) + 1];
+ if( !list ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for filter");
+ return;
+ }
+ strcpy(list, arg_file_to_download);
+ tok = strtok(list, ", ");
+ while( tok ){
+ if( !node ){
+ node = new BFNODE;
+ if( !node ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for filter");
+ return;
+ }
+ if( pnode ) pnode->next = node;
+ else m_filters = node;
+ }
+
+ if( node->name && strlen(node->name) < strlen(tok) ){
+ delete []node->name;
+ node->name = (char *)0;
+ }
+ if( !node->name ){
+ node->name = new char[strlen(tok)+1];
+ if( !node ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for filter");
+ return;
+ }
+ }
+ strcpy(node->name, tok);
+
+ pfilter = &(node->bitfield);
+ if( strstr(tok, "...") || strchr(tok, '*') ){
+ pfilter->Clear();
+ pBMasterFilter->Clear();
+ pnode = node;
+ node = node->next;
+ break;
+ }
+ pfilter->SetAll();
+ do{
+ start = atoi(tok);
+ m_btfiles.SetFilter((int)start, &tmpFilter, m_piece_length);
+ pfilter->And(tmpFilter);
+
+ plus = strchr(tok, '+');
+
+ if( (dash = strchr(tok, '-')) && (!plus || dash < plus) ){
+ end = atoi(dash + 1);
+ while( ++start <= end ){
+ m_btfiles.SetFilter((int)start, &tmpFilter, m_piece_length);
+ pfilter->And(tmpFilter);
+ }
+ }
+
+ tok = plus ? plus+1 : plus;
+ }while( tok );
+
+ pBMasterFilter->And(*pfilter);
+ tok = strtok(NULL, ", ");
+ pnode = node;
+ node = node->next;
+ }
+ delete []list;
+ }else // no arg_file_to_download
+ pBMasterFilter->Clear();
+
+ if( m_filters && m_filters->bitfield.IsEmpty() ){
+ delete []arg_file_to_download;
+ arg_file_to_download = (char *)0;
+ pBMasterFilter->Clear();
+ node = m_filters;
+ pnode = (BFNODE *)0;
+ }
+
+ if( node ){
+ if( m_filters == node ) m_filters = (BFNODE *)0;
+ if( pnode ) pnode->next = (BFNODE *)0;
+ for( BFNODE *goner=node; goner; goner=node ){
+ node = goner->next;
+ delete goner;
+ }
+ }
+
+ m_current_filter = (BFNODE *)0;
+ CheckFilter();
+ WORLD.CheckInterest();
+}
+
+
+BitField *btContent::GetNextFilter(BitField *pfilter) const
+{
+ static BFNODE *p = m_filters;
+
+ if( !pfilter ) p = m_filters;
+ else if( p && &(p->bitfield) == pfilter ){
+ p = p->next;
+ }else{
+ for( p=m_filters; p && (&(p->bitfield) != pfilter); p = p->next );
+ if(p) p = p->next;
+ else p = m_filters;
+ }
+
+ if(p) return &(p->bitfield);
+ else return (BitField *) 0;
+}
+
+
+int btContent::Seeding() const
+{
+ if( IsFull() || m_flush_failed ) return 1;
+ if( arg_file_to_download && !m_current_filter ) return 1;
+ return 0;
+}
+
+
+// Note, this functions assumes the program is exiting.
+void btContent::SaveBitfield()
+{
+ if( arg_bitfield_file ){
+ if( m_check_piece < m_npieces ){ // still checking
+ // Anything unchecked needs to be checked next time.
+ pBChecked->Invert();
+ pBF->Comb(*pBChecked);
+ }
+ if( !pBF->IsFull() ) pBF->WriteToFile(arg_bitfield_file);
+ }
+}
+
+
+void btContent::CountDupBlock(size_t len)
+{
+ m_dup_blocks++;
+ Tracker.CountDL(len);
+}
+
+
+void btContent::DumpCache()
+{
+ BTCACHE *p = m_cache_oldest;
+ int count;
+
+ CONSOLE.Debug("CACHE CONTENTS:");
+ count = 0;
+ for( ; p; p = p->age_next ){
+ CONSOLE.Debug(" %p prev=%p %d/%d/%d %sflushed",
+ p, p->age_prev,
+ (int)(p->bc_off / m_piece_length), (int)(p->bc_off % m_piece_length),
+ (int)(p->bc_len),
+ p->bc_f_flush ? "un" : "");
+ count++;
+ }
+ CONSOLE.Debug(" count=%d", count);
+ CONSOLE.Debug(" newest=%p", m_cache_newest);
+
+ CONSOLE.Debug("BY PIECE:");
+ count = 0;
+ for( size_t idx=0; idx < m_npieces; idx++ ){
+ for( p=m_cache[idx]; p; p=p->bc_next ){
+ CONSOLE.Debug(" %p prev=%p %d/%d/%d %sflushed",
+ p, p->bc_prev,
+ (int)(p->bc_off / m_piece_length), (int)(p->bc_off % m_piece_length),
+ (int)(p->bc_len),
+ p->bc_f_flush ? "un" : "");
+ count++;
+ }
+ }
+ CONSOLE.Debug(" count=%d", count);
+}
+
diff --git a/btcontent.h b/btcontent.h
new file mode 100644
index 0000000..dc58636
--- a/dev/null
+++ b/btcontent.h
@@ -0,0 +1,198 @@
+#ifndef BTCONTENT_H
+#define BTCONTENT_H
+
+#include "def.h"
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <time.h>
+#include "bitfield.h"
+#include "btfiles.h"
+
+typedef struct _btcache{
+ uint64_t bc_off;
+ size_t bc_len;
+
+ unsigned char bc_f_flush:1;
+ unsigned char bc_f_reserved:7;
+
+ char *bc_buf;
+
+ struct _btcache *bc_next;
+ struct _btcache *bc_prev;
+ struct _btcache *age_next;
+ struct _btcache *age_prev;
+}BTCACHE;
+
+typedef struct _btflush{
+ size_t idx;
+ struct _btflush *next;
+}BTFLUSH;
+
+typedef struct _bfnode{
+ char *name;
+ BitField bitfield;
+ struct _bfnode *next;
+
+ _bfnode(){
+ name = (char *)0;
+ next = (struct _bfnode *)0;
+ }
+ ~_bfnode(){
+ if(name) delete []name;
+ }
+}BFNODE;
+
+class btContent
+{
+ //METAINFO成员
+ char *m_announce;
+ unsigned char *m_hash_table;
+ unsigned char m_shake_buffer[68];
+ char *m_announcelist[9];
+ char *m_comment, *m_created_by;
+
+ size_t m_hashtable_length;
+ size_t m_piece_length;
+ size_t m_npieces, m_check_piece;
+ time_t m_create_date, m_seed_timestamp, m_start_timestamp;
+ size_t m_private;
+
+ uint64_t m_left_bytes;
+ btFiles m_btfiles;
+
+ time_t m_flush_failed, m_flush_tried;
+
+ BTCACHE **m_cache, *m_cache_oldest, *m_cache_newest;
+ size_t m_cache_size, m_cache_used;
+ size_t m_cache_hit, m_cache_miss, m_cache_pre;
+ time_t m_cache_eval_time;
+ BTFLUSH *m_flushq;
+
+ BFNODE *m_filters, *m_current_filter;
+
+ size_t m_prevdlrate;
+ size_t m_hash_failures, m_dup_blocks, m_unwanted_blocks;
+
+ void _Set_InfoHash(unsigned char buf[20]);
+ char* _file2mem(const char *fname, size_t *psiz);
+
+ void ReleaseHashTable(){
+ if(m_hash_table){
+ delete []m_hash_table;
+ m_hash_table = (unsigned char*) 0;
+ }
+ }
+
+ int CheckExist();
+ void CacheClean(size_t need);
+ void CacheEval();
+ uint64_t max_uint64_t(uint64_t a,uint64_t b) { return (a > b) ? a : b; }
+ uint64_t min_uint64_t(uint64_t a,uint64_t b) { return (a > b) ? b : a; }
+ ssize_t CacheIO(char *buf, uint64_t off, size_t len, int method);
+ void FlushEntry(BTCACHE *p);
+
+ public:
+ BitField *pBF;
+ BitField *pBMasterFilter;
+ BitField *pBRefer;
+ BitField *pBChecked;
+ BitField *pBMultPeer;
+ char *global_piece_buffer;
+ size_t global_buffer_size;
+
+ btContent();
+ ~btContent();
+
+ void CacheConfigure();
+ void FlushCache();
+ void FlushPiece(size_t idx);
+ void Uncache(size_t idx);
+ void FlushQueue();
+ int NeedFlush() const;
+ int FlushFailed() const { return m_flush_failed ? 1 : 0 ; }
+
+ int CreateMetainfoFile(const char *mifn);
+ int InitialFromFS(const char *pathname, char *ann_url, size_t piece_length);
+ int InitialFromMI(const char *metainfo_fname,const char *saveas);
+
+ int CheckNextPiece();
+ size_t CheckedPieces() const { return m_check_piece; }
+
+ char* GetAnnounce() { return m_announce;}
+
+ unsigned char* GetShakeBuffer() {return m_shake_buffer;}
+ unsigned char* GetInfoHash() {return (m_shake_buffer + 28);}
+ unsigned char* GetPeerId() {return (m_shake_buffer + 48); }
+
+ size_t GetPieceLength(size_t idx);
+ size_t GetPieceLength() const { return m_piece_length; }
+ size_t GetNPieces() const { return m_npieces; }
+
+ uint64_t GetTotalFilesLength() const { return m_btfiles.GetTotalLength(); }
+ uint64_t GetLeftBytes() const { return m_left_bytes; }
+
+ int APieceComplete(size_t idx);
+ int GetHashValue(size_t idx,unsigned char *md);
+
+ int CachePrep(size_t idx);
+ ssize_t ReadSlice(char *buf,size_t idx,size_t off,size_t len);
+ ssize_t WriteSlice(char *buf,size_t idx,size_t off,size_t len);
+ ssize_t ReadPiece(char *buf,size_t idx);
+
+ int PrintOut();
+ int PrintFiles();
+ int SeedTimeout();
+ void CompletionCommand();
+ void SaveBitfield();
+
+ void CheckFilter();
+ void SetFilter();
+ BitField *GetFilter() const {
+ return m_current_filter ? &(m_current_filter->bitfield) : (BitField *)0;
+ }
+ BitField *GetNextFilter() const { return GetNextFilter((BitField *)0); }
+ BitField *GetNextFilter(BitField *pfilter) const;
+ char *GetFilterName() const { return m_current_filter->name; }
+ void SetTmpFilter(int nfile, BitField *pFilter){
+ m_btfiles.SetFilter(nfile, pFilter, m_piece_length);
+ }
+
+ size_t GetNFiles() const { return m_btfiles.GetNFiles(); }
+ char *GetFileName(size_t nfile) const {
+ return m_btfiles.GetFileName(nfile);
+ }
+ uint64_t GetFileSize(size_t nfile) const {
+ return m_btfiles.GetFileSize(nfile);
+ }
+ size_t GetFilePieces(size_t nfile) const {
+ return m_btfiles.GetFilePieces(nfile);
+ }
+
+ time_t GetStartTime() const { return m_start_timestamp; }
+ time_t GetSeedTime() const { return m_seed_timestamp; }
+
+ size_t GetHashFailures() const { return m_hash_failures; }
+ size_t GetDupBlocks() const { return m_dup_blocks; }
+ size_t GetUnwantedBlocks() const { return m_unwanted_blocks; }
+ void CountHashFailure() { m_hash_failures++; }
+ void CountDupBlock(size_t len);
+ void CountUnwantedBlock() { m_unwanted_blocks++; }
+
+ int IsFull() const { return pBF->IsFull(); }
+ int Seeding() const;
+
+ size_t CacheHits() const { return m_cache_hit; }
+ // "miss" does not count prefetch reads from disk
+ size_t CacheMiss() const { return m_cache_miss; }
+ // instead, "pre" does
+ size_t CachePre() const { return m_cache_pre; }
+ size_t CacheSize() const { return m_cache_size; }
+ size_t CacheUsed() const { return m_cache_used; }
+
+ void DumpCache();
+};
+
+extern btContent BTCONTENT;
+
+#endif
diff --git a/btcontent.o b/btcontent.o
new file mode 100644
index 0000000..90148d1
--- a/dev/null
+++ b/btcontent.o
Binary files differ
diff --git a/btfiles.cpp b/btfiles.cpp
new file mode 100644
index 0000000..e81511b
--- a/dev/null
+++ b/btfiles.cpp
@@ -0,0 +1,815 @@
+#include "btfiles.h"
+
+#ifdef WINDOWS
+#include <io.h>
+#include <memory.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/param.h>
+#endif
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h> // isprint
+
+#include "bencode.h"
+#include "btcontent.h"
+#include "bitfield.h"
+#include "console.h"
+#include "bttime.h"
+
+#ifndef HAVE_SNPRINTF
+#include "compat.h"
+#endif
+
+#define MAX_OPEN_FILES 20
+
+btFiles::btFiles()
+{
+ m_btfhead = (BTFILE*) 0;
+ m_nfiles = 0;
+ m_file = (BTFILE **)0;
+ m_total_files_length = 0;
+ m_total_opened = 0;
+ m_flag_automanage = 1;
+ m_directory = (char*)0;
+}
+
+btFiles::~btFiles()
+{
+ _btf_destroy();
+ if( m_directory ) delete []m_directory;
+}
+
+BTFILE* btFiles::_new_bfnode()
+{
+ BTFILE *pnew = new BTFILE;
+
+#ifndef WINDOWS
+ if( !pnew ) return (BTFILE*) 0;
+#endif
+
+ pnew->bf_flag_opened = 0;
+ pnew->bf_flag_readonly = 0;
+
+ pnew->bf_filename = (char*) 0;
+ pnew->bf_fp = (FILE*) 0;
+ pnew->bf_length = 0;
+ pnew->bf_buffer = (char *) 0;
+
+ pnew->bf_last_timestamp = (time_t) 0;
+ pnew->bf_next = (BTFILE*) 0;
+ return pnew;
+}
+
+void btFiles::CloseFile(size_t nfile)
+{
+ if( nfile && nfile <= m_nfiles )
+ _btf_close(m_file[nfile-1]);
+}
+
+int btFiles::_btf_close_oldest()
+{
+ BTFILE *pbf_n,*pbf_close;
+ pbf_close = (BTFILE *) 0;
+ for(pbf_n = m_btfhead; pbf_n; pbf_n = pbf_n->bf_next){
+ if(!pbf_n->bf_flag_opened) continue; // file not been opened.
+ if(!pbf_close || pbf_n->bf_last_timestamp < pbf_close->bf_last_timestamp)
+ pbf_close = pbf_n;
+ }
+ if(!pbf_close) return -1;
+ return _btf_close(pbf_close);
+}
+
+int btFiles::_btf_close(BTFILE *pbf)
+{
+ if( !pbf->bf_flag_opened ) return 0;
+
+ if( fclose(pbf->bf_fp) == EOF )
+ CONSOLE.Warning(2, "warn, error closing file \"%s\": %s",
+ pbf->bf_filename, strerror(errno));
+ pbf->bf_flag_opened = 0;
+ pbf->bf_fp = (FILE *)0;
+ if( pbf->bf_buffer ){
+ delete []pbf->bf_buffer;
+ pbf->bf_buffer = (char *)0;
+ }
+ m_total_opened--;
+ return 0;
+}
+
+int btFiles::_btf_open(BTFILE *pbf, const int iotype)
+{
+ char fn[MAXPATHLEN];
+
+ if( pbf->bf_flag_opened ){
+ if( pbf->bf_flag_readonly && iotype ) _btf_close(pbf);
+ else return 0; // already open in a usable mode
+ }
+
+ if(m_flag_automanage && (m_total_opened >= MAX_OPEN_FILES)){ // close a file
+ if( _btf_close_oldest() < 0 ) return -1;
+ }
+
+ if( m_directory ){
+ if( MAXPATHLEN <= snprintf(fn, MAXPATHLEN, "%s%c%s", m_directory, PATH_SP,
+ pbf->bf_filename) ){
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }else{
+ strcpy(fn, pbf->bf_filename);
+ }
+
+ pbf->bf_last_timestamp = now + 1;
+ if( !(pbf->bf_fp = fopen(fn, iotype ? "r+b" : "rb")) ){
+ if( EMFILE == errno || ENFILE == errno ){
+ if( _btf_close_oldest() < 0 ||
+ !(pbf->bf_fp = fopen(fn, iotype ? "r+b" : "rb")) )
+ return -1; // caller prints error
+ }else return -1; // caller prints error
+ }
+ pbf->bf_buffer = new char[DEFAULT_SLICE_SIZE];
+ if(pbf->bf_buffer)
+ setvbuf(pbf->bf_fp, pbf->bf_buffer, _IOFBF, DEFAULT_SLICE_SIZE);
+
+ pbf->bf_flag_opened = 1;
+ pbf->bf_flag_readonly = iotype ? 0 : 1;
+ m_total_opened++;
+ return 0;
+}
+
+ssize_t btFiles::IO(char *buf, uint64_t off, size_t len, const int iotype)
+{
+ uint64_t n = 0;
+ off_t pos,nio;
+ BTFILE *pbf = m_btfhead;
+
+ if( (off + (uint64_t)len) > m_total_files_length ){
+ CONSOLE.Warning(1, "error, data offset %llu length %lu out of range",
+ (unsigned long long)off, (unsigned long)len);
+ return -1;
+ }
+
+ for(; pbf; pbf = pbf->bf_next){
+ n += (uint64_t) pbf->bf_length;
+ if(n > off) break;
+ }
+
+ if( !pbf ){
+ CONSOLE.Warning(1, "error, failed to find file for offset %llu",
+ (unsigned long long)off);
+ return -1;
+ }
+
+ pos = off - (n - pbf->bf_length);
+
+ for(; len ;){
+ if( (!pbf->bf_flag_opened || (iotype && pbf->bf_flag_readonly)) &&
+ _btf_open(pbf, iotype) < 0 ){
+ CONSOLE.Warning(1, "error, failed to open file \"%s\": %s",
+ pbf->bf_filename, strerror(errno));
+ return -1;
+ }
+
+ pbf->bf_last_timestamp = now;
+
+#ifdef HAVE_FSEEKO
+ if( fseeko(pbf->bf_fp,pos,SEEK_SET) < 0 ){
+#else
+ if( fseek(pbf->bf_fp,(long) pos,SEEK_SET) < 0 ){
+#endif
+ CONSOLE.Warning(1, "error, failed to seek to %llu on file \"%s\": %s",
+ (unsigned long long)pos, pbf->bf_filename, strerror(errno));
+ return -1;
+ }
+// }
+
+ nio = (len < pbf->bf_length - pos) ? len : (pbf->bf_length - pos);
+
+ if(0 == iotype){
+ errno = 0;
+ if( 1 != fread(buf,nio,1,pbf->bf_fp) && ferror(pbf->bf_fp) ){
+ CONSOLE.Warning(1, "error, read failed at %llu on file \"%s\": %s",
+ (unsigned long long)pos, pbf->bf_filename, strerror(errno));
+ return -1;
+ }
+ }else{
+ errno = 0;
+ if( 1 != fwrite(buf,nio,1,pbf->bf_fp) ){
+ CONSOLE.Warning(1, "error, write failed at %llu on file \"%s\": %s",
+ (unsigned long long)pos, pbf->bf_filename, strerror(errno));
+ return -1;
+ }
+ if( fflush(pbf->bf_fp) == EOF ){
+ CONSOLE.Warning(1, "error, flush failed at %llu on file \"%s\": %s",
+ (unsigned long long)pos, pbf->bf_filename, strerror(errno));
+ return -1;
+ }
+ }
+
+ len -= nio;
+ buf += nio;
+
+ if( len ){
+ do{
+ pbf = pbf->bf_next;
+ if( !pbf ){
+ CONSOLE.Warning(1,
+ "error, data left over with no more files to write");
+ return -1;
+ }
+ }while( 0==pbf->bf_length );
+ pos = 0;
+ }
+ } // end for
+ return 0;
+}
+
+int btFiles::_btf_destroy()
+{
+ BTFILE *pbf,*pbf_next;
+ for(pbf = m_btfhead; pbf;){
+ pbf_next = pbf->bf_next;
+ if( pbf->bf_fp && pbf->bf_flag_opened ) fclose( pbf->bf_fp );
+ if( pbf->bf_filename ) delete []pbf->bf_filename;
+ if( pbf->bf_buffer ) delete []pbf->bf_buffer;
+ delete pbf;
+ pbf = pbf_next;
+ }
+ m_btfhead = (BTFILE*) 0;
+ m_total_files_length = (uint64_t) 0;
+ m_total_opened = 0;
+ return 0;
+}
+
+int btFiles::_btf_ftruncate(int fd,int64_t length)
+{
+ if( arg_allocate ){
+ char *c = new char[256*1024];
+ if( !c ){ errno = ENOMEM; return -1; }
+ memset(c, 0, 256*1024);
+ int r, wlen;
+ int64_t len = 0;
+ for( int i=0; len < length; i++ ){
+ if( len + 256*1024 > length ) wlen = (int)(length - len);
+ else wlen = 256*1024;
+ if( 0 == i % 100 ) CONSOLE.Interact_n(".");
+ if( (r = write(fd, c, wlen)) < 0 ) return r;
+ len += wlen;
+ }
+ delete []c;
+ return r;
+ }
+#ifdef WINDOWS
+ char c = (char)0;
+ if( lseek(fd,length - 1, SEEK_SET) < 0 ) return -1;
+ return write(fd, &c, 1);
+#else
+ // ftruncate() not allowed on [v]fat under linux
+ int retval = ftruncate(fd,length);
+ if( retval < 0 ) {
+ char c = (char)0;
+ if( lseek(fd,length - 1, SEEK_SET) < 0 ) return -1;
+ return write(fd, &c, 1);
+ }
+ else return retval;
+#endif
+}
+
+int btFiles::_btf_recurses_directory(const char *cur_path, BTFILE* *plastnode)
+{
+ char full_cur[MAXPATHLEN];
+ char fn[MAXPATHLEN];
+ struct stat sb;
+ struct dirent *dirp;
+ DIR *dp;
+ BTFILE *pbf;
+
+ if( !getcwd(full_cur,MAXPATHLEN) ) return -1;
+
+ if( cur_path ){
+ strcpy(fn, full_cur);
+ if( MAXPATHLEN <= snprintf(full_cur, MAXPATHLEN, "%s%c%s", fn, PATH_SP,
+ cur_path) ){
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }
+
+ if( (DIR*) 0 == (dp = opendir(full_cur)) ){
+ CONSOLE.Warning(1, "error, open directory \"%s\" failed: %s",
+ cur_path, strerror(errno));
+ return -1;
+ }
+
+ while( (struct dirent*) 0 != (dirp = readdir(dp)) ){
+
+ if( 0 == strcmp(dirp->d_name, ".") ||
+ 0 == strcmp(dirp->d_name, "..") ) continue;
+
+ if( cur_path ){
+ if(MAXPATHLEN < snprintf(fn, MAXPATHLEN, "%s%c%s", cur_path, PATH_SP,
+ dirp->d_name)){
+ CONSOLE.Warning(1, "error, pathname too long");
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }else{
+ strcpy(fn, dirp->d_name);
+ }
+
+ if( stat(fn, &sb) < 0 ){
+ CONSOLE.Warning(1, "error, stat \"%s\" failed: %s",fn,strerror(errno));
+ return -1;
+ }
+
+ if( S_IFREG & sb.st_mode ){
+
+ pbf = _new_bfnode();
+#ifndef WINDOWS
+ if( !pbf ){ errno = ENOMEM; return -1; }
+#endif
+ pbf->bf_filename = new char[strlen(fn) + 1];
+#ifndef WINDOWS
+ if( !pbf->bf_filename ){ closedir(dp); errno = ENOMEM; return -1; }
+#endif
+ strcpy(pbf->bf_filename, fn);
+
+ pbf->bf_length = sb.st_size;
+ m_total_files_length += sb.st_size;
+
+ if( *plastnode ) (*plastnode)->bf_next = pbf; else m_btfhead = pbf;
+
+ *plastnode = pbf;
+
+ }else if( S_IFDIR & sb.st_mode ){
+ if(_btf_recurses_directory(fn, plastnode) < 0){closedir(dp); return -1;}
+ }else{
+ CONSOLE.Warning(1, "error, \"%s\" is not a directory or regular file.",
+ fn);
+ closedir(dp);
+ return -1;
+ }
+ } // end while
+ closedir(dp);
+ return 0;
+}
+
+int btFiles::_btf_creat_by_path(const char *pathname, int64_t file_length)
+{
+ struct stat sb;
+ int fd;
+ char *p,*pnext,last = 0;
+ char sp[MAXPATHLEN];
+
+ strcpy(sp,pathname);
+
+ pnext = sp;
+ if(PATH_SP == *pnext) pnext++;
+
+ for(; !last; ){
+ for(p = pnext; *p && PATH_SP != *p; p++) ;
+ if( !*p ) last = 1;
+ if(last && PATH_SP == *p){ last = 0; break;}
+ *p = '\0';
+ if(stat(sp,&sb) < 0){
+ if( ENOENT == errno ){
+ if( !last ){
+#ifdef WINDOWS
+ if(mkdir(sp) < 0) break;
+#else
+ if(mkdir(sp,0755) < 0) break;
+#endif
+ }else{
+ if((fd = creat(sp,0644)) < 0){ last = 0; break; }
+ if(file_length && _btf_ftruncate(fd, file_length) < 0){
+ close(fd); last = 0; break;
+ }
+ close(fd);
+ }
+ }else{last = 0; break;}
+ }
+ if( !last ){ *p = PATH_SP; pnext = p + 1; }
+ }
+ return last;
+}
+
+int btFiles::BuildFromFS(const char *pathname)
+{
+ struct stat sb;
+ BTFILE *pbf = (BTFILE*) 0;
+ BTFILE *lastnode = (BTFILE*) 0;
+
+ if( stat(pathname, &sb) < 0 ){
+ CONSOLE.Warning(1, "error, stat file \"%s\" failed: %s",
+ pathname, strerror(errno));
+ return -1;
+ }
+
+ if( S_IFREG & sb.st_mode ){
+ pbf = _new_bfnode();
+#ifndef WINDOWS
+ if( !pbf ) return -1;
+#endif
+ pbf->bf_length = m_total_files_length = sb.st_size;
+ pbf->bf_filename = new char[strlen(pathname) + 1];
+#ifndef WINDOWS
+ if( !pbf->bf_filename ) return -1;
+#endif
+ strcpy(pbf->bf_filename, pathname);
+ m_btfhead = pbf;
+ }else if( S_IFDIR & sb.st_mode ){
+ char wd[MAXPATHLEN];
+ if( !getcwd(wd,MAXPATHLEN) ) return -1;
+ m_directory = new char[strlen(pathname) + 1];
+#ifndef WINDOWS
+ if( !m_directory ) return -1;
+#endif
+ strcpy(m_directory, pathname);
+
+ if(chdir(m_directory) < 0){
+ CONSOLE.Warning(1, "error, change work directory to \"%s\" failed: %s",
+ m_directory, strerror(errno));
+ return -1;
+ }
+
+ if(_btf_recurses_directory((const char*)0, &lastnode) < 0) return -1;
+ if( chdir(wd) < 0) return -1;
+ }else{
+ CONSOLE.Warning(1, "error, \"%s\" is not a directory or regular file.",
+ pathname);
+ return -1;
+ }
+ return 0;
+}
+
+int btFiles::BuildFromMI(const char *metabuf, const size_t metabuf_len, const char *saveas)
+{
+ char path[MAXPATHLEN];
+ const char *s, *p;
+ size_t r,q,n;
+ int64_t t;
+ int f_warned = 0;
+
+ if( !decode_query(metabuf, metabuf_len, "info|name", &s, &q, (int64_t*)0,
+ QUERY_STR) || MAXPATHLEN <= q )
+ return -1;
+
+ memcpy(path, s, q);
+ path[q] = '\0';
+
+ r = decode_query(metabuf, metabuf_len, "info|files", (const char**)0, &q,
+ (int64_t*)0, QUERY_POS);
+
+ if( r ){
+ BTFILE *pbf_last = (BTFILE*) 0;
+ BTFILE *pbf = (BTFILE*) 0;
+ size_t dl;
+ if( decode_query(metabuf,metabuf_len,"info|length",
+ (const char**) 0,(size_t*) 0,(int64_t*) 0,QUERY_LONG) )
+ return -1;
+
+ if( saveas ){
+ m_directory = new char[strlen(saveas) + 1];
+#ifndef WINDOWS
+ if(!m_directory) return -1;
+#endif
+ strcpy(m_directory,saveas);
+ }else{
+ int f_conv;
+ char *tmpfn = new char[strlen(path)*2+5];
+#ifndef WINDOWS
+ if( !tmpfn ) return -1;
+#endif
+ if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){
+ if( arg_flg_convert_filenames ){
+ m_directory = new char[strlen(tmpfn) + 1];
+#ifndef WINDOWS
+ if( !m_directory ){
+ delete []tmpfn;
+ return -1;
+ }
+#endif
+ strcpy(m_directory,tmpfn);
+ }else{
+ CONSOLE.Warning(3,
+ "Dir name contains non-printable characters; use -T to convert.");
+ f_warned = 1;
+ }
+ }
+ delete []tmpfn;
+ if( !f_conv || !arg_flg_convert_filenames ){
+ m_directory = new char[strlen(path) + 1];
+#ifndef WINDOWS
+ if( !m_directory ) return -1;
+#endif
+ strcpy(m_directory,path);
+ }
+ }
+
+ /* now r saved the pos of files list. q saved list length */
+ p = metabuf + r + 1;
+ q--;
+ for(; q && 'e' != *p; p += dl, q -= dl){
+ if(!(dl = decode_dict(p, q, (const char*) 0)) ) return -1;
+ if( !decode_query(p, dl, "length", (const char**) 0,
+ (size_t*) 0,&t,QUERY_LONG) ) return -1;
+ pbf = _new_bfnode();
+#ifndef WINDOWS
+ if( !pbf ) return -1;
+#endif
+ pbf->bf_length = t;
+ m_total_files_length += t;
+ r = decode_query(p, dl, "path", (const char **)0, &n, (int64_t*)0,
+ QUERY_POS);
+ if( !r ) return -1;
+ if(!decode_list2path(p + r, n, path)) return -1;
+
+ int f_conv;
+ char *tmpfn = new char[strlen(path)*2+5];
+#ifndef WINDOWS
+ if( !tmpfn ) return -1;
+#endif
+ if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){
+ if( arg_flg_convert_filenames ){
+ pbf->bf_filename = new char[strlen(tmpfn) + 1];
+#ifndef WINDOWS
+ if( !pbf->bf_filename ){
+ delete []tmpfn;
+ return -1;
+ }
+#endif
+ strcpy(pbf->bf_filename, tmpfn);
+ }else if(!f_warned){
+ CONSOLE.Warning(3,
+ "Filename contains non-printable characters; use -T to convert.");
+ f_warned = 1;
+ }
+ }
+ delete []tmpfn;
+ if( !f_conv || !arg_flg_convert_filenames ){
+ pbf->bf_filename = new char[strlen(path) + 1];
+#ifndef WINDOWS
+ if( !pbf->bf_filename ) return -1;
+#endif
+ strcpy(pbf->bf_filename, path);
+ }
+ if(pbf_last) pbf_last->bf_next = pbf; else m_btfhead = pbf;
+ pbf_last = pbf;
+ }
+ }else{
+ if( !decode_query(metabuf,metabuf_len,"info|length",
+ (const char**) 0,(size_t*) 0,&t,QUERY_LONG) )
+ return -1;
+ m_btfhead = _new_bfnode();
+#ifndef WINDOWS
+ if( !m_btfhead) return -1;
+#endif
+ m_btfhead->bf_length = m_total_files_length = t;
+ if( saveas ){
+ m_btfhead->bf_filename = new char[strlen(saveas) + 1];
+#ifndef WINDOWS
+ if(!m_btfhead->bf_filename ) return -1;
+#endif
+ strcpy(m_btfhead->bf_filename, saveas);
+ }else if( arg_flg_convert_filenames ){
+ char *tmpfn = new char[strlen(path)*2+5];
+#ifndef WINDOWS
+ if( !tmpfn ) return -1;
+#endif
+ ConvertFilename(tmpfn, path, strlen(path)*2+5);
+ m_btfhead->bf_filename = new char[strlen(tmpfn) + 1];
+#ifndef WINDOWS
+ if( !m_btfhead->bf_filename ){
+ delete []tmpfn;
+ return -1;
+ }
+#endif
+ strcpy(m_btfhead->bf_filename, tmpfn);
+ delete []tmpfn;
+ }else{
+ m_btfhead->bf_filename = new char[strlen(path) + 1];
+#ifndef WINDOWS
+ if(!m_btfhead->bf_filename ) return -1;
+#endif
+ strcpy(m_btfhead->bf_filename, path);
+ }
+ }
+ return 0;
+}
+
+int btFiles::CreateFiles()
+{
+ int check_exist = 0;
+ char fn[MAXPATHLEN];
+ BTFILE *pbt = m_btfhead;
+ struct stat sb;
+ int i = 0;
+
+ for(; pbt; pbt = pbt->bf_next){
+ m_nfiles++;
+
+ if( m_directory ){
+ if( MAXPATHLEN <= snprintf(fn, MAXPATHLEN, "%s%c%s",
+ m_directory, PATH_SP, pbt->bf_filename) ){
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }else{
+ strcpy(fn, pbt->bf_filename);
+ }
+
+ if(stat(fn, &sb) < 0){
+ if(ENOENT == errno){
+ CONSOLE.Interact_n("");
+ CONSOLE.Interact_n("Creating file \"%s\"", fn);
+ if( !_btf_creat_by_path(fn,pbt->bf_length)){
+ CONSOLE.Warning(1, "error, create file \"%s\" failed: %s", fn,
+ strerror(errno));
+ return -1;
+ }
+ }else{
+ CONSOLE.Warning(1, "error, couldn't create file \"%s\": %s", fn,
+ strerror(errno));
+ return -1;
+ }
+ }else{
+ if( !check_exist) check_exist = 1;
+ if( !(S_IFREG & sb.st_mode) ){
+ CONSOLE.Warning(1, "error, file \"%s\" is not a regular file.", fn);
+ return -1;
+ }
+ if(sb.st_size != pbt->bf_length){
+ CONSOLE.Warning(1,"error, file \"%s\" size doesn't match; must be %llu",
+ fn, (unsigned long long)(pbt->bf_length));
+ return -1;
+ }
+ }
+ } //end for
+
+ m_file = new BTFILE *[m_nfiles];
+ if( !m_file ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for files list");
+ return -1;
+ }
+ for( pbt = m_btfhead; pbt; pbt = pbt->bf_next ){
+ m_file[i++] = pbt;
+ }
+ return check_exist;
+}
+
+void btFiles::PrintOut()
+{
+ BTFILE *p = m_btfhead;
+ size_t id = 0;
+ CONSOLE.Print("");
+ CONSOLE.Print("FILES INFO");
+ BitField tmpBitField, tmpFilter;
+ if(m_directory) CONSOLE.Print("Directory: %s", m_directory);
+ for( ; p ; p = p->bf_next ){
+ ++id;
+ CONSOLE.Print_n("");
+ CONSOLE.Print_n("<%d> %s%s [%llu]", (int)id, m_directory ? " " : "",
+ p->bf_filename, (unsigned long long)(p->bf_length));
+ if( !arg_flg_exam_only ){
+ BTCONTENT.SetTmpFilter(id, &tmpFilter);
+ tmpBitField = *BTCONTENT.pBF;
+ tmpBitField.Except(tmpFilter);
+ CONSOLE.Print_n(" %d/%d (%d%%)",
+ (int)(tmpBitField.Count()), (int)(GetFilePieces(id)),
+ GetFilePieces(id) ?
+ (100 * tmpBitField.Count() / GetFilePieces(id)) : 100);
+ }
+ }
+ CONSOLE.Print("Total: %lu MB",
+ (unsigned long)(m_total_files_length/1024/1024));
+}
+
+size_t btFiles::FillMetaInfo(FILE* fp)
+{
+ BTFILE *p;
+ if( m_directory ){
+ // multi files
+ if( bencode_str("files", fp) != 1 ) return 0;
+
+ if( bencode_begin_list(fp) != 1) return 0;
+
+ for( p = m_btfhead; p; p = p->bf_next){
+ if( bencode_begin_dict(fp) != 1) return 0;
+
+ if( bencode_str("length", fp) != 1 ) return 0;
+ if( bencode_int(p->bf_length, fp) != 1) return 0;
+
+ if( bencode_str("path", fp) != 1) return 0;
+ if( bencode_path2list(p->bf_filename, fp) != 1 ) return 0;
+
+ if( bencode_end_dict_list(fp) != 1) return 0;
+ }
+
+ if(bencode_end_dict_list(fp) != 1 ) return 0;
+
+ if(bencode_str("name", fp) != 1) return 0;
+ return bencode_str(m_directory, fp);
+
+ }else{
+ if( bencode_str("length", fp) != 1 ) return 0;
+ if( bencode_int(m_btfhead->bf_length, fp) != 1) return 0;
+
+ if( bencode_str("name", fp) != 1 ) return 0;
+ return bencode_str(m_btfhead->bf_filename, fp);
+ }
+ return 1;
+}
+
+
+void btFiles::SetFilter(int nfile, BitField *pFilter, size_t pieceLength)
+{
+ BTFILE *p = m_btfhead;
+ size_t id = 0;
+ uint64_t sizeBuffer=0;
+ size_t index;
+
+ if( nfile==0 || nfile>m_nfiles ){
+ pFilter->Clear();
+ return;
+ }
+
+ pFilter->SetAll();
+ for( ; p ; p = p->bf_next ){
+ if(++id == nfile){
+ if( 0 == p->bf_length ){
+ p->bf_npieces = 0;
+ return;
+ }
+ size_t start, stop;
+ start = sizeBuffer / pieceLength;
+ stop = (sizeBuffer + p->bf_length) / pieceLength;
+ // calculation is off if file ends on a piece boundary
+ if(stop > start && 0 == (sizeBuffer + p->bf_length) % pieceLength)
+ --stop;
+ p->bf_npieces = stop - start + 1;
+ for(index = start; index <= stop; index++) {
+ pFilter->UnSet(index);
+ }
+ break;
+ }
+ sizeBuffer += p->bf_length;
+ }
+}
+
+char *btFiles::GetFileName(size_t nfile) const
+{
+ if( nfile && nfile <= m_nfiles )
+ return m_file[nfile-1]->bf_filename;
+ return (char *)0;
+}
+
+uint64_t btFiles::GetFileSize(size_t nfile) const
+{
+ if( nfile && nfile <= m_nfiles )
+ return m_file[nfile-1]->bf_length;
+ return 0;
+}
+
+size_t btFiles::GetFilePieces(size_t nfile) const
+{
+ //returns the number of pieces in the file
+ if( nfile && nfile <= m_nfiles )
+ return m_file[nfile-1]->bf_npieces;
+ return 0;
+}
+
+int btFiles::ConvertFilename(char *dst, const char *src, int size)
+{
+ int retval=0, i, j, f_print=0, f_punct=0;
+
+ for(i=j=0; src[i] != '\0' && j < size-2; i++){
+ if( isprint(src[i]) ){
+ if( ispunct(src[i]) ) f_punct = 1;
+ else f_punct = 0;
+ if(j && !f_print && !f_punct){ sprintf(dst+j, "_"); j++; }
+ dst[j++] = src[i];
+ f_print = 1;
+ }else{
+ if(f_print && !f_punct){ sprintf(dst+j, "_"); j++; }
+ snprintf(dst+j, 3, "%.2X", (unsigned char)(src[i]));
+ j += 2;
+ f_print = f_punct = 0;
+ if( !retval ) retval = 1;
+ }
+ }
+ dst[j] = '\0';
+ return retval;
+}
+
+char *btFiles::GetDataName() const
+{
+ return m_directory ? m_directory : m_btfhead->bf_filename;
+}
+
diff --git a/btfiles.h b/btfiles.h
new file mode 100644
index 0000000..ebb4b71
--- a/dev/null
+++ b/btfiles.h
@@ -0,0 +1,81 @@
+#ifndef BTFILES_H
+#define BTFILES_H
+
+#include "./def.h"
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "bitfield.h"
+#include "btconfig.h"
+
+typedef struct _btfile{
+ char *bf_filename; // full path of file.
+ uint64_t bf_length;
+ FILE *bf_fp;
+ char *bf_buffer;
+
+ time_t bf_last_timestamp; // last io timestamp.
+
+ size_t bf_npieces; //number of pieces
+
+ unsigned char bf_flag_opened:1;
+ unsigned char bf_flag_readonly:1;
+ unsigned char bf_reserved:6;
+
+ struct _btfile *bf_next;
+}BTFILE;
+
+
+class btFiles
+{
+ private:
+
+ BTFILE *m_btfhead;
+ char *m_directory;
+ uint64_t m_total_files_length;
+ size_t m_total_opened; // already opened
+ size_t m_nfiles;
+ BTFILE **m_file;
+
+ uint8_t m_flag_automanage:1;
+ uint8_t m_flag_reserved:7; // current version not implement
+
+ BTFILE* _new_bfnode();
+ int _btf_close_oldest();
+ int _btf_close(BTFILE *pbf);
+ int _btf_open(BTFILE *pbf, const int iotype);
+ int _btf_ftruncate(int fd, int64_t length);
+ int _btf_creat_by_path(const char *pathname, int64_t file_length);
+ int _btf_destroy();
+ int _btf_recurses_directory(const char *cur_path, BTFILE **plastnode);
+ int ConvertFilename(char *dst, const char *src, int size);
+
+ public:
+ int CreateFiles();
+ void CloseFile(size_t nfile);
+
+ btFiles();
+ ~btFiles();
+
+ int BuildFromFS(const char *pathname);
+ int BuildFromMI(const char *metabuf, const size_t metabuf_len,
+ const char *saveas);
+
+ char *GetDataName() const;
+ uint64_t GetTotalLength() const { return m_total_files_length; }
+ ssize_t IO(char *buf, uint64_t off, size_t len, const int iotype);
+ size_t FillMetaInfo(FILE* fp);
+
+ void SetFilter(int nfile, BitField *pFilter, size_t pieceLength);
+
+ size_t GetNFiles() const { return m_nfiles; }
+ char *GetFileName(size_t nfile) const;
+ uint64_t GetFileSize(size_t nfile) const;
+ size_t GetFilePieces(size_t nfile) const;
+
+ void PrintOut();
+};
+
+#endif
diff --git a/btfiles.o b/btfiles.o
new file mode 100644
index 0000000..f635f26
--- a/dev/null
+++ b/btfiles.o
Binary files differ
diff --git a/btrequest.cpp b/btrequest.cpp
new file mode 100644
index 0000000..de8f2a6
--- a/dev/null
+++ b/btrequest.cpp
@@ -0,0 +1,651 @@
+#include "btrequest.h" // def.h
+
+#include <stdlib.h>
+
+#include "btcontent.h"
+#include "btconfig.h"
+#include "console.h"
+
+#ifndef HAVE_RANDOM
+#include "compat.h"
+#endif
+
+
+static void _empty_slice_list(PSLICE *ps_head)
+{
+ PSLICE p;
+ for(; *ps_head;){
+ p = (*ps_head)->next;
+ delete (*ps_head);
+ *ps_head = p;
+ }
+}
+
+RequestQueue::~RequestQueue()
+{
+ if( rq_head ) _empty_slice_list(&rq_head);
+}
+
+RequestQueue::RequestQueue()
+{
+ rq_head = (PSLICE) 0;
+ rq_send = rq_head;
+}
+
+void RequestQueue::Empty()
+{
+ if(rq_head) _empty_slice_list(&rq_head);
+ rq_send = rq_head;
+}
+
+void RequestQueue::SetHead(PSLICE ps)
+{
+ if( rq_head ) _empty_slice_list(&rq_head);
+ rq_head = ps;
+ rq_send = rq_head;
+}
+
+void RequestQueue::operator=(RequestQueue &rq)
+{
+ PSLICE n, u = (PSLICE) 0;
+ size_t idx;
+ int flag = 0;
+
+ if( rq_head ) _empty_slice_list(&rq_head);
+ rq_head = rq.rq_head;
+ rq_send = rq_head;
+
+ // Reassign only the first piece represented in the queue.
+ n = rq_head;
+ idx = n->index;
+ for( ; n ; u = n,n = u->next ){
+ if( rq.rq_send == n ) flag = 1;
+ if( n->index != idx ) break;
+ }
+ if(n){
+ u->next = (PSLICE) 0;
+ rq.rq_head = n;
+ if(flag) rq.rq_send = rq.rq_head;
+ }else{
+ rq.rq_head = (PSLICE) 0;
+ rq.rq_send = rq.rq_head;
+ }
+}
+
+int RequestQueue::Copy(const RequestQueue *prq, size_t idx)
+{
+ PSLICE n, u, ps;
+ int found = 0;
+
+ if( prq->IsEmpty() ) return 0;
+
+ n = rq_head;
+ u = (PSLICE)0;
+ for( ; n ; u = n, n = u->next ); // move to end
+
+ ps = prq->GetHead();
+ for( ; ps; ps = ps->next ){
+ if( ps->index != idx ){
+ if( found ) break;
+ else continue;
+ }else found = 1;
+ if( Add(ps->index, ps->offset, ps->length) < 0 ){
+ PSLICE temp;
+ for( n = u ? u->next : rq_head; n; n=temp ){
+ temp = n->next;
+ delete n;
+ }
+ if( u ) u->next = (PSLICE)0;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int RequestQueue::CopyShuffle(const RequestQueue *prq, size_t idx)
+{
+ PSLICE n, u, ps, prev, end, psnext, temp;
+ SLICE dummy;
+ unsigned long rndbits;
+ int len, shuffle, i=0, setsend=0;
+ size_t firstoff;
+
+ if( prq->IsEmpty() ) return 0;
+
+ n = rq_head;
+ u = (PSLICE)0;
+ for( ; n ; u = n, n = u->next ); // move to end
+
+ if( !rq_send ) setsend = 1;
+
+ ps = prq->GetHead();
+ for( ; ps && ps->index != idx; ps = ps->next );
+ if( !ps ) return -1;
+ firstoff = ps->offset;
+ for( len=0; ps && ps->index == idx; ps = ps->next ){
+ if( Add(ps->index, ps->offset, ps->length) < 0 ){
+ for( n = u ? u->next : rq_head; n; n=temp ){
+ temp = n->next;
+ delete n;
+ }
+ if( u ) u->next = (PSLICE)0;
+ return -1;
+ }
+ len++;
+ }
+ if( !u ){
+ u = &dummy;
+ u->next = rq_head;
+ }
+
+ shuffle = (random()&0x07)+2;
+ if( shuffle > len/2 ) shuffle = len/2;
+ for( ; shuffle; shuffle-- ){
+ prev = u;
+ ps = u->next->next;
+ u->next->next = (PSLICE)0;
+ end = u->next;
+ for( ; ps; ps = psnext ){
+ psnext = ps->next;
+ if( !i-- ){
+ rndbits = random();
+ i = sizeof(rndbits) - 3; // insure an extra bit
+ }
+ if( (rndbits>>=1)&01 ){ // beginning or end of list
+ if( (rndbits>>=1)&01 ){
+ prev = end;
+ ps->next = (PSLICE)0;
+ end->next = ps;
+ end = ps;
+ }else{
+ ps->next = u->next;
+ u->next = ps;
+ prev = u;
+ }
+ }else{ // before or after previous insertion
+ if( (rndbits>>=1)&01 ){ // put after prev->next
+ if( end == prev->next ) end = ps;
+ temp = prev->next;
+ ps->next = prev->next->next;
+ prev->next->next = ps;
+ prev = temp;
+ }else{ // put after prev (before prev->next)
+ ps->next = prev->next;
+ prev->next = ps;
+ }
+ }
+ }
+ } // shuffle loop
+
+ // If first slice is the same as in the original, move it to the end.
+ if( u->next->offset == firstoff ){
+ end->next = u->next;
+ u->next = u->next->next;
+ end = end->next;
+ end->next = (PSLICE)0;
+ }
+ if( u == &dummy ) rq_head = u->next;
+ if( setsend ) rq_send = u->next;
+
+ return 0;
+}
+
+// Counts all queued slices.
+size_t RequestQueue::Qsize() const
+{
+ size_t cnt = 0;
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+
+ for( ; n ; u = n,n = u->next ) cnt++; // move to end
+ return cnt;
+}
+
+// Counts only slices from one piece.
+size_t RequestQueue::Qlen(size_t piece) const
+{
+ size_t cnt = 0;
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+ size_t idx;
+
+ for( ; n && n->index != piece; n = n->next );
+
+ if(n) idx = n->index;
+ for( ; n ; u = n,n = u->next ){
+ if( n->index != idx ) break;
+ cnt++;
+ }
+ return cnt;
+}
+
+int RequestQueue::LastSlice() const
+{
+ return ( rq_head &&
+ (!rq_head->next || rq_head->index != rq_head->next->index) ) ? 1 : 0;
+}
+
+int RequestQueue::Insert(PSLICE ps,size_t idx,size_t off,size_t len)
+{
+ PSLICE n;
+
+ n = new SLICE;
+
+#ifndef WINDOWS
+ if( !n ) return -1;
+#endif
+
+ n->index = idx;
+ n->offset = off;
+ n->length = len;
+ n->reqtime = (time_t) 0;
+
+ // ps is the slice to insert after; if 0, insert at the head.
+ if(ps){
+ n->next = ps->next;
+ ps->next = n;
+ if( rq_send == n->next ) rq_send = n;
+ }else{
+ n->next = rq_head;
+ rq_head = n;
+ rq_send = rq_head;
+ }
+
+ return 0;
+}
+
+int RequestQueue::Add(size_t idx,size_t off,size_t len)
+{
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+
+ for( ; n ; u = n,n = u->next ); // move to end
+
+ n = new SLICE;
+
+#ifndef WINDOWS
+ if( !n ) return -1;
+#endif
+
+ n->next = (PSLICE) 0;
+ n->index = idx;
+ n->offset = off;
+ n->length = len;
+ n->reqtime = (time_t) 0;
+
+ if( u ) u->next = n;
+ else{
+ rq_head = n;
+ rq_send = rq_head;
+ }
+
+ if( !rq_send ) rq_send = n;
+
+ return 0;
+}
+
+int RequestQueue::Append(PSLICE ps)
+{
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+
+ for( ; n ; u = n,n = u->next ); // move to end
+
+ if(u) u->next = ps;
+ else rq_head = ps;
+
+ if( !rq_send ) rq_send = ps;
+
+ return 0;
+}
+
+int RequestQueue::Remove(size_t idx,size_t off,size_t len)
+{
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+
+ for( ; n ; u = n, n = u->next ){
+ if( n->index == idx && n->offset == off && n->length == len ) break;
+ }
+
+ if( !n ) return -1; /* not found */
+
+ if( u ) u->next = n->next; else rq_head = n->next;
+ if( rq_send == n ) rq_send = n->next;
+ delete n;
+
+ return 0;
+}
+
+// Add a slice at an appropriate place in the queue.
+// returns -1 if failed, 1 if request needs to be sent.
+int RequestQueue::Requeue(size_t idx,size_t off,size_t len)
+{
+ int f_send, retval;
+ PSLICE n = rq_head;
+ PSLICE u = (PSLICE) 0;
+ PSLICE save_send = rq_send;
+
+ // find last slice of same piece
+ if( rq_send ) f_send = 1;
+ for( ; n ; u = n,n = u->next ){
+ if( rq_send == u ) f_send = 0;
+ if( u && idx == u->index && idx != n->index ) break;
+ }
+ if( !u ) f_send = 1;
+
+ retval = ( Insert(u,idx,off,len) < 0 ) ? -1 : f_send;
+ rq_send = save_send;
+ return retval;
+}
+
+// Move the slice to the end of its piece sequence.
+void RequestQueue::MoveLast(PSLICE ps)
+{
+ PSLICE n, u;
+
+ for( n = rq_head; n && n->next != ps; n = n->next );
+ if( !n || !ps ) return;
+ for( u = ps; u->next && u->next->index == ps->index; u = u->next );
+ if( u == ps ) return;
+
+ if( rq_send == ps ) rq_send = ps->next;
+ else if( rq_send == u->next ) rq_send = ps;
+ n->next = ps->next;
+ ps->next = u->next;
+ u->next = ps;
+}
+
+int RequestQueue::HasIdx(size_t idx) const
+{
+ PSLICE n = rq_head;
+
+ for( ; n ; n = n->next ){
+ if(n->index == idx) break;
+ }
+
+ return n ? 1 : 0;
+}
+
+int RequestQueue::HasSlice(size_t idx, size_t off, size_t len) const
+{
+ PSLICE n = rq_head;
+
+ for( ; n ; n = n->next ){
+ if( n->index == idx && n->offset == off && n->length == len ) break;
+ }
+
+ return n ? 1 : 0;
+}
+
+time_t RequestQueue::GetReqTime(size_t idx,size_t off,size_t len) const
+{
+ PSLICE n = rq_head;
+
+ for( ; n ; n = n->next ){
+ if( n->index == idx && n->offset == off && n->length == len ) break;
+ }
+
+ if( !n ) return (time_t)0; /* not found */
+
+ return n->reqtime;
+}
+
+void RequestQueue::SetReqTime(PSLICE n,time_t t)
+{
+ n->reqtime = t;
+}
+
+int RequestQueue::Pop(size_t *pidx,size_t *poff,size_t *plen)
+{
+ PSLICE n;
+
+ if( !rq_head ) return -1;
+
+ n = rq_head->next;
+
+ if(pidx) *pidx = rq_head->index;
+ if(poff) *poff = rq_head->offset;
+ if(plen) *plen = rq_head->length;
+
+ if( rq_send == rq_head ) rq_send = n;
+ delete rq_head;
+
+ rq_head = n;
+
+ return 0;
+}
+
+int RequestQueue::Peek(size_t *pidx,size_t *poff,size_t *plen) const
+{
+ if( !rq_head ) return -1;
+
+ if(pidx) *pidx = rq_head->index;
+ if(poff) *poff = rq_head->offset;
+ if(plen) *plen = rq_head->length;
+
+ return 0;
+}
+
+int RequestQueue::CreateWithIdx(size_t idx)
+{
+ size_t i,off,len,ns;
+
+ ns = NSlices(idx);
+
+ for( i = off = 0; i < ns; i++ ){
+ len = Slice_Length(idx,i);
+ if( Add(idx,off,len) < 0 ) return -1;
+ off += len;
+ }
+
+ return 0;
+}
+
+size_t RequestQueue::Slice_Length(size_t idx,size_t sidx) const
+{
+ size_t plen = BTCONTENT.GetPieceLength(idx);
+
+ return (sidx == ( plen / cfg_req_slice_size)) ?
+ (plen % cfg_req_slice_size) :
+ cfg_req_slice_size;
+}
+
+size_t RequestQueue::NSlices(size_t idx) const
+{
+ size_t r,n;
+ r = BTCONTENT.GetPieceLength(idx);
+ n = r / cfg_req_slice_size;
+ return ( r % cfg_req_slice_size ) ? n + 1 : n;
+}
+
+int RequestQueue::IsValidRequest(size_t idx,size_t off,size_t len) const
+{
+ return ( idx < BTCONTENT.GetNPieces() &&
+ len &&
+ (off + len) <= BTCONTENT.GetPieceLength(idx) &&
+ len <= cfg_max_slice_size ) ?
+ 1 : 0;
+}
+
+// ****************************** PendingQueue ******************************
+
+PendingQueue PENDINGQUEUE;
+
+PendingQueue::PendingQueue()
+{
+ int i = 0;
+ for(; i < PENDING_QUEUE_SIZE; i++) pending_array[i] = (PSLICE) 0;
+ pq_count = 0;
+}
+
+PendingQueue::~PendingQueue()
+{
+ if(pq_count) Empty();
+}
+
+void PendingQueue::Empty()
+{
+ int i = 0;
+ for ( ; i < PENDING_QUEUE_SIZE && pq_count; i++ )
+ if( pending_array[i] != (PSLICE) 0 ){
+ _empty_slice_list(&(pending_array[i]));
+ pq_count--;
+ }
+}
+
+int PendingQueue::Exist(size_t idx) const
+{
+ int i, j = 0;
+ for ( i = 0; i < PENDING_QUEUE_SIZE && j < pq_count; i++ ){
+ if( pending_array[i] ){
+ j++;
+ if( idx == pending_array[i]->index ) return 1;
+ }
+ }
+ return 0;
+}
+
+int PendingQueue::HasSlice(size_t idx, size_t off, size_t len)
+{
+ int i, j = 0;
+ for( i = 0; i < PENDING_QUEUE_SIZE && j < pq_count; i++ ){
+ if( pending_array[i] ){
+ j++;
+ if( idx == pending_array[i]->index &&
+ off == pending_array[i]->offset && len == pending_array[i]->length )
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Sending an empty queue to this function WILL cause a crash. This exposure
+ is left open in order to help track down bugs that cause this condition.
+ Returns:
+ 0 if all pieces were added to Pending
+ -1 if Pending is full (at least one piece not added)
+ 1 if at least one piece was already in Pending
+*/
+int PendingQueue::Pending(RequestQueue *prq)
+{
+ int retval = 0;
+ int i = 0, j = -1;
+ PSLICE n, u = (PSLICE) 0;
+ size_t idx, off, len;
+ RequestQueue tmprq;
+
+ if( pq_count >= PENDING_QUEUE_SIZE ){
+ prq->Empty();
+ return -1;
+ }
+ if( prq->Qlen(prq->GetRequestIdx()) >=
+ BTCONTENT.GetPieceLength() / cfg_req_slice_size ){
+ // This shortcut relies on the fact that we don't add to a queue if it
+ // already contains a full piece.
+ prq->Empty();
+ return 0;
+ }
+
+ for( ; i < PENDING_QUEUE_SIZE; i++ ){
+ if( pending_array[i] == (PSLICE)0 ){
+ // Find an empty slot in case we need it.
+ if(j<0) j = i;
+ }else if( prq->GetRequestIdx() == pending_array[i]->index ){
+ // Don't add a piece to Pending more than once.
+ while( !prq->IsEmpty() &&
+ prq->GetRequestIdx() == pending_array[i]->index )
+ prq->Pop(&idx,&off,&len);
+ retval = 1;
+ if( prq->IsEmpty() ) return retval;
+ i = 0;
+ }
+ }
+ pending_array[j] = prq->GetHead();
+ prq->Release();
+ pq_count++;
+
+ // If multiple pieces are queued, break up the queue separately.
+ n = pending_array[j];
+ idx = n->index;
+ for( ; n ; u = n, n = u->next ){
+ if( n->index != idx ) break;
+ n->reqtime = (time_t)0;
+ }
+ if(n){
+ u->next = (PSLICE) 0;
+ tmprq.SetHead(n);
+ i = Pending(&tmprq);
+ if( i < 0 ) retval = i;
+ else if( i > 0 && retval == 0 ) retval = i;
+ tmprq.Release();
+ }
+
+ return retval;
+}
+
+size_t PendingQueue::ReAssign(RequestQueue *prq, BitField &bf)
+{
+ int i = 0;
+ size_t sc = pq_count;
+ size_t idx = BTCONTENT.GetNPieces();
+
+ for( ; i < PENDING_QUEUE_SIZE && sc; i++ ){
+ if( pending_array[i] != (PSLICE) 0){
+ if( bf.IsSet(pending_array[i]->index) &&
+ !prq->HasIdx(pending_array[i]->index) ){
+ idx = pending_array[i]->index;
+ prq->Append(pending_array[i]);
+ pending_array[i] = (PSLICE) 0;
+ pq_count--;
+ Delete(idx); // delete any copies from Pending
+ break;
+ }
+ sc--;
+ }
+ }
+ // Return value now indicates the assigned piece or GetNPieces
+ return idx;
+}
+
+int PendingQueue::Delete(size_t idx)
+{
+ int i, j = 0, r = 0;
+ for ( i = 0; i < PENDING_QUEUE_SIZE && j < pq_count; i++ ){
+ if( pending_array[i] ){
+ j++;
+ if( idx == pending_array[i]->index ){
+ r = 1;
+ _empty_slice_list(&(pending_array[i]));
+ pq_count--;
+ break;
+ }
+ }
+ }
+ return r;
+}
+
+int PendingQueue::DeleteSlice(size_t idx, size_t off, size_t len)
+{
+ int i, j = 0, r = 0;
+ RequestQueue rq;
+ for( i = 0; i < PENDING_QUEUE_SIZE && j < pq_count; i++ ){
+ if( pending_array[i] ){
+ j++;
+ if( idx == pending_array[i]->index ){
+ //check if off & len match any slice
+ //remove the slice if so
+ rq.SetHead(pending_array[i]);
+ if( rq.Remove(idx, off, len) == 0 ){
+ r = 1;
+ pending_array[i] = rq.GetHead();
+ if( (PSLICE) 0 == pending_array[i] ) pq_count--;
+ i = PENDING_QUEUE_SIZE; // exit loop
+ }
+ rq.Release();
+ }
+ }
+ }
+ return r;
+}
+
diff --git a/btrequest.h b/btrequest.h
new file mode 100644
index 0000000..0ca576b
--- a/dev/null
+++ b/btrequest.h
@@ -0,0 +1,92 @@
+#ifndef SLICE_H
+#define SLICE_H
+
+#include "def.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include "btcontent.h"
+#include "bitfield.h"
+
+typedef struct _slice{
+ size_t index;
+ size_t offset;
+ size_t length;
+ time_t reqtime;
+ struct _slice *next;
+}SLICE,*PSLICE;
+
+class RequestQueue
+{
+ private:
+ PSLICE rq_head;
+ public:
+ PSLICE rq_send; // next slice to request
+
+ RequestQueue();
+ ~RequestQueue();
+
+ void Empty();
+
+ void SetHead(PSLICE ps);
+ void SetNextSend(PSLICE ps) { rq_send = ps; }
+ PSLICE GetHead() const { return rq_head; }
+ PSLICE NextSend() const { return rq_send; }
+ size_t GetRequestIdx() const { return rq_head ? rq_head->index :
+ BTCONTENT.GetNPieces(); }
+ size_t GetRequestLen() const { return rq_head ? rq_head->length : 0; }
+ void Release(){ rq_head = rq_send = (PSLICE) 0; }
+ int IsValidRequest(size_t idx,size_t off,size_t len) const;
+
+ void operator=(RequestQueue &rq);
+ int Copy(const RequestQueue *prq, size_t idx);
+ int CopyShuffle(const RequestQueue *prq, size_t idx);
+ size_t Qsize() const;
+ size_t Qlen(size_t piece) const;
+ int LastSlice() const;
+
+ int IsEmpty() const { return rq_head ? 0 : 1; }
+
+ int Insert(PSLICE ps,size_t idx,size_t off,size_t len);
+ int Add(size_t idx,size_t off,size_t len);
+ int Append(PSLICE ps);
+ int Remove(size_t idx,size_t off,size_t len);
+ int Requeue(size_t idx,size_t off,size_t len);
+ void MoveLast(PSLICE ps);
+ int HasIdx(size_t idx) const;
+ int HasSlice(size_t idx, size_t off, size_t len) const;
+ time_t GetReqTime(size_t idx,size_t off,size_t len) const;
+ void SetReqTime(PSLICE n,time_t t);
+
+
+ int Pop(size_t *pidx,size_t *poff,size_t *plen);
+ int Peek(size_t *pidx,size_t *poff,size_t *plen) const;
+
+ int CreateWithIdx(size_t idx);
+ size_t NSlices(size_t idx) const;
+ size_t Slice_Length(size_t idx,size_t sidx) const;
+};
+
+#define PENDING_QUEUE_SIZE 100
+
+class PendingQueue
+{
+ private:
+ PSLICE pending_array[PENDING_QUEUE_SIZE];
+ size_t pq_count;
+
+ public:
+ PendingQueue();
+ ~PendingQueue();
+ void Empty();
+ int Pending(RequestQueue *prq);
+ size_t ReAssign(RequestQueue *prq, BitField &bf);
+ int Exist(size_t idx) const;
+ int HasSlice(size_t idx, size_t off, size_t len);
+ int Delete(size_t idx);
+ int DeleteSlice(size_t idx, size_t off, size_t len);
+};
+
+extern PendingQueue PENDINGQUEUE;
+
+#endif
diff --git a/btstream.cpp b/btstream.cpp
new file mode 100644
index 0000000..a0859fe
--- a/dev/null
+++ b/btstream.cpp
@@ -0,0 +1,195 @@
+#include "btstream.h" // def.h
+
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <sys/time.h>
+#include <string.h> // memcpy
+
+#include "msgencode.h"
+#include "btconfig.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+#include "compat.h"
+#endif
+
+size_t get_nl(char *from)
+{
+ // assumes H_INT_LEN==H_LEN==4
+ uint32_t t = 0;
+ memcpy(&t, from, H_INT_LEN);
+ return (size_t)ntohl((unsigned long)t);
+}
+
+void set_nl(char *to, size_t from)
+{
+ // assumes H_INT_LEN==H_LEN==4
+ uint32_t from32 = (uint32_t)htonl((unsigned long)from);
+ memcpy(to, &from32, H_INT_LEN);
+}
+
+ssize_t btStream::Flush()
+{
+ return out_buffer.FlushOut(sock);
+}
+
+ssize_t btStream::Send_State(unsigned char state)
+{
+ char msg[H_LEN + H_BASE_LEN];
+
+ set_nl(msg, H_BASE_LEN);
+ msg[H_LEN] = (char)state;
+ return out_buffer.Put(sock,msg,H_LEN + H_BASE_LEN);
+}
+
+ssize_t btStream::Send_Have(size_t idx)
+{
+ char msg[H_LEN + H_HAVE_LEN];
+
+ set_nl(msg, H_HAVE_LEN);
+ msg[H_LEN] = (char)M_HAVE;
+ set_nl(msg + H_LEN + H_BASE_LEN, idx);
+
+ return out_buffer.Put(sock,msg,H_LEN + H_HAVE_LEN);
+}
+
+ssize_t btStream::Send_Bitfield(char *bit_buf,size_t len)
+{
+ size_t q = htonl(len + H_BASE_LEN);
+ unsigned char t = M_BITFIELD;
+ ssize_t r = out_buffer.Put(sock,(char*)&q,H_LEN);
+ if(r < 0) return r;
+ r = out_buffer.Put(sock,(char*)&t,H_BASE_LEN);
+ if(r < 0) return r;
+ return out_buffer.Put(sock,bit_buf,len);
+}
+
+ssize_t btStream::Send_Cancel(size_t idx,size_t off,size_t len)
+{
+ char msg[H_LEN + H_CANCEL_LEN];
+
+ set_nl(msg, H_CANCEL_LEN);
+ msg[H_LEN] = M_CANCEL;
+ set_nl(msg + H_LEN + H_BASE_LEN, idx);
+ set_nl(msg + H_LEN + H_BASE_LEN + H_INT_LEN, off);
+ set_nl(msg + H_LEN + H_BASE_LEN + H_INT_LEN * 2, len);
+ return out_buffer.Put(sock,msg,H_LEN + H_CANCEL_LEN);
+}
+
+ssize_t btStream::Send_Piece(size_t idx,size_t off,char *piece_buf,size_t len)
+{
+ size_t q = htonl(len + H_PIECE_LEN);
+ unsigned char t = M_PIECE;
+ ssize_t r;
+
+ idx = htonl(idx);
+ off = htonl(off);
+ if( (r = out_buffer.Put(sock,(char*)&q,H_LEN)) < 0 ) return r;
+ if( (r = out_buffer.Put(sock,(char*)&t,H_BASE_LEN)) < 0 ) return r;
+ if( (r = out_buffer.Put(sock,(char*)&idx,H_INT_LEN)) < 0) return r;
+ if( (r = out_buffer.Put(sock,(char*)&off,H_INT_LEN)) < 0) return r;
+ return out_buffer.PutFlush(sock,piece_buf,len);
+}
+
+ssize_t btStream::Send_Request(size_t idx, size_t off,size_t len)
+{
+ char msg[H_LEN + H_REQUEST_LEN];
+
+ set_nl(msg, H_REQUEST_LEN);
+ msg[H_LEN] = (char)M_REQUEST;
+ set_nl(msg + H_LEN + H_BASE_LEN, idx);
+ set_nl(msg + H_LEN + H_BASE_LEN + H_INT_LEN, off);
+ set_nl(msg + H_LEN + H_BASE_LEN + H_INT_LEN * 2, len);
+ return out_buffer.Put(sock,msg,H_LEN + H_REQUEST_LEN);
+}
+
+ssize_t btStream::Send_Keepalive()
+{
+ size_t i = 0;
+ return out_buffer.Put(sock,(char*)&i,H_LEN);
+}
+
+int btStream::HaveMessage()
+{
+ // if message arrived.
+ size_t r;
+ if( H_LEN <= in_buffer.Count() ){
+ r = get_nl(in_buffer.BasePointer());
+ if( cfg_max_slice_size + H_LEN + H_PIECE_LEN < r )
+ return -1; //message too long
+ if( r + H_LEN <= in_buffer.Count() ) return 1;
+ }
+ return 0; //no message arrived
+}
+
+ssize_t btStream::Feed()
+{
+ return in_buffer.FeedIn(sock);
+}
+
+ssize_t btStream::Feed(Rate *rate)
+{
+ return Feed(0, rate);
+}
+
+ssize_t btStream::Feed(size_t limit, Rate *rate)
+{
+ ssize_t retval;
+ struct timespec nowspec;
+
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+ retval = in_buffer.FeedIn(sock, limit);
+
+ if( H_LEN + H_PIECE_LEN < in_buffer.Count() &&
+ M_PIECE == in_buffer.BasePointer()[H_LEN] ){
+ size_t r = get_nl(in_buffer.BasePointer());
+ if( r > H_PIECE_LEN ){
+ size_t change;
+ if( in_buffer.Count() >= r + H_LEN ){ // have the whole message
+ change = r - H_PIECE_LEN - m_oldbytes;
+ m_oldbytes = 0;
+ }else{
+ size_t nbytes = in_buffer.Count() - H_LEN - H_PIECE_LEN;
+ change = nbytes - m_oldbytes;
+ m_oldbytes = nbytes;
+ }
+ rate->RateAdd(change, (size_t)cfg_max_bandwidth_down,
+ nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000);
+ }
+ }
+ return retval;
+}
+
+ssize_t btStream::PickMessage()
+{
+ return in_buffer.PickUp( get_nl(in_buffer.BasePointer()) + H_LEN );
+}
+
+ssize_t btStream::Send_Buffer(char *buf, size_t len)
+{
+ return out_buffer.Put(sock,buf,len);
+}
+
+// Does not distinguish between keepalive, choke (msg 0), and no message.
+char btStream::PeekMessage()
+{
+ return ( H_LEN < in_buffer.Count() && get_nl(in_buffer.BasePointer()) ) ?
+ in_buffer.BasePointer()[H_LEN] : 0;
+}
+
+// Is the next message known to match m?
+int btStream::PeekMessage(char m)
+{
+ return ( H_LEN < in_buffer.Count() && m == in_buffer.BasePointer()[H_LEN] &&
+ get_nl(in_buffer.BasePointer()) ) ? 1 : 0;
+}
+
+// Is the next next message known to match m?
+int btStream::PeekNextMessage(char m)
+{
+ char *base;
+
+ base = in_buffer.BasePointer() + H_LEN + get_nl(in_buffer.BasePointer());
+ return ( H_LEN < in_buffer.Count() - (base - in_buffer.BasePointer()) &&
+ m == base[H_LEN] && get_nl(base) ) ? 1 : 0;
+}
+
diff --git a/btstream.h b/btstream.h
new file mode 100644
index 0000000..f3a7e0e
--- a/dev/null
+++ b/btstream.h
@@ -0,0 +1,66 @@
+#ifndef BTSTREAM_H
+#define BTSTREAM_H
+
+#include "./def.h"
+#include "./bufio.h"
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "rate.h"
+
+size_t get_nl(char *from);
+void set_nl(char *to, size_t from);
+
+class btStream
+{
+private:
+ SOCKET sock, sock_was;
+ size_t m_oldbytes;
+
+public:
+ BufIo in_buffer;
+ BufIo out_buffer;
+
+ btStream() { sock = sock_was = INVALID_SOCKET; m_oldbytes = 0; }
+ ~btStream() { if( INVALID_SOCKET != sock) CLOSE_SOCKET(sock); }
+
+ SOCKET GetSocket() { return (INVALID_SOCKET==sock) ? sock_was : sock; }
+ void SetSocket(SOCKET sk){ sock = sk; }
+
+ void Close(){
+ if( INVALID_SOCKET != sock ){
+ CLOSE_SOCKET(sock);
+ sock_was = sock;
+ sock = INVALID_SOCKET;
+ }
+ in_buffer.Close();
+ out_buffer.Close();
+ }
+
+ ssize_t PickMessage(); //移除接收缓存中的一条消息
+ ssize_t Feed();
+ ssize_t Feed(Rate *rate);
+ ssize_t Feed(size_t limit, Rate *rate);
+
+ int HaveMessage(); // 返回值 1: 缓存中有消息 0: 暂无消息 -1: 失败
+ char PeekMessage();
+ int PeekMessage(char m);
+ int PeekNextMessage(char m);
+
+ ssize_t Send_Keepalive();
+ ssize_t Send_State(unsigned char state);
+ ssize_t Send_Have(size_t idx);
+ ssize_t Send_Piece(size_t idx,size_t off,char *piece_buf,size_t len);
+ ssize_t Send_Bitfield(char *bit_buf,size_t len);
+ ssize_t Send_Request(size_t idx,size_t off,size_t len);
+ ssize_t Send_Cancel(size_t idx,size_t off,size_t len);
+ ssize_t Send_Buffer(char *buf,size_t len);
+
+ ssize_t Flush();
+};
+
+#endif
diff --git a/bttime.h b/bttime.h
new file mode 100644
index 0000000..3ccb8fb
--- a/dev/null
+++ b/bttime.h
@@ -0,0 +1,9 @@
+#ifndef BTTIME_H
+#define BTTIME_H
+
+#include <time.h>
+
+extern time_t now;
+
+#endif
+
diff --git a/bufio.cpp b/bufio.cpp
new file mode 100644
index 0000000..fd9843e
--- a/dev/null
+++ b/bufio.cpp
@@ -0,0 +1,177 @@
+#include "./bufio.h"
+
+#ifndef WINDOWS
+#include <unistd.h>
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+
+#include "btrequest.h"
+
+#define _left_buffer_size (n - p)
+
+BufIo::BufIo()
+{
+ f_socket_remote_closed = 0;
+ b = new char[BUF_DEF_SIZ];
+#ifndef WINDOWS
+ if( !b ) throw 9;
+#endif
+ p = 0;
+ n = BUF_DEF_SIZ;
+}
+
+ssize_t BufIo::_realloc_buffer()
+{
+ return SetSize(n + BUF_INC_SIZ);
+}
+
+ssize_t BufIo::SetSize(size_t len)
+{
+ char *tbuf;
+
+ if( len > BUF_MAX_SIZ ) return -1; // buffer too long
+
+ if( p > len) len = p;
+ if( len == n ) return 0;
+
+ tbuf = new char[len];
+#ifndef WINDOWS
+ if( !tbuf ) return -1;
+#endif
+
+ if(p) memcpy(tbuf, b, p);
+ delete []b;
+ b = tbuf;
+ n = len;
+
+ return 0;
+}
+
+// retval
+// successful return bytes sended. otherwise -1;
+ssize_t BufIo::_SEND(SOCKET sk, char *buf, size_t len)
+{
+ ssize_t r;
+ size_t t = 0;
+ for(; len;){
+ r = SEND(sk,buf,len);
+ if(r < 0){
+#ifndef WINDOWS
+ if(errno == EINTR) continue;
+#endif
+ return (EWOULDBLOCK == errno || EAGAIN == errno) ? (ssize_t)t : -1;
+ }else if( 0 == r ){
+ return (ssize_t)t; // no possible???
+ }else{
+ buf += r;
+ len -= r;
+ t += r;
+ }
+ }
+ return (ssize_t)t;
+}
+
+ssize_t BufIo::_RECV(SOCKET sk, char *buf,size_t len)
+{
+ ssize_t r;
+ size_t t = 0;
+ for(; len;){
+ r = RECV(sk,(char*)buf,len);
+ if(r < 0){
+#ifndef WINDOWS
+ if(errno == EINTR) continue;
+#endif
+ return (EWOULDBLOCK == errno || EAGAIN == errno) ? (ssize_t)t : -1;
+ }else if( 0 == r ){
+ f_socket_remote_closed = 1;
+ return (ssize_t)t; //connection closed by remote.
+ }else{
+ buf += r;
+ len -= r;
+ t += r;
+ }
+ }
+ return (ssize_t)t;
+}
+
+ssize_t BufIo::Put(SOCKET sk, char *buf,size_t len)
+{
+ ssize_t r;
+ if( _left_buffer_size < len ){ //no enough space
+ r = FlushOut(sk);
+ if( r < 0 ) return r;
+ for( ; _left_buffer_size < len; ) // still no enough space
+ if(_realloc_buffer() < 0) return -3;
+ }
+ memcpy(b + p, buf, len);
+ p += len;
+ return 0;
+}
+
+ssize_t BufIo::FeedIn(SOCKET sk)
+{
+ return FeedIn(sk, _left_buffer_size);
+}
+
+ssize_t BufIo::FeedIn(SOCKET sk, size_t limit)
+{
+ ssize_t r;
+
+ if(!_left_buffer_size)
+ if(_realloc_buffer() < 0) return (ssize_t) -2;
+
+ if( 0==limit || limit > _left_buffer_size ) limit = _left_buffer_size;
+ r = _RECV(sk, b + p, limit);
+ if( r < 0 ) return -1;
+ else{
+ if( r ) p += r;
+ if( f_socket_remote_closed ) return -2; // connection closed by remote
+ }
+ return (ssize_t) p;
+}
+
+ssize_t BufIo::PutFlush(SOCKET sk, char *buf,size_t len)
+{
+ if( _left_buffer_size < len && p){
+ if( FlushOut(sk) < 0) return -1;
+ }
+
+ for(; _left_buffer_size < len; )
+ if( _realloc_buffer() < 0) return -3;
+
+ memcpy(b + p, buf, len);
+ p += len;
+ return FlushOut(sk);
+}
+
+// retval
+// >= 0 left bytes in buffer
+// < 0 failed
+ssize_t BufIo::FlushOut(SOCKET sk)
+{
+ ssize_t r;
+ if( !p ) return 0; // no data to be send
+
+ r = _SEND(sk,b,p);
+ if( r < 0 ) return r;
+ else if( r > 0){
+ p -= r;
+ if( p ) memmove(b, b + r, p);
+ }
+ return (ssize_t)p;
+}
+
+ssize_t BufIo::PickUp(size_t len)
+{
+ if( p < len ) return -1;
+ p -= len;
+ if( p ) memmove(b, b + len, p);
+ return 0;
+}
diff --git a/bufio.h b/bufio.h
new file mode 100644
index 0000000..7682a90
--- a/dev/null
+++ b/bufio.h
@@ -0,0 +1,58 @@
+#ifndef BUFIO_H
+#define BUFIO_H
+
+#include "def.h"
+#include <sys/types.h>
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#endif
+
+#include "btconfig.h"
+
+#define BUF_DEF_SIZ 256
+#define BUF_INC_SIZ 256
+#define BUF_MAX_SIZ (cfg_max_slice_size + BUF_DEF_SIZ + BUF_INC_SIZ)
+
+class BufIo
+{
+ private:
+ char *b; // buffer
+ size_t p; // amount of data in the buffer
+ size_t n; // buffer size
+
+ int f_socket_remote_closed;
+
+ ssize_t _realloc_buffer();
+ ssize_t _SEND(SOCKET socket,char *buf,size_t len);
+ ssize_t _RECV(SOCKET socket,char *buf,size_t len);
+
+ public:
+ BufIo();
+ ~BufIo() { if(b){ delete []b; b = (char*) 0;} }
+
+ ssize_t SetSize(size_t len);
+
+ void Reset(){ p = 0; f_socket_remote_closed = 0;}
+
+ void Close(){
+ if( b ){ delete []b; b = (char*) 0; }
+ p = n = 0;
+ }
+
+ size_t Count() const { return p; } //缓存中现有字节数
+ size_t LeftSize() const { return (n - p); }
+
+ ssize_t PickUp(size_t len); //移除缓存中前len个字节
+
+ ssize_t FeedIn(SOCKET sk); //从sk读数据到缓存直到暂时无数据可读或缓冲区满
+ ssize_t FeedIn(SOCKET sk, size_t limit);
+ ssize_t FlushOut(SOCKET sk); //将缓存中数据写到socket
+ ssize_t Put(SOCKET sk,char *buf,size_t len); //将buf内容添加到缓存
+ ssize_t PutFlush(SOCKET sk,char *buf,size_t len);
+
+ char *BasePointer() { return b; }
+ char *CurrentPointer() { return ( b + p); }
+};
+
+#endif
diff --git a/cheatorrent.cpp b/cheatorrent.cpp
new file mode 100644
index 0000000..47af4d5
--- a/dev/null
+++ b/cheatorrent.cpp
@@ -0,0 +1,445 @@
+#include "./def.h"
+#include <sys/types.h>
+
+#ifdef WINDOWS
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <signal.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "btconfig.h"
+#include "btcontent.h"
+#include "downloader.h"
+#include "peerlist.h"
+#include "tracker.h"
+#include "ctcs.h"
+#include "console.h"
+
+#include "./config.h"
+
+#ifndef HAVE_RANDOM
+#include "compat.h"
+#endif
+
+#ifndef WINDOWS
+#include "sigint.h"
+#endif
+
+void usage();
+int param_check(int argc, char **argv);
+
+#ifdef WINDOWS
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrzevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+}
+
+#else
+
+void Random_init()
+{
+ unsigned long seed;
+#ifdef HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ gettimeofday(&tv,(struct timezone*) 0);
+ seed = tv.tv_usec + tv.tv_sec + getpid();
+#else
+ seed = (unsigned long)time((time_t *)0);
+#endif
+ srandom(seed);
+}
+
+int main(int argc, char **argv)
+{
+ char *s;
+
+ Random_init();
+ arg_user_agent = new char[MAX_PF_LEN+1];
+ strcpy(arg_user_agent,PEER_PFX);
+
+ cfg_user_agent = new char[strlen("BitComet V.1.19")+2];
+#ifndef WINDOWS
+ if( !cfg_user_agent ) return -1;
+#endif
+ sprintf(cfg_user_agent, "BitComet V.1.19");
+ while(s = strchr(cfg_user_agent, ' ')) *s = '-';
+
+ if( argc < 2 ){
+ usage();
+ exit(1);
+ } else if( param_check(argc,argv) < 0 ) exit(1);
+
+ if( arg_flg_make_torrent ){
+ if( !arg_announce ){
+ CONSOLE.Warning(1, "Please use -u to specify an announce URL!");
+ exit(1);
+ }
+ if( !arg_save_as ){
+ CONSOLE.Warning(1, "Please use -s to specify a metainfo file name!");
+ exit(1);
+ }
+ if( BTCONTENT.InitialFromFS(arg_metainfo_file, arg_announce,
+ arg_piece_length) < 0 ||
+ BTCONTENT.CreateMetainfoFile(arg_save_as) < 0 ){
+ CONSOLE.Warning(1, "create metainfo failed.");
+ exit(1);
+ }
+ CONSOLE.Print("Create metainfo file %s successful.", arg_save_as);
+ exit(0);
+ }
+
+ if( arg_daemon ) CONSOLE.Daemonize();
+
+ if( !arg_flg_exam_only && (!arg_flg_check_only || arg_flg_force_seed_mode) )
+ if( arg_ctcs ) CTCS.Initial();
+
+ if( BTCONTENT.InitialFromMI(arg_metainfo_file, arg_save_as) < 0){
+ CONSOLE.Warning(1, "error, initial meta info failed.");
+ exit(1);
+ }
+
+ if( !arg_flg_exam_only && (!arg_flg_check_only || arg_flg_force_seed_mode) ){
+ if(WORLD.Initial_ListenPort() < 0){
+ CONSOLE.Warning(2, "warn, you can't accept connections.");
+ }
+
+ if( Tracker.Initial() < 0 ){
+ CONSOLE.Warning(1, "error, tracker setup failed.");
+ exit(1);
+ }
+
+ sig_setup(); // setup signal handling
+ CONSOLE.Interact(
+ "Press 'h' or '?' for help (display/control client options)." );
+ Downloader();
+ if( cfg_cache_size ) BTCONTENT.FlushCache();
+ }
+ if( !arg_flg_exam_only ) BTCONTENT.SaveBitfield();
+ WORLD.CloseAll();
+
+ if(arg_verbose) CONSOLE.cpu();
+ exit(0);
+}
+
+#endif
+
+int param_check(int argc, char **argv)
+{
+ const char *opts;
+ int c, l;
+ char *s;
+
+ if( 0==strncmp(argv[1], "-t", 2) )
+ opts = "tc:l:ps:u:";
+ else opts = "aA:b:cC:dD:e:E:fi:I:M:m:n:P:p:s:S:Tu:U:vxX:z:hH";
+
+ while( (c=getopt(argc, argv, opts)) != -1 )
+ switch( c ){
+ case 'a':
+ arg_allocate = 1;
+ break;
+
+ case 'b':
+ arg_bitfield_file = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_bitfield_file ) return -1;
+#endif
+ strcpy(arg_bitfield_file, optarg);
+ break;
+
+ case 'i': // listen on ip XXXX
+ cfg_listen_ip = inet_addr(optarg);
+ break;
+
+ case 'I': // set public ip XXXX
+ cfg_public_ip = new char[strlen(optarg) + 1];
+ if( !cfg_public_ip ) return -1;
+ strcpy(cfg_public_ip, optarg);
+ break;
+
+ case 'p': // listen on Port XXXX
+ if( arg_flg_make_torrent ) arg_flg_private = 1;
+ else cfg_listen_port = atoi(optarg);
+ break;
+
+ case 's': // Save as FILE/DIR NAME
+ if( arg_save_as ) return -1; // specified twice
+ arg_save_as = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_save_as ) return -1;
+#endif
+ strcpy(arg_save_as,optarg);
+ break;
+
+ case 'e': // Exit while complete
+ cfg_seed_hours = (time_t)strtoul(optarg, NULL, 10);
+ break;
+
+ case 'E': // target seed ratio
+ cfg_seed_ratio = atof(optarg);
+ break;
+
+ case 'c': // Check exist only
+ if( arg_flg_make_torrent ){
+ arg_comment = new char[strlen(optarg) + 1];
+ if( !arg_comment ) return -1;
+ strcpy(arg_comment, optarg);
+ }else arg_flg_check_only = 1;
+ break;
+
+ case 'C': // Max cache size
+ cfg_cache_size = atoi(optarg);
+ break;
+
+ case 'M': // Max peers
+ cfg_max_peers = atoi(optarg);
+ if( cfg_max_peers > 1000 || cfg_max_peers < 20 ){
+ CONSOLE.Warning(1, "-%c argument must be between 20 and 1000", c);
+ return -1;
+ }
+ break;
+
+ case 'm': // Min peers
+ cfg_min_peers = atoi(optarg);
+ if( cfg_min_peers > 1000 || cfg_min_peers < 1 ){
+ CONSOLE.Warning(1, "-%c argument must be between 1 and 1000", c);
+ return -1;
+ }
+ break;
+
+ case 'z': // slice size
+ cfg_req_slice_size = atoi(optarg) * 1024;
+ if(cfg_req_slice_size < 1024 || cfg_req_slice_size > cfg_max_slice_size){
+ CONSOLE.Warning(1, "-%c argument must be between 1 and %d",
+ c, cfg_max_slice_size / 1024);
+ return -1;
+ }
+ break;
+
+ case 'n': // Which file download
+ if( arg_file_to_download ) return -1; // specified twice
+ arg_file_to_download = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_file_to_download ) return -1;
+#endif
+ strcpy(arg_file_to_download,optarg);
+ break;
+
+ case 'f': // force seed mode, skip sha1 check when startup.
+ arg_flg_force_seed_mode = 1;
+ break;
+
+ case 'D': // download bandwidth limit
+ cfg_max_bandwidth_down = (int)(strtod(optarg, NULL) * 1024);
+ break;
+
+ case 'U': // upload bandwidth limit
+ cfg_max_bandwidth_up = (int)(strtod(optarg, NULL) * 1024);
+ break;
+
+ case 'P': // peer ID prefix
+ l = strlen(optarg);
+ if (l > MAX_PF_LEN) {
+ CONSOLE.Warning(1, "-P arg must be %d or less characters", MAX_PF_LEN);
+ return -1;
+ }
+ if (l == 1 && *optarg == '-') *arg_user_agent = (char) 0;
+ else strcpy(arg_user_agent,optarg);
+ break;
+
+ case 'A': // HTTP user-agent header string
+ if( cfg_user_agent ) delete []cfg_user_agent;
+ cfg_user_agent = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !cfg_user_agent ) return -1;
+#endif
+ strcpy(cfg_user_agent, optarg);
+ break;
+
+ case 'T': // convert foreign filenames to printable text
+ arg_flg_convert_filenames = 1;
+ break;
+
+ // BELOW OPTIONS USED FOR CREATE TORRENT.
+ case 'u': // Announce URL
+ if( arg_announce ) return -1; // specified twice
+ arg_announce = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_announce ) return -1;
+#endif
+ strcpy(arg_announce, optarg);
+ break;
+
+ case 't': // make Torrent
+ arg_flg_make_torrent = 1;
+ CONSOLE.ChangeChannel(O_INPUT, "off", 0);
+ break;
+
+ case 'l': // piece Length (default 262144)
+ arg_piece_length = atoi(optarg);
+ if( arg_piece_length < 65536 || arg_piece_length > 4096*1024 ){
+ CONSOLE.Warning(1, "-%c argument must be between 65536 and %d",
+ c, 4096*1024);
+ return -1;
+ }
+ break;
+ // ABOVE OPTIONS USED FOR CREATE TORRENT.
+
+ case 'x': // print torrent information only
+ arg_flg_exam_only = 1;
+ CONSOLE.ChangeChannel(O_INPUT, "off", 0);
+ break;
+
+ case 'S': // CTCS server
+ if( arg_ctcs ) return -1; // specified twice
+ arg_ctcs = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_ctcs ) return -1;
+#endif
+ if( !strchr(optarg, ':') ){
+ CONSOLE.Warning(1, "-%c argument requires a port number", c);
+ return -1;
+ }
+ strcpy(arg_ctcs, optarg);
+ break;
+
+ case 'X': // "user exit" on download completion
+ if( arg_completion_exit ) return -1; // specified twice
+ arg_completion_exit = new char[strlen(optarg) + 1];
+#ifndef WINDOWS
+ if( !arg_completion_exit ) return -1;
+#endif
+#ifndef HAVE_SYSTEM
+ CONSOLE.Warning(1, "-X is not supported on your system");
+ return -1;
+#endif
+#ifndef HAVE_WORKING_FORK
+ CONSOLE.Warning(2,
+ "No working fork function; be sure the -X command is brief!");
+#endif
+ strcpy(arg_completion_exit, optarg);
+ break;
+
+ case 'v': // verbose output
+ arg_verbose = 1;
+ break;
+
+ case 'd': // daemon mode (fork to background)
+ arg_daemon++;
+ break;
+
+ case 'h':
+ case 'H': // help
+ usage();
+ return -1;
+
+ default:
+ //unknown option.
+ CONSOLE.Warning(1, "Use -h for help/usage.");
+ return -1;
+ }
+
+ argc -= optind; argv += optind;
+ if( cfg_min_peers >= cfg_max_peers ) cfg_min_peers = cfg_max_peers - 1;
+ if( argc != 1 ){
+ if( arg_flg_make_torrent )
+ CONSOLE.Warning(1,
+ "Must specify torrent contents (one file or directory)");
+ else CONSOLE.Warning(1, "Must specify one torrent file");
+ return -1;
+ }
+ arg_metainfo_file = new char[strlen(*argv) + 1];
+#ifndef WINDOWS
+ if( !arg_metainfo_file ) return -1;
+#endif
+ strcpy(arg_metainfo_file, *argv);
+
+ if( !arg_bitfield_file ){
+ arg_bitfield_file = new char[strlen(arg_metainfo_file) + 4];
+#ifndef WINDOWS
+ if( !arg_bitfield_file ) return -1;
+#endif
+ strcpy(arg_bitfield_file, arg_metainfo_file);
+ strcat(arg_bitfield_file, ".bf");
+ }
+ return 0;
+}
+
+void usage()
+{
+ CONSOLE.ChangeChannel(O_INPUT, "off", 0);
+ fprintf(stderr,"WARNING: THERE IS NO WARRANTY FOR CheaTorrent. USE AT YOUR OWN RISK!!!\n");
+ fprintf(stderr,"\nGeneral Options:\n");
+ fprintf(stderr, "%-15s %s\n", "-h/-H", "Show this message");
+ fprintf(stderr, "%-15s %s\n", "-x",
+ "Decode metainfo (torrent) file only, don't download");
+ fprintf(stderr, "%-15s %s\n", "-c", "Check pieces only, don't download");
+ fprintf(stderr, "%-15s %s\n", "-v", "Verbose output (for debugging)");
+
+ fprintf(stderr,"\nDownload Options:\n");
+ fprintf(stderr, "%-15s %s\n", "-e int",
+ "Exit while seed <int> hours later (default 72 hours)");
+ fprintf(stderr, "%-15s %s\n", "-E num",
+ "Exit after seeding to <num> ratio (UL:DL)");
+ fprintf(stderr, "%-15s %s\n", "-i ip",
+ "Listen for connections on specific IP address (default all/any)");
+ fprintf(stderr, "%-15s %s\n", "-p port",
+ "Listen port (default 2706 -> 2106)");
+ fprintf(stderr, "%-15s %s\n", "-I ip",
+ "Specify public/external IP address for peer connections");
+ fprintf(stderr, "%-15s %s\n", "-u num or URL",
+ "Use an alternate announce (tracker) URL");
+ fprintf(stderr, "%-15s %s\n", "-s filename",
+ "Download (\"save as\") to a different file or directory");
+ fprintf(stderr, "%-15s %s\n", "-C cache_size",
+ "Cache size, unit MB (default 16MB)");
+ fprintf(stderr, "%-15s %s\n", "-f",
+ "Force saved bitfield or seed mode (skip initial hash check)");
+ fprintf(stderr, "%-15s %s\n", "-b filename",
+ "Specify bitfield save file (default is torrent+\".bf\")");
+ fprintf(stderr, "%-15s %s\n", "-M max_peers",
+ "Max peers count (default 100)");
+ fprintf(stderr, "%-15s %s\n", "-m min_peers", "Min peers count (default 1)");
+ fprintf(stderr, "%-15s %s\n", "-z slice_size",
+ "Download slice/block size, unit KB (default 16, max 128)");
+ fprintf(stderr, "%-15s %s\n", "-n file_list",
+ "Specify file number(s) to download");
+ fprintf(stderr, "%-15s %s\n", "-D rate", "Max bandwidth down (unit KB/s)");
+ fprintf(stderr, "%-15s %s\n", "-U rate", "Max bandwidth up (unit KB/s)");
+ fprintf(stderr, "%-15s %s%s\")\n", "-P peer_id",
+ "Set Peer ID prefix (default \"", PEER_PFX);
+ fprintf(stderr, "%-15s %s%s\")\n", "-A user_agent",
+ "Set User-Agent header (default \"", cfg_user_agent);
+ fprintf(stderr, "%-15s %s\n", "-S host:port",
+ "Use CTCS server at host:port");
+ fprintf(stderr, "%-15s %s\n", "-a", "Preallocate files on disk");
+ fprintf(stderr, "%-15s %s\n", "-T",
+ "Convert foreign filenames to printable text");
+ fprintf(stderr, "%-15s %s\n", "-X command",
+ "Run command upon download completion (\"user exit\")");
+ fprintf(stderr, "%-15s %s\n", "-d", "Daemon mode (fork to background)");
+ fprintf(stderr, "%-15s %s\n", "-dd", "Daemon mode with I/O redirection");
+
+ fprintf(stderr,"\nMake metainfo (torrent) file options:\n");
+ fprintf(stderr, "%-15s %s\n", "-t", "Create a new torrent file");
+ fprintf(stderr, "%-15s %s\n", "-u URL", "Tracker's URL");
+ fprintf(stderr, "%-15s %s\n", "-l piece_len",
+ "Piece length (default 262144)");
+ fprintf(stderr, "%-15s %s\n", "-s filename", "Specify metainfo file name");
+ fprintf(stderr, "%-15s %s\n", "-p", "Private (disable peer exchange)");
+ fprintf(stderr, "%-15s %s\n", "-c comment", "Include a comment/description");
+
+ fprintf(stderr,"\nExample:\n");
+ fprintf(stderr,"cheatorrent -s new_filename -e 12 -C 32 -p 6881 example.torrent\n");
+}
+
diff --git a/cheatorrent.h b/cheatorrent.h
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/cheatorrent.h
diff --git a/compat.c b/compat.c
new file mode 100644
index 0000000..de40b63
--- a/dev/null
+++ b/compat.c
@@ -0,0 +1,158 @@
+#include "def.h"
+
+/* compat.c: Copyright 2007 Dennis Holmes (dholmes@rahul.net)
+ * except as noted.
+ */
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "compat.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+int clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+ int r = 0;
+
+#if defined(HAVE_GETTIMEOFDAY)
+ struct timeval tv;
+ if( (r = gettimeofday(&tv, (struct timezone *)0)) == 0 ){
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = tv.tv_usec * 1000;
+ }
+#else
+#error No suitable precision timing functions appear to be available!
+#error Please report this problem and identify your system platform.
+#endif
+
+ return r;
+}
+#endif
+
+
+#ifndef HAVE_VSNPRINTF
+int vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+ int r;
+ char *buffer[4*MAXPATHLEN]; /* git-r-dun */
+
+ if( (r = vsprintf(buffer, format, ap)) >= 0){
+ strncpy(str, buffer, size-1);
+ str[size] = '\0';
+ }
+ return r;
+}
+#endif
+
+
+#ifndef HAVE_SNPRINTF
+int snprintf(char *str, size_t size, const char *format, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, format);
+ r = vsnprintf(str, size, format, ap);
+ va_end(ap);
+
+ return r;
+}
+#endif
+
+
+#ifndef HAVE_STRNSTR
+#include <string.h>
+/* FUNCTION PROGRAMER: Siberiaic Sang */
+char *strnstr(const char *haystack, const char *needle, size_t haystacklen)
+{
+ char *p;
+ ssize_t plen;
+ ssize_t len = strlen(needle);
+
+ if( *needle == '\0' )
+ return (char *)haystack;
+
+ plen = haystacklen;
+ for( p = (char *)haystack;
+ p != (char *)0;
+ p = (char *)memchr(p + 1, *needle, plen-1) ){
+ plen = haystacklen - (p - haystack);
+
+ if( plen < len ) return (char *)0;
+
+ if( strncmp(p, needle, len) == 0 )
+ return (p);
+ }
+ return (char*) 0;
+}
+#endif
+
+
+#ifndef HAVE_STRNCASECMP
+#include <ctype.h>
+int strncasecmp(const char *s1, const char *s2, size_t len)
+{
+ unsigned char c1, c2;
+ int r = 0;
+
+ for( ; r==0 && len && *s1 && *s2; s1++, s2++, len-- ){
+ if( *s1 == *s2 ) continue;
+ c1 = (unsigned char)tolower((int)*s1);
+ c2 = (unsigned char)tolower((int)*s2);
+ if( c1 == c2 ) continue;
+ else if( c1 < c2 ) r = -1;
+ else if( c1 > c2 ) r = 1;
+ }
+ if( r==0 && len ){
+ if( !*s1 && !*s2 ) r = 0;
+ else if( *s1 ) r = 1;
+ else r = -1;
+ }
+ return r;
+}
+#endif
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp(const char *s1, const char *s2)
+{
+ return strncasecmp(s1, s2, strlen(s1));
+}
+#endif
+
+
+#ifndef HAVE_RANDOM
+long random(void)
+{
+ long result;
+ unsigned long maxlong = 0, i = RAND_MAX;
+
+ maxlong--;
+ maxlong /= 2;
+
+ result = (long)rand();
+ while( i < maxlong ){
+ result = (result * 2UL*(RAND_MAX+1UL)) | rand();
+ i *= 2UL*(RAND_MAX+1UL);
+ }
+ return (result < 0) ? -result : result;
+}
+
+void srandom(unsigned long seed)
+{
+ unsigned useed;
+
+ if( sizeof(seed) > sizeof(useed) ){
+ unsigned long mask = 0xffff;
+ int i = 2;
+ while( i < sizeof(useed) ){
+ mask = (mask << 16) | 0xffff;
+ i += 2;
+ }
+ useed = (unsigned)(seed & mask);
+ }else useed = seed;
+
+ srand(useed);
+}
+#endif
+
diff --git a/compat.h b/compat.h
new file mode 100644
index 0000000..2caad68
--- a/dev/null
+++ b/compat.h
@@ -0,0 +1,65 @@
+#ifndef COMPAT_H
+#define COMPAT_H
+/* compat.h: Copyright 2007 Dennis Holmes (dholmes@rahul.net) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if !defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME)
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+#ifndef HAVE_CLOCKID_T
+typedef int clockid_t;
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+int clock_gettime(clockid_t clock_id, struct timespec *tp);
+#endif
+
+
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+#endif
+
+#ifndef HAVE_SNPRINTF
+#include <stdarg.h>
+int snprintf(char *str, size_t size, const char *format, ...);
+#endif
+
+
+#ifndef HAVE_STRNSTR
+char *strnstr(const char *haystack, const char *needle, size_t haystacklen);
+#endif
+
+#ifndef HAVE_STRNCASECMP
+int strncasecmp(const char *s1, const char *s2, size_t len);
+#endif
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp(const char *s1, const char *s2);
+#endif
+
+
+#ifndef HAVE_RANDOM
+long random(void);
+void srandom(unsigned long seed);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // COMPAT_H
+
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..b24af56
--- a/dev/null
+++ b/config.h
@@ -0,0 +1,322 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */
+#define GWINSZ_IN_SYS_IOCTL 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the clockid_t type. */
+#define HAVE_CLOCKID_T 1
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define if ctime_r() takes 2 arguments. */
+#define HAVE_CTIME_R_2 1
+
+/* Define if ctime_r() takes 3 arguments. */
+/* #undef HAVE_CTIME_R_3 */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getwd' function. */
+#define HAVE_GETWD 1
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#define HAVE_INET_NTOA 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <ioctl.h> header file. */
+/* #undef HAVE_IOCTL_H */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkdir' function. */
+#define HAVE_MKDIR 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <openssl/sha.h> header file. */
+/* #undef HAVE_OPENSSL_SHA_H */
+
+/* Define to 1 if you have the `random' function. */
+#define HAVE_RANDOM 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the <sha.h> header file. */
+/* #undef HAVE_SHA_H */
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <ssl/sha.h> header file. */
+/* #undef HAVE_SSL_SHA_H */
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strnstr' function. */
+/* #undef HAVE_STRNSTR */
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `system' function. */
+#define HAVE_SYSTEM 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Define to the unsuccessful return value of inet_addr(). */
+/* #undef INADDR_NONE */
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Name of package */
+#define PACKAGE "cheatorrent"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "lol"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "CheaTorrent"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "CheaTorrent"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "cheatorrent"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "v1.0"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to use sgtty.h (gtty/stty) for terminal control. */
+/* #undef USE_SGTTY */
+
+/* Define to 1 to use Steve Reid's public-domain SHA-1 code. */
+#define USE_STANDALONE_SHA1 1
+
+/* Define to use termio for terminal control. */
+/* #undef USE_TERMIO */
+
+/* Define to use Posix termios for terminal control. */
+#define USE_TERMIOS 1
+
+/* Version number of package */
+#define VERSION "v1.0"
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT64_T */
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT8_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to the type of a signed integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int16_t */
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int32_t */
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int64_t */
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+ a type exists and the standard includes do not define it. */
+/* #undef int8_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint16_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint64_t */
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint8_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..d12e9da
--- a/dev/null
+++ b/config.h.in
@@ -0,0 +1,321 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */
+#undef GWINSZ_IN_SYS_IOCTL
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the clockid_t type. */
+#undef HAVE_CLOCKID_T
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define if ctime_r() takes 2 arguments. */
+#undef HAVE_CTIME_R_2
+
+/* Define if ctime_r() takes 3 arguments. */
+#undef HAVE_CTIME_R_3
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getwd' function. */
+#undef HAVE_GETWD
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <ioctl.h> header file. */
+#undef HAVE_IOCTL_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the `memchr' function. */
+#undef HAVE_MEMCHR
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <openssl/sha.h> header file. */
+#undef HAVE_OPENSSL_SHA_H
+
+/* Define to 1 if you have the `random' function. */
+#undef HAVE_RANDOM
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define to 1 if you have the <sha.h> header file. */
+#undef HAVE_SHA_H
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the <ssl/sha.h> header file. */
+#undef HAVE_SSL_SHA_H
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strnstr' function. */
+#undef HAVE_STRNSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoll' function. */
+#undef HAVE_STRTOLL
+
+/* Define to 1 if you have the `system' function. */
+#undef HAVE_SYSTEM
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to the unsuccessful return value of inet_addr(). */
+#undef INADDR_NONE
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to use sgtty.h (gtty/stty) for terminal control. */
+#undef USE_SGTTY
+
+/* Define to 1 to use Steve Reid's public-domain SHA-1 code. */
+#undef USE_STANDALONE_SHA1
+
+/* Define to use termio for terminal control. */
+#undef USE_TERMIO
+
+/* Define to use Posix termios for terminal control. */
+#undef USE_TERMIOS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT64_T
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to the type of a signed integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int16_t
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int32_t
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int64_t
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+ a type exists and the standard includes do not define it. */
+#undef int8_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint64_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/configure b/configure
new file mode 100755
index 0000000..8f4f380
--- a/dev/null
+++ b/configure
@@ -0,0 +1,10686 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='CheaTorrent'
+PACKAGE_TARNAME='cheatorrent'
+PACKAGE_VERSION='v1.0'
+PACKAGE_STRING='CheaTorrent'
+PACKAGE_BUGREPORT='lol'
+
+ac_unique_file="cheatorrent.cpp"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+CXX
+CXXFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CXX
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+CC
+CFLAGS
+ac_ct_CC
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+CXXCPP
+GREP
+EGREP
+LIBOBJS
+POW_LIB
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ 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 | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ 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 "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures cheatorrent to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/cheatorrent]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of CheaTorrent";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-largefile omit support for large files
+ --enable-profile enable code profiling
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-ssl=DIR use SSL libraries in DIR for SHA1 support
+ --with-ssl=no use builtin (Steve Reid's public-domain) SHA-1 code
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CC C compiler command
+ CFLAGS C compiler flags
+ CXXCPP C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by CheaTorrent $as_me which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version="1.9"
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# 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
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_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. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# 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 "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+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"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=cheatorrent
+ VERSION=v1.0
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_config_files="$ac_config_files Makefile"
+
+
+
+
+# Checks for programs.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+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 "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5
+echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+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 | grep -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 "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CXX" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&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
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/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=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&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
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/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=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+# Checks for libaries.
+
+{ echo "$as_me:$LINENO: checking for library containing clock_gettime" >&5
+echo $ECHO_N "checking for library containing clock_gettime... $ECHO_C" >&6; }
+if test "${ac_cv_search_clock_gettime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt posix4; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_clock_gettime=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_clock_gettime+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_clock_gettime+set}" = set; then
+ :
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5
+echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6; }
+if test "${ac_cv_search_gethostbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl resolv; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_gethostbyname=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_gethostbyname+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_gethostbyname+set}" = set; then
+ :
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing socket" >&5
+echo $ECHO_N "checking for library containing socket... $ECHO_C" >&6; }
+if test "${ac_cv_search_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_socket=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_socket+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_socket+set}" = set; then
+ :
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_socket" >&5
+echo "${ECHO_T}$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ { echo "$as_me:$LINENO: checking for socket in -lnsl" >&5
+echo $ECHO_N "checking for socket in -lnsl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nsl_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl -lsocket $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_nsl_socket=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_nsl_socket=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_socket" >&6; }
+if test $ac_cv_lib_nsl_socket = yes; then
+ LIBS="$LIBS -lsocket -lnsl"
+fi
+
+fi
+
+
+# Checks for header files.
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_opendir=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_opendir+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+ :
+else
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+ { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_opendir=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_opendir+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+ :
+else
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in arpa/inet.h fcntl.h limits.h memory.h netdb.h netinet/in.h sys/param.h sys/socket.h sys/time.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ---------------------------------------------------------------------------------- ##
+## Report this to http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com ##
+## ---------------------------------------------------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+for ac_header in termios.h termio.h sgtty.h ioctl.h sys/ioctl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ---------------------------------------------------------------------------------- ##
+## Report this to http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com ##
+## ---------------------------------------------------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset cs;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_inline=$ac_kw
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6; }
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_ssize_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef ssize_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_ssize_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_ssize_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6; }
+if test $ac_cv_type_ssize_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+
+ { echo "$as_me:$LINENO: checking for int8_t" >&5
+echo $ECHO_N "checking for int8_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int8_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_int8_t=no
+ for ac_type in 'int8_t' 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1)
+ < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ case $ac_type in
+ int8_t) ac_cv_c_int8_t=yes ;;
+ *) ac_cv_c_int8_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_int8_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int8_t" >&5
+echo "${ECHO_T}$ac_cv_c_int8_t" >&6; }
+ case $ac_cv_c_int8_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int8_t $ac_cv_c_int8_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for int16_t" >&5
+echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int16_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_int16_t=no
+ for ac_type in 'int16_t' 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1)
+ < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ case $ac_type in
+ int16_t) ac_cv_c_int16_t=yes ;;
+ *) ac_cv_c_int16_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_int16_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int16_t" >&5
+echo "${ECHO_T}$ac_cv_c_int16_t" >&6; }
+ case $ac_cv_c_int16_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int16_t $ac_cv_c_int16_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for int32_t" >&5
+echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int32_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_int32_t=no
+ for ac_type in 'int32_t' 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1)
+ < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ case $ac_type in
+ int32_t) ac_cv_c_int32_t=yes ;;
+ *) ac_cv_c_int32_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_int32_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5
+echo "${ECHO_T}$ac_cv_c_int32_t" >&6; }
+ case $ac_cv_c_int32_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int32_t $ac_cv_c_int32_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for int64_t" >&5
+echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_int64_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_int64_t=no
+ for ac_type in 'int64_t' 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1)
+ < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 2))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ case $ac_type in
+ int64_t) ac_cv_c_int64_t=yes ;;
+ *) ac_cv_c_int64_t=$ac_type ;;
+esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_int64_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_int64_t" >&5
+echo "${ECHO_T}$ac_cv_c_int64_t" >&6; }
+ case $ac_cv_c_int64_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int64_t $ac_cv_c_int64_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for uint8_t" >&5
+echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint8_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_uint8_t=no
+ for ac_type in 'uint8_t' 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (8 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ case $ac_type in
+ uint8_t) ac_cv_c_uint8_t=yes ;;
+ *) ac_cv_c_uint8_t=$ac_type ;;
+esac
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_uint8_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint8_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint8_t" >&6; }
+ case $ac_cv_c_uint8_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<\_ACEOF
+#define _UINT8_T 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t $ac_cv_c_uint8_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for uint16_t" >&5
+echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint16_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_uint16_t=no
+ for ac_type in 'uint16_t' 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (16 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ case $ac_type in
+ uint16_t) ac_cv_c_uint16_t=yes ;;
+ *) ac_cv_c_uint16_t=$ac_type ;;
+esac
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_uint16_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint16_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint16_t" >&6; }
+ case $ac_cv_c_uint16_t in #(
+ no|yes) ;; #(
+ *)
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint16_t $ac_cv_c_uint16_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for uint32_t" >&5
+echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint32_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_uint32_t=no
+ for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (32 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ case $ac_type in
+ uint32_t) ac_cv_c_uint32_t=yes ;;
+ *) ac_cv_c_uint32_t=$ac_type ;;
+esac
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_uint32_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; }
+ case $ac_cv_c_uint32_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<\_ACEOF
+#define _UINT32_T 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+ esac
+
+
+ { echo "$as_me:$LINENO: checking for uint64_t" >&5
+echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; }
+if test "${ac_cv_c_uint64_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_uint64_t=no
+ for ac_type in 'uint64_t' 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> (64 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ case $ac_type in
+ uint64_t) ac_cv_c_uint64_t=yes ;;
+ *) ac_cv_c_uint64_t=$ac_type ;;
+esac
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_uint64_t" != no && break
+ done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_uint64_t" >&5
+echo "${ECHO_T}$ac_cv_c_uint64_t" >&6; }
+ case $ac_cv_c_uint64_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<\_ACEOF
+#define _UINT64_T 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint64_t $ac_cv_c_uint64_t
+_ACEOF
+;;
+ esac
+
+{ echo "$as_me:$LINENO: checking for clockid_t" >&5
+echo $ECHO_N "checking for clockid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_clockid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef clockid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_clockid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_clockid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_clockid_t" >&5
+echo "${ECHO_T}$ac_cv_type_clockid_t" >&6; }
+if test $ac_cv_type_clockid_t = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CLOCKID_T 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether INADDR_NONE is declared" >&5
+echo $ECHO_N "checking whether INADDR_NONE is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_INADDR_NONE+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <arpa/inet.h>
+ #include <netinet/in.h>
+
+int
+main ()
+{
+#ifndef INADDR_NONE
+ (void) INADDR_NONE;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_INADDR_NONE=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_INADDR_NONE=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_INADDR_NONE" >&5
+echo "${ECHO_T}$ac_cv_have_decl_INADDR_NONE" >&6; }
+if test $ac_cv_have_decl_INADDR_NONE = yes; then
+ :
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define INADDR_NONE ((unsigned long)-1)
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+# Checks for library functions.
+{ echo "$as_me:$LINENO: checking for working memcmp" >&5
+echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6; }
+if test "${ac_cv_func_memcmp_working+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_memcmp_working=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Some versions of memcmp are not 8-bit clean. */
+ char c0 = '\100', c1 = '\200', c2 = '\201';
+ if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+ return 1;
+
+ /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+ or more and with at least one buffer not starting on a 4-byte boundary.
+ William Lewis provided this test program. */
+ {
+ char foo[21];
+ char bar[21];
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ char *a = foo + i;
+ char *b = bar + i;
+ strcpy (a, "--------01111111");
+ strcpy (b, "--------10000000");
+ if (memcmp (a, b, 16) >= 0)
+ return 1;
+ }
+ return 0;
+ }
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_memcmp_working=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_memcmp_working=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5
+echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6; }
+test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
+ *" memcmp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
+ ;;
+esac
+
+
+{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+if test "${ac_cv_type_signal+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_signal=int
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_signal=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
+echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; }
+if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ /* Linux will dereference the symlink and fail.
+ That is better in the sense that it means we will not
+ have to compile and use the lstat wrapper. */
+ return lstat ("conftest.sym/", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+ # If the `ln -s' command failed, then we probably don't even
+ # have an lstat function.
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+ case " $LIBOBJS " in
+ *" lstat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
+echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; }
+if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ return stat ("", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_stat_empty_string_bug=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+ case " $LIBOBJS " in
+ *" stat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for working strtod" >&5
+echo $ECHO_N "checking for working strtod... $ECHO_C" >&6; }
+if test "${ac_cv_func_strtod+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_strtod=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+$ac_includes_default
+#ifndef strtod
+double strtod ();
+#endif
+int
+main()
+{
+ {
+ /* Some versions of Linux strtod mis-parse strings with leading '+'. */
+ char *string = " +69";
+ char *term;
+ double value;
+ value = strtod (string, &term);
+ if (value != 69 || term != (string + 4))
+ return 1;
+ }
+
+ {
+ /* Under Solaris 2.4, strtod returns the wrong value for the
+ terminating character under some conditions. */
+ char *string = "NaN";
+ char *term;
+ strtod (string, &term);
+ if (term != string && *(term - 1) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strtod=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_strtod=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strtod" >&5
+echo "${ECHO_T}$ac_cv_func_strtod" >&6; }
+if test $ac_cv_func_strtod = no; then
+ case " $LIBOBJS " in
+ *" strtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtod.$ac_objext"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for pow" >&5
+echo $ECHO_N "checking for pow... $ECHO_C" >&6; }
+if test "${ac_cv_func_pow+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pow to an innocuous variant, in case <limits.h> declares pow.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pow innocuous_pow
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pow (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pow
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pow ();
+/* 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_pow || defined __stub___pow
+choke me
+#endif
+
+int
+main ()
+{
+return pow ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_pow=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_pow=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_pow" >&5
+echo "${ECHO_T}$ac_cv_func_pow" >&6; }
+
+if test $ac_cv_func_pow = no; then
+ { echo "$as_me:$LINENO: checking for pow in -lm" >&5
+echo $ECHO_N "checking for pow in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_pow+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pow ();
+int
+main ()
+{
+return pow ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_m_pow=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_m_pow=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_pow" >&5
+echo "${ECHO_T}$ac_cv_lib_m_pow" >&6; }
+if test $ac_cv_lib_m_pow = yes; then
+ POW_LIB=-lm
+else
+ { echo "$as_me:$LINENO: WARNING: cannot find library containing definition of pow" >&5
+echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;}
+fi
+
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in clock_gettime ftruncate gethostbyname gettimeofday getwd inet_ntoa memchr memmove memset mkdir random select snprintf socket strerror strcasecmp strncasecmp strtol strtoll strnstr system vsnprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* 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
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_pid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_pid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
+if test $ac_cv_type_pid_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+
+for ac_header in vfork.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ---------------------------------------------------------------------------------- ##
+## Report this to http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com ##
+## ---------------------------------------------------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in fork vfork
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* 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
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { echo "$as_me:$LINENO: checking for working fork" >&5
+echo $ECHO_N "checking for working fork... $ECHO_C" >&6; }
+if test "${ac_cv_func_fork_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_fork_works=cross
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_fork_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5
+echo "${ECHO_T}$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { echo "$as_me:$LINENO: checking for working vfork" >&5
+echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; }
+if test "${ac_cv_func_vfork_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_vfork_works=cross
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_vfork_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5
+echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_VFORK 1
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define vfork fork
+_ACEOF
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_FORK 1
+_ACEOF
+
+fi
+
+
+# Enable/check large file support
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_largefile_CC=' -n32'; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_file_offset_bits=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_file_offset_bits=64; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -f conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_large_files=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_large_files=1; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -f conftest*
+ fi
+fi
+
+{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_sys_largefile_source=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _LARGEFILE_SOURCE 1
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_sys_largefile_source=1; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_cv_sys_largefile_source=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -f conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FSEEKO 1
+_ACEOF
+
+fi
+
+
+# Check for termios support
+{ echo "$as_me:$LINENO: checking POSIX termios" >&5
+echo $ECHO_N "checking POSIX termios... $ECHO_C" >&6; }
+if test "${ac_cv_sys_posix_termios+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
+
+int
+main ()
+{
+/* SunOS 4.0.3 has termios.h but not the library calls. */
+ tcgetattr(0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_sys_posix_termios=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_sys_posix_termios=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_posix_termios" >&5
+echo "${ECHO_T}$ac_cv_sys_posix_termios" >&6; }
+
+if test "$ac_cv_sys_posix_termios" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_TERMIOS 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: checking whether termios.h defines TIOCGWINSZ" >&5
+echo $ECHO_N "checking whether termios.h defines TIOCGWINSZ... $ECHO_C" >&6; }
+if test "${ac_cv_sys_tiocgwinsz_in_termios_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <termios.h>
+#ifdef TIOCGWINSZ
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then
+ ac_cv_sys_tiocgwinsz_in_termios_h=yes
+else
+ ac_cv_sys_tiocgwinsz_in_termios_h=no
+fi
+rm -f conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5
+echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_termios_h" >&6; }
+
+if test $ac_cv_sys_tiocgwinsz_in_termios_h != yes; then
+ { echo "$as_me:$LINENO: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5
+echo $ECHO_N "checking whether sys/ioctl.h defines TIOCGWINSZ... $ECHO_C" >&6; }
+if test "${ac_cv_sys_tiocgwinsz_in_sys_ioctl_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef TIOCGWINSZ
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then
+ ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=yes
+else
+ ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=no
+fi
+rm -f conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5
+echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&6; }
+
+ if test $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define GWINSZ_IN_SYS_IOCTL 1
+_ACEOF
+
+ fi
+fi
+
+else
+ if test "${ac_cv_header_termio_h+set}" = set; then
+ { echo "$as_me:$LINENO: checking for termio.h" >&5
+echo $ECHO_N "checking for termio.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_termio_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_termio_h" >&5
+echo "${ECHO_T}$ac_cv_header_termio_h" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking termio.h usability" >&5
+echo $ECHO_N "checking termio.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <termio.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking termio.h presence" >&5
+echo $ECHO_N "checking termio.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <termio.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: termio.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: termio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: termio.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: termio.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: termio.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: termio.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: termio.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: termio.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: termio.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: termio.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: termio.h: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ---------------------------------------------------------------------------------- ##
+## Report this to http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com ##
+## ---------------------------------------------------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for termio.h" >&5
+echo $ECHO_N "checking for termio.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_termio_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_termio_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_termio_h" >&5
+echo "${ECHO_T}$ac_cv_header_termio_h" >&6; }
+
+fi
+if test $ac_cv_header_termio_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_TERMIO 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: checking for library containing gtty" >&5
+echo $ECHO_N "checking for library containing gtty... $ECHO_C" >&6; }
+if test "${ac_cv_search_gtty+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gtty ();
+int
+main ()
+{
+return gtty ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' compat; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_gtty=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_gtty+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_gtty+set}" = set; then
+ :
+else
+ ac_cv_search_gtty=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_gtty" >&5
+echo "${ECHO_T}$ac_cv_search_gtty" >&6; }
+ac_res=$ac_cv_search_gtty
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_SGTTY 1
+_ACEOF
+
+fi
+
+fi
+
+
+fi
+
+# Check for SSL support, letting the user give a location hint.
+
+# Check whether --with-ssl was given.
+if test "${with_ssl+set}" = set; then
+ withval=$with_ssl; with_ssl=$withval
+fi
+
+
+# Check whether --with-ssl was given.
+if test "${with_ssl+set}" = set; then
+ withval=$with_ssl;
+fi
+
+if test "$with_ssl" = "no"; then
+ echo "Forcing use of Steve Reid's public-domain SHA-1 code."
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_STANDALONE_SHA1 1
+_ACEOF
+
+else
+ if test -n "$with_ssl" -a "$with_ssl" != "yes"; then
+ # a directory was specified
+ echo "Trying SSL support in $with_ssl or system default locations."
+ CPPFLAGS="$CPPFLAGS -I$with_ssl/include -I$with_ssl/include/openssl"
+ CPPFLAGS="$CPPFLAGS -I$with_ssl/include/ssl -I$with_ssl"
+ LDFLAGS="$LDFLAGS -L$with_ssl/lib -L$with_ssl/lib/openssl"
+ LDFLAGS="$LDFLAGS -L$with_ssl/lib/ssl -L$with_ssl"
+ { echo "$as_me:$LINENO: checking for library containing SHA1_Init" >&5
+echo $ECHO_N "checking for library containing SHA1_Init... $ECHO_C" >&6; }
+if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SHA1_Init ();
+int
+main ()
+{
+return SHA1_Init ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' ssl crypto crypt md; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_SHA1_Init=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ :
+else
+ ac_cv_search_SHA1_Init=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_SHA1_Init" >&5
+echo "${ECHO_T}$ac_cv_search_SHA1_Init" >&6; }
+ac_res=$ac_cv_search_SHA1_Init
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: cannot find library for SHA1_Init() under $with_ssl" >&5
+echo "$as_me: error: cannot find library for SHA1_Init() under $with_ssl" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ fi
+ if test -z "$with_ssl" -o "$with_ssl" = "yes"; then
+ # no dir given--fall back to builtin code if necessary
+ { echo "$as_me:$LINENO: checking for library containing SHA1_Init" >&5
+echo $ECHO_N "checking for library containing SHA1_Init... $ECHO_C" >&6; }
+if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SHA1_Init ();
+int
+main ()
+{
+return SHA1_Init ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' ssl crypto crypt md; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_SHA1_Init=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_SHA1_Init+set}" = set; then
+ :
+else
+ ac_cv_search_SHA1_Init=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_SHA1_Init" >&5
+echo "${ECHO_T}$ac_cv_search_SHA1_Init" >&6; }
+ac_res=$ac_cv_search_SHA1_Init
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_STANDALONE_SHA1 1
+_ACEOF
+
+fi
+
+ fi
+
+
+
+for ac_header in openssl/sha.h ssl/sha.h sha.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ---------------------------------------------------------------------------------- ##
+## Report this to http://sourceforge.net/projects/dtorrent/ or dholmes@ct.boxmail.com ##
+## ---------------------------------------------------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+fi
+
+# Check for number of arguments to ctime_r().
+# by Iago Rubio
+# http://www.ems.ru/~villain/bluefish-dev.2003-12/0298.html
+{ echo "$as_me:$LINENO: checking for ctime_r" >&5
+echo $ECHO_N "checking for ctime_r... $ECHO_C" >&6; }
+if test -z "$ac_cv_ctime_args"; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_ctime_args=2
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf, 26);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_ctime_args=3
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+if test -z "$ac_cv_ctime_args"; then
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+else
+ if test "$ac_cv_ctime_args" = 2; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CTIME_R_2 1
+_ACEOF
+
+ elif test "$ac_cv_ctime_args" = 3; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CTIME_R_3 1
+_ACEOF
+
+ fi
+ { echo "$as_me:$LINENO: result: yes, and it takes $ac_cv_ctime_args arguments" >&5
+echo "${ECHO_T}yes, and it takes $ac_cv_ctime_args arguments" >&6; }
+fi
+
+
+# Check whether --enable-profile was given.
+if test "${enable_profile+set}" = set; then
+ enableval=$enable_profile; CXXFLAGS="$CXXFLAGS -pg"
+ CFLAGS="$CFLAGS -pg"
+
+fi
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by CheaTorrent $as_me dnh3.3.2, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+CheaTorrent config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+POW_LIB!$POW_LIB$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 86; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $ac_file | $ac_file:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $ac_file" >`$as_dirname -- $ac_file ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X$ac_file : 'X\(//\)[^/]' \| \
+ X$ac_file : 'X\(//\)$' \| \
+ X$ac_file : 'X\(/\)' \| . 2>/dev/null ||
+echo X$ac_file |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. 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 "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/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=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..2e230a7
--- a/dev/null
+++ b/configure.ac
@@ -0,0 +1,154 @@
+# Process this file with autoconf to produce a configure script.
+m4_include([version.m4])
+AC_INIT([m4_PACKAGE_NAME], [m4_PACKAGE_VERSION], [m4_PACKAGE_BUGREPORT],
+ [m4_PACKAGE_TARNAME])
+AM_INIT_AUTOMAKE([AC_PACKAGE_TARNAME], [AC_PACKAGE_VERSION])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([Makefile])
+
+AC_CONFIG_SRCDIR([cheatorrent.cpp])
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+
+AC_LANG([C++])
+
+# Checks for libaries.
+AC_SEARCH_LIBS([clock_gettime],[rt posix4])
+AC_SEARCH_LIBS([gethostbyname],[nsl resolv])
+AC_SEARCH_LIBS([socket],[socket],,
+ [AC_CHECK_LIB([nsl],[socket],LIBS="$LIBS -lsocket -lnsl",,-lsocket)])
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h memory.h netdb.h netinet/in.h sys/param.h sys/socket.h sys/time.h unistd.h])
+AC_CHECK_HEADERS([termios.h termio.h sgtty.h ioctl.h sys/ioctl.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_INT8_T
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_CHECK_TYPE([clockid_t],
+ [AC_DEFINE([HAVE_CLOCKID_T],1,
+ [Define to 1 if you have the clockid_t type.])])
+AC_CHECK_DECL([INADDR_NONE],,
+ [AC_DEFINE([INADDR_NONE],[((unsigned long)-1)],
+ [Define to the unsuccessful return value of inet_addr().])],
+ [#include <arpa/inet.h>
+ #include <netinet/in.h>])
+AC_C_BIGENDIAN
+
+# Checks for library functions.
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([clock_gettime ftruncate gethostbyname gettimeofday getwd inet_ntoa memchr memmove memset mkdir random select snprintf socket strerror strcasecmp strncasecmp strtol strtoll strnstr system vsnprintf])
+AC_FUNC_FORK
+
+# Enable/check large file support
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+# Check for termios support
+AC_SYS_POSIX_TERMIOS
+if test "$ac_cv_sys_posix_termios" = yes; then
+ AC_DEFINE([USE_TERMIOS],1,
+ [Define to use Posix termios for terminal control.])
+ AC_HEADER_TIOCGWINSZ
+else
+ AC_CHECK_HEADER([termio.h],
+ [AC_DEFINE([USE_TERMIO],1,[Define to use termio for terminal control.])],
+ [AC_SEARCH_LIBS([gtty],[compat],
+ [AC_DEFINE([USE_SGTTY],1,
+ [Define to use sgtty.h (gtty/stty) for terminal control.])])])
+fi
+
+# Check for SSL support, letting the user give a location hint.
+AC_ARG_WITH([ssl],
+ [AS_HELP_STRING([--with-ssl=DIR],
+ [use SSL libraries in DIR for SHA1 support])],
+ [with_ssl=$withval],
+ [])
+AC_ARG_WITH([ssl],
+ [AS_HELP_STRING([--with-ssl=no],
+ [use builtin (Steve Reid's public-domain) SHA-1 code])])
+if test "$with_ssl" = "no"; then
+ echo "Forcing use of Steve Reid's public-domain SHA-1 code."
+ AC_DEFINE([USE_STANDALONE_SHA1],1,
+ [Define to use Steve Reid's public-domain SHA-1 code.])
+else
+ if test -n "$with_ssl" -a "$with_ssl" != "yes"; then
+ # a directory was specified
+ echo "Trying SSL support in $with_ssl or system default locations."
+ CPPFLAGS="$CPPFLAGS -I$with_ssl/include -I$with_ssl/include/openssl"
+ CPPFLAGS="$CPPFLAGS -I$with_ssl/include/ssl -I$with_ssl"
+ LDFLAGS="$LDFLAGS -L$with_ssl/lib -L$with_ssl/lib/openssl"
+ LDFLAGS="$LDFLAGS -L$with_ssl/lib/ssl -L$with_ssl"
+ AC_SEARCH_LIBS([SHA1_Init],[ssl crypto crypt md],,
+ [AC_MSG_ERROR([cannot find library for SHA1_Init() under $with_ssl])])
+ fi
+ if test -z "$with_ssl" -o "$with_ssl" = "yes"; then
+ # no dir given--fall back to builtin code if necessary
+ AC_SEARCH_LIBS([SHA1_Init],[ssl crypto crypt md],,
+ [AC_DEFINE([USE_STANDALONE_SHA1],1,
+ [Define to 1 to use Steve Reid's public-domain SHA-1 code.])])
+ fi
+ AC_CHECK_HEADERS([openssl/sha.h ssl/sha.h sha.h])
+fi
+
+# Check for number of arguments to ctime_r().
+# by Iago Rubio
+# http://www.ems.ru/~villain/bluefish-dev.2003-12/0298.html
+AC_MSG_CHECKING(for ctime_r)
+if test -z "$ac_cv_ctime_args"; then
+ AC_TRY_COMPILE(
+ [#include <time.h>],
+ [
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf);
+ ], ac_cv_ctime_args=2)
+
+ AC_TRY_COMPILE(
+ [#include <time.h>],
+ [
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf, 26);
+ ], ac_cv_ctime_args=3)
+fi
+if test -z "$ac_cv_ctime_args"; then
+ AC_MSG_RESULT(no)
+else
+ if test "$ac_cv_ctime_args" = 2; then
+ AC_DEFINE(HAVE_CTIME_R_2,1,[Define if ctime_r() takes 2 arguments.])
+ elif test "$ac_cv_ctime_args" = 3; then
+ AC_DEFINE(HAVE_CTIME_R_3,1,[Define if ctime_r() takes 3 arguments.])
+ fi
+ AC_MSG_RESULT([yes, and it takes $ac_cv_ctime_args arguments])
+fi
+
+
+AC_ARG_ENABLE([profile],
+ [AS_HELP_STRING([--enable-profile], [enable code profiling])],
+ [CXXFLAGS="$CXXFLAGS -pg"
+ CFLAGS="$CFLAGS -pg"
+ ],
+ [])
+
+AC_OUTPUT()
+
diff --git a/connect_nonb.cpp b/connect_nonb.cpp
new file mode 100644
index 0000000..6c7a04d
--- a/dev/null
+++ b/connect_nonb.cpp
@@ -0,0 +1,15 @@
+#include "connect_nonb.h" // def.h
+
+#include <errno.h>
+
+// 返回值
+// >0 连接已成功
+// -1 连接已失败
+// -2 连接正在进行
+int connect_nonb(SOCKET sk,struct sockaddr* psa)
+{
+ int r;
+ r = connect(sk,psa,sizeof(struct sockaddr));
+ if(r < 0 && errno == EINPROGRESS) r = -2;
+ return r;
+}
diff --git a/connect_nonb.h b/connect_nonb.h
new file mode 100644
index 0000000..bafdc5c
--- a/dev/null
+++ b/connect_nonb.h
@@ -0,0 +1,17 @@
+#ifndef CONNECT_NONB_H
+#define CONNECT_NONB_H
+
+#include "./def.h"
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+int connect_nonb(SOCKET sk,struct sockaddr *psa);
+
+#endif
diff --git a/console.cpp b/console.cpp
new file mode 100644
index 0000000..25c9226
--- a/dev/null
+++ b/console.cpp
@@ -0,0 +1,1441 @@
+#include "console.h" // def.h
+
+#include <stdlib.h> // atoi()
+#include <sys/types.h> // fstat(), FD_SET(), fork()
+#include <sys/stat.h> // fstat()
+#include <unistd.h> // isatty(), fork(), setsid()
+#include <string.h>
+#include <errno.h>
+#include <ctype.h> // isdigit()
+#include <signal.h>
+#include <fcntl.h> // open()
+#include <time.h> // clock()
+
+#if defined(HAVE_IOCTL_H)
+#include <ioctl.h> // ioctl()
+#elif defined(HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
+
+#include "btconfig.h"
+#include "ctcs.h"
+#include "btcontent.h"
+#include "tracker.h"
+#include "peer.h"
+#include "peerlist.h"
+#include "bitfield.h"
+#include "bttime.h"
+#include "sigint.h"
+
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF) || \
+ !defined(HAVE_STRCASECMP)
+#include "compat.h"
+#endif
+
+// console.cpp: Copyright 2007-2008 Dennis Holmes (dholmes@rahul.net)
+
+// input mode definitions
+#define K_CHARS 0
+#define K_LINES 1
+
+const char LIVE_CHAR[4] = {'-', '\\','|','/'};
+
+Console CONSOLE;
+static int g_console_ready = 0;
+
+
+//===========================================================================
+// ConStream class functions
+
+
+ConStream::ConStream()
+{
+ m_stream = (FILE *)0;
+ m_name = (char *)0;
+ m_restore = 0;
+ m_newline = 1;
+ m_suspend = 0;
+ m_inputmode = K_LINES;
+}
+
+
+ConStream::~ConStream()
+{
+ if( m_restore ) RestoreMode();
+ if( !m_suspend ) _newline();
+ if( m_stream ) fclose(m_stream);
+ if( m_name ) delete []m_name;
+}
+
+
+void ConStream::Close()
+{
+ if( m_stream ){
+ fclose(m_stream);
+ m_stream = (FILE *)0;
+ }
+ m_suspend = 1;
+}
+
+
+void ConStream::Associate(FILE *stream, const char *name, int mode)
+{
+ m_stream = stream;
+ m_filemode = mode;
+ if( m_name = new char[strlen(name)+1] )
+ strcpy(m_name, name);
+ else Error(1, "Failed to allocate memory for output filename.");
+}
+
+
+int ConStream::SameDev(ConStream *master) const
+{
+ struct stat sbone, sbtwo;
+
+ if( master == this || Fileno() == master->Fileno() ) return 1;
+ else if( Fileno() < 0 || master->Fileno() < 0 ) return 0;
+
+ if( !fstat(Fileno(), &sbone) && !fstat(master->Fileno(), &sbtwo) )
+ return (sbone.st_dev==sbtwo.st_dev && sbone.st_ino==sbtwo.st_ino) ? 1 : 0;
+ else return 0;
+}
+
+
+int ConStream::IsTTY() const
+{
+ return (Fileno() >= 0) ? isatty(Fileno()) : 0;
+}
+
+
+void ConStream::PreserveMode()
+{
+ int r;
+
+ if( !IsTTY() ) return;
+
+#if defined(USE_TERMIOS)
+ r = tcgetattr(Fileno(), &m_original);
+#elif defined(USE_TERMIO)
+ r = ioctl(Fileno(), TCGETA, &m_original);
+#elif defined(USE_SGTTY)
+ r = gtty(Fileno(), &m_original);
+#endif
+ if( r < 0 ){
+ Error(1, "Error preserving terminal mode on fd %d: %s", Fileno(),
+ strerror(errno));
+ }else m_restore = 1;
+}
+
+
+void ConStream::RestoreMode()
+{
+ int r;
+
+ if( !IsTTY() ) return;
+
+#if defined(USE_TERMIOS)
+ r = tcsetattr(Fileno(), TCSANOW, &m_original);
+#elif defined(USE_TERMIO)
+ r = ioctl(Fileno(), TCSETA, &m_original);
+#elif defined(USE_SGTTY)
+ r = stty(Fileno(), &m_original);
+#endif
+ if( r < 0 ){
+ Error(1, "Error restoring terminal mode on fd %d: %s", Fileno(),
+ strerror(errno));
+ }
+}
+
+
+void ConStream::SetInputMode(int keymode)
+{
+ if( m_suspend ) return;
+
+ m_inputmode = keymode;
+ if( !IsTTY() ) return;
+
+#if defined(USE_TERMIOS)
+ struct termios termset;
+ tcgetattr(Fileno(), &termset);
+#elif defined(USE_TERMIO)
+ struct termio termset;
+ ioctl(Fileno(), TCGETA, &termset);
+#elif defined(USE_SGTTY)
+ struct sgttyb termset;
+ gtty(Fileno(), &termset);
+#endif
+
+ switch(keymode) {
+ case K_CHARS: // read a char at a time, no echo
+#if defined(USE_TERMIOS)
+ termset.c_lflag &= ~(ICANON | ECHO);
+ termset.c_cc[VMIN] = 1;
+ termset.c_cc[VTIME] = 0;
+ tcsetattr(Fileno(), TCSANOW, &termset);
+#elif defined(USE_TERMIO)
+ termset.c_lflag &= ~(ICANON | ECHO);
+ termset.c_cc[VMIN] = 1;
+ termset.c_cc[VTIME] = 0;
+ ioctl(Fileno(), TCSETA, &termset);
+#elif defined(USE_SGTTY)
+ termset.sg_flags |= CBREAK;
+ termset.sg_flags &= ~ECHO;
+ stty(Fileno(), &termset);
+#endif
+ break;
+
+ case K_LINES: // read a line at a time (allow terminal editing)
+#if defined(USE_TERMIOS)
+ termset.c_lflag |= (ICANON | ECHO);
+ termset.c_cc[VMIN] = 1;
+ termset.c_cc[VTIME] = 0;
+ tcsetattr(Fileno(), TCSANOW, &termset);
+#elif defined(USE_TERMIO)
+ termset.c_lflag |= (ICANON | ECHO);
+ termset.c_cc[VMIN] = 1;
+ termset.c_cc[VTIME] = 0;
+ ioctl(Fileno(), TCSETA, &termset);
+#elif defined(USE_SGTTY)
+ termset.sg_flags &= ~CBREAK;
+ termset.sg_flags |= ECHO;
+ stty(Fileno(), &termset);
+#endif
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+int ConStream::Output(const char *message, va_list ap)
+{
+ if( m_suspend ) return 0;
+
+ int old_newline = m_newline;
+ _newline();
+ _convprintf(message, ap);
+ _newline();
+ fflush(m_stream);
+ return (old_newline==m_newline) ? 0 : 1;
+}
+
+
+int ConStream::Output_n(const char *message, va_list ap)
+{
+ if( m_suspend ) return 0;
+
+ int old_newline = m_newline;
+ if( !message || !*message ) _newline();
+ else _convprintf(message, ap);
+ fflush(m_stream);
+ return (old_newline==m_newline) ? 0 : 1;
+}
+
+
+int ConStream::Update(const char *message, va_list ap)
+{
+ if( m_suspend ) return 0;
+
+ int old_newline = m_newline;
+ if( !m_newline) fprintf(m_stream, IsTTY() ? "\r" : "\n");
+ _convprintf(message, ap);
+ fflush(m_stream);
+ return (old_newline==m_newline) ? 0 : 1;
+}
+
+
+char *ConStream::Input(char *field, size_t length)
+{
+ if( m_suspend ) return (char *)0;
+
+ m_newline = 1;
+ return fgets(field, length, m_stream);
+}
+
+
+int ConStream::CharIn()
+{
+ if( m_suspend ) return 0;
+
+ return fgetc(m_stream);
+}
+
+
+inline void ConStream::_newline()
+{
+ if( !m_newline ){
+ fprintf(m_stream, "\n");
+ m_newline = 1;
+ }
+}
+
+
+inline int ConStream::_convprintf(const char *format, va_list ap)
+{
+ int r = ( '\n' == format[strlen(format)-1] );
+ m_newline = r;
+ return vfprintf(m_stream, format, ap);
+}
+
+
+/* ConStream functions need to call Error instead of CONSOLE.Warning, because
+ CONSOLE may not be initialized yet (or may have been destroyed already).
+*/
+void ConStream::Error(int sev, const char *message, ...)
+{
+ va_list ap;
+
+ va_start(ap, message);
+ /* Note the call to Warning sends only the literal message--a limitation to
+ deal with later. */
+ if( g_console_ready ) CONSOLE.Warning(sev, message);
+ else{
+ vfprintf(stderr, message, ap);
+ fflush(stderr);
+ }
+ va_end(ap);
+}
+
+
+
+//===========================================================================
+// Console class functions
+
+
+Console::Console()
+{
+ m_skip_status = m_status_last = 0;
+ m_live_idx = 0;
+ m_oldfd = -1;
+
+ m_status_format = 0;
+ int i = 0;
+ m_statusline[i++] = &Console::StatusLine0;
+ m_statusline[i++] = &Console::StatusLine1;
+ if( STATUSLINES > i ){
+ fprintf(stderr, "Unassigned status line in Console() constructor!\n");
+ exit(1);
+ }else if ( STATUSLINES < i ){
+ fprintf(stderr, "Value of STATUSLINES is too small!\n");
+ exit(1);
+ }
+
+ m_status_len = 80;
+
+ m_stdout.Associate(stdout, "stdout", 1);
+ m_stderr.Associate(stderr, "stderr", 1);
+ m_stdin.Associate(stdin, "stdin", 0);
+ m_off.Associate(NULL, "off", 1);
+ m_off.Suspend();
+ m_streams[O_NORMAL] = &m_stdout;
+ m_streams[O_WARNING] = &m_stderr;
+ m_streams[O_DEBUG] = &m_stderr;
+ m_streams[O_INTERACT] = &m_stdout;
+ m_streams[O_INPUT] = &m_stdin;
+
+ m_streams[O_INPUT]->PreserveMode();
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ m_conmode = K_CHARS;
+
+ if( this == &CONSOLE ) g_console_ready = 1;
+}
+
+
+Console::~Console()
+{
+ if( this == &CONSOLE ) g_console_ready = 0;
+}
+
+
+int Console::IntervalCheck(fd_set *rfdp, fd_set *wfdp)
+{
+ Status(0);
+
+ if( m_oldfd >= 0 ){
+ FD_CLR(m_oldfd, rfdp);
+ m_oldfd = -1;
+ }
+
+ if( !m_streams[O_INPUT]->IsSuspended() ){
+ FD_SET(m_streams[O_INPUT]->Fileno(), rfdp);
+ return m_streams[O_INPUT]->Fileno();
+ }else{
+ if( m_streams[O_INPUT]->Fileno() >= 0 )
+ FD_CLR(m_streams[O_INPUT]->Fileno(), rfdp);
+ return -1;
+ }
+}
+
+
+void Console::User(fd_set *rfdp, fd_set *wfdp, int *nready,
+ fd_set *rfdnextp, fd_set *wfdnextp)
+{
+ static char pending = '\0';
+ static int inc, count;
+ char c, param[MAXPATHLEN], *s;
+
+ if( m_streams[O_INPUT]->Fileno() >= 0 &&
+ FD_ISSET(m_streams[O_INPUT]->Fileno(), rfdp) ){
+ FD_CLR(m_streams[O_INPUT]->Fileno(), rfdnextp);
+ (*nready)--;
+ if( K_LINES==m_streams[O_INPUT]->GetInputMode() ){ // command parameter
+ SyncNewlines(O_INPUT);
+ if( m_streams[O_INPUT]->Input(param, sizeof(param)) ){
+ if( s = strchr(param, '\n') ) *s = '\0';
+ if( '0'==pending ){
+ if( OperatorMenu(param) ) pending = '\0';
+ }else{
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ if( *param ) switch( pending ){
+ case 'n': // get1file
+ if( arg_file_to_download ) delete []arg_file_to_download;
+ arg_file_to_download = new char[strlen(param) + 1];
+ if( !arg_file_to_download )
+ Warning(1, "error, failed to allocate memory for option");
+ else strcpy(arg_file_to_download, param);
+ BTCONTENT.SetFilter();
+ break;
+ case 'S': // CTCS server
+ if( !strchr(param, ':') )
+ Interact("Invalid input");
+ else{
+ if( arg_ctcs ) delete []arg_ctcs;
+ if(0==strcmp(":", param)){
+ if(arg_ctcs) CTCS.Reset(1);
+ arg_ctcs = (char*) 0;
+ }else{
+ arg_ctcs = new char[strlen(param) + 1];
+ if( !arg_ctcs )
+ Warning(1, "error, failed to allocate memory for option");
+ else{
+ strcpy(arg_ctcs, param);
+ CTCS.Initial();
+ CTCS.Reset(1);
+ }
+ }
+ }
+ break;
+ case 'X': // completion command (user exit)
+ if( arg_completion_exit ) delete []arg_completion_exit;
+ arg_completion_exit = new char[strlen(param) + 1];
+ if( !arg_completion_exit )
+ Warning(1, "error, failed to allocate memory for option");
+ else strcpy(arg_completion_exit, param);
+ break;
+ case 'Q': // quit
+ if( 'y'==*param || 'Y'==*param ){
+ Tracker.ClearRestart();
+ Tracker.SetStoped();
+ }
+ break;
+ default:
+ Interact("Input mode error");
+ }
+ }
+ }else{
+ if( m_streams[O_INPUT]->Eof() ){
+ Interact("End of input reached.");
+ if( ChangeChannel(O_INPUT, "off") < 0 )
+ m_streams[O_INPUT]->Suspend();
+ }else if(errno){
+ if( ENODEV==errno || ENOTTY==errno ) m_streams[O_INPUT]->Suspend();
+ else Interact("Input error: %s", strerror(errno));
+ }else Interact("Input error!");
+ }
+ if( '0' != pending ){
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ Status(1);
+ }
+
+ }else{ // command character received
+
+ m_skip_status = 1;
+ if( (c = m_streams[O_INPUT]->CharIn()) == EOF ){
+ if( m_streams[O_INPUT]->Eof() ){
+ Interact("End of input reached.");
+ if( ChangeChannel(O_INPUT, "off") < 0 )
+ m_streams[O_INPUT]->Suspend();
+ }else if(errno){
+ if( ENODEV==errno || ENOTTY==errno ) m_streams[O_INPUT]->Suspend();
+ else Interact("Input error: %s", strerror(errno));
+ }else Interact("Input error!");
+ return;
+ }
+ if( c!='+' && c!='-' ) pending = c;
+ switch( c ){
+ case 'h': // help
+ case '?': // help
+ Interact("Available commands:");
+ Interact(" %-9s%-30s %-9s%s", "[Esc/0]", "Operator menu",
+ "m[+/-]", "Adjust min peers count");
+ Interact(" %-9s%-30s %-9s%s", "d[+/-]", "Adjust download limit",
+ "M[+/-]", "Adjust max peers count");
+ Interact(" %-9s%-30s %-9s%s", "u[+/-]", "Adjust upload limit",
+ "C[+/-]", "Adjust max cache size");
+ Interact(" %-9s%-30s %-9s%s", "n", "Download specific files",
+ "S", "Set/change CTCS server");
+ Interact(" %-9s%-30s %-9s%s", "e[+/-]", "Adjust seed exit time",
+ "v", "Toggle verbose mode");
+ Interact(" %-9s%-30s %-9s%s", "E[+/-]", "Adjust seed exit ratio",
+ "Q", "Quit");
+ Interact(" %-9s%-30s %-9s%s", "X", "Completion command",
+ "", "");
+ break;
+ case 'd': // download bw limit
+ case 'u': // upload bw limit
+ if(arg_ctcs) Interact("Note, changes may be overridden by CTCS.");
+ case 'e': // seed time
+ case 'E': // seed ratio
+ case 'm': // min peers
+ case 'M': // max peers
+ case 'C': // max cache size
+ inc = 1; count = 0;
+ Interact_n("");
+ break;
+ case 'n': // get1file
+ if( BTCONTENT.IsFull() )
+ Interact("Download is already complete.");
+ else{
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ ShowFiles();
+ Interact("Enter 0 or * for all files (normal behavior).");
+ if( arg_file_to_download )
+ Interact_n("Get file number/list (currently %s): ",
+ arg_file_to_download);
+ else Interact_n("Get file number/list: ");
+ }
+ break;
+ case 'S': // CTCS server
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ Interact_n("");
+ if( arg_ctcs ){
+ Interact("Enter ':' to stop using CTCS.");
+ Interact_n("CTCS server:port (currently %s): ", arg_ctcs);
+ }
+ else Interact_n("CTCS server:port: ");
+ break;
+ case 'X': // completion command (user exit)
+ if( BTCONTENT.IsFull() )
+ Interact("Download is already complete.");
+ else{
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ Interact("Enter a command to run upon download completion.");
+ if( arg_completion_exit )
+ Interact("Currently: %s", arg_completion_exit);
+ Interact_n(">");
+ }
+ break;
+ case 'v': // verbose
+ if( arg_verbose && !m_streams[O_INPUT]->SameDev(m_streams[O_DEBUG]) )
+ Debug("Verbose output off");
+ arg_verbose = !arg_verbose;
+ Interact("Verbose output %s", arg_verbose ? "on" : "off");
+ break;
+ case 'Q': // quit
+ if( !Tracker.IsQuitting() ){
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ Interact_n("");
+ Interact_n("Quit: Are you sure? ");
+ }
+ break;
+ case '+': // increase value
+ case '-': // decrease value
+ if( ('+'==c && inc<0) || ('-'==c && inc>0) ) inc *= -1;
+ switch( pending ){
+ int value;
+ case 'd': cfg_max_bandwidth_down +=
+ ( (cfg_max_bandwidth_down * (abs(inc)/100.0) < 1) ? inc :
+ (int)(cfg_max_bandwidth_down * (inc/100.0)) );
+ if( cfg_max_bandwidth_down < 0 ) cfg_max_bandwidth_down = 0;
+ break;
+ case 'u': cfg_max_bandwidth_up +=
+ ( (cfg_max_bandwidth_up * (abs(inc)/100.0) < 1) ? inc :
+ (int)(cfg_max_bandwidth_up * (inc/100.0)) );
+ if( cfg_max_bandwidth_up < 0 ) cfg_max_bandwidth_up = 0;
+ break;
+ case 'e': cfg_seed_hours += inc;
+ if( cfg_seed_hours < 0 ) cfg_seed_hours = 0;
+ break;
+ case 'E': cfg_seed_ratio += inc / 10.0;
+ if( cfg_seed_ratio < 0 ) cfg_seed_ratio = 0;
+ break;
+ case 'm': value = (int)cfg_min_peers; value += inc;
+ cfg_min_peers = (value < 1) ? 1 : (size_t)value;
+ if( cfg_min_peers > cfg_max_peers ) cfg_min_peers = cfg_max_peers;
+ break;
+ case 'M': value = (int)cfg_max_peers; value += inc;
+ cfg_max_peers = (value < (int)cfg_min_peers) ?
+ cfg_min_peers : (size_t)value;
+ if( cfg_max_peers > 1000 ) cfg_max_peers = 1000;
+ break;
+ case 'C': value = (int)cfg_cache_size; value += inc;
+ cfg_cache_size = (value < 0) ? 0 : (size_t)value;
+ BTCONTENT.CacheConfigure();
+ break;
+ default:
+ Status(1);
+ break;
+ }
+ if( 10==++count ) inc *= 2;
+ else if( 5==count ) inc *= 5;
+ if( arg_ctcs ){
+ if( 'd'==pending || 'u'==pending ) CTCS.Send_bw();
+ else CTCS.Send_Config();
+ }
+ break;
+ case '0': // operator menu
+ case 0x1b: // Escape key
+ pending = '0';
+ OperatorMenu("");
+ break;
+ default:
+ Status(1);
+ break;
+ }
+
+ switch( pending ){
+ case 'd': InteractU("DL Limit: %d B/s ", (int)cfg_max_bandwidth_down);
+ break;
+ case 'u': InteractU("UL Limit: %d B/s ", (int)cfg_max_bandwidth_up);
+ break;
+ case 'e': InteractU("Seed time: %.1f hours ", BTCONTENT.GetSeedTime() ?
+ (cfg_seed_hours - (now - BTCONTENT.GetSeedTime())/(double)3600) :
+ (double)cfg_seed_hours);
+ break;
+ case 'E': InteractU("Seed ratio: %.2f ", (double)cfg_seed_ratio);
+ break;
+ case 'm': InteractU("Minimum peers: %d ", (int)cfg_min_peers);
+ break;
+ case 'M': InteractU("Maximum peers: %d ", (int)cfg_max_peers);
+ break;
+ case 'C': InteractU("Maximum cache: %d MB ", (int)cfg_cache_size);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
+// Return non-zero to exit operator menu mode.
+int Console::OperatorMenu(const char *param)
+{
+ static int oper_mode = 0;
+ static int channel, n_opt;
+
+ if( 0==oper_mode ){
+ Interact("Operator Menu");
+ n_opt = 0;
+ Interact(" Console Channels:");
+ Interact(" %2d) Normal/status: %s", ++n_opt,
+ m_streams[O_NORMAL]->GetName());
+ Interact(" %2d) Interactive: %s", ++n_opt,
+ m_streams[O_INTERACT]->GetName());
+ Interact(" %2d) Error/warning: %s", ++n_opt,
+ m_streams[O_WARNING]->GetName());
+ Interact(" %2d) Debug/verbose: %s", ++n_opt,
+ m_streams[O_DEBUG]->GetName());
+ Interact(" %2d) Input: %s", ++n_opt,
+ m_streams[O_INPUT]->GetName());
+ char buffer[80];
+ Interact(" Status Line Formats:");
+ for( int i=0; i < STATUSLINES; i++ ){
+ (this->*m_statusline[i])(buffer, sizeof(buffer));
+ Interact(" %c%d) %s", (i==m_status_format) ? '*' : ' ', ++n_opt, buffer);
+ }
+ Interact(" Other options:");
+ Interact(" %2d) View detailed status", ++n_opt);
+ if( WORLD.IsPaused() )
+ Interact(" %2d) Resume (continue upload/download)", ++n_opt);
+ else Interact(" %2d) Pause (suspend upload/download)", ++n_opt);
+ if( !arg_daemon )
+ Interact(" %2d) Become daemon (fork to background)", ++n_opt);
+ Interact(" %2d) Update tracker stats & get peers", ++n_opt);
+ Interact(" %2d) Restart (recover) the tracker session", ++n_opt);
+ Interact_n("Enter selection: ");
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ oper_mode = 1;
+ return 0;
+ }
+ else if( 1==oper_mode ){
+ if( !*param ){ oper_mode = 0; Interact("Exiting menu"); return 1; }
+ int sel = atoi(param);
+ if( sel < 1 || sel > n_opt ){
+ Interact_n("Enter selection: ");
+ return 0;
+ }
+ if( sel <= O_NCHANNELS+1 ){ // change i/o channel
+ channel = sel - 1;
+ Interact("Possible values are:");
+ Interact(" %s", m_stdout.GetName());
+ Interact(" %s", m_stderr.GetName());
+ Interact(" %s", m_off.GetName());
+ Interact(" a filename");
+ Interact_n("Enter a destination: ");
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ oper_mode = 2;
+ return 0;
+ }else if( sel <= O_NCHANNELS+1 + STATUSLINES ){
+ m_status_format = sel - (O_NCHANNELS+1) - 1;
+ oper_mode = 0;
+ return OperatorMenu("");
+ }else if( sel == 1 + O_NCHANNELS+1 + STATUSLINES ){ // detailed status
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ Interact("");
+ Interact("Torrent: %s", arg_metainfo_file);
+ ShowFiles();
+ if( arg_file_to_download && !BTCONTENT.Seeding() )
+ Interact("Downloading: %s", arg_file_to_download);
+ Interact("");
+ Interact("Download rate: %dB/s Limit: %dB/s Total: %llu",
+ (int)(Self.RateDL()), (int)cfg_max_bandwidth_down,
+ (unsigned long long)(Self.TotalDL()));
+ Interact(" Upload rate: %dB/s Limit: %dB/s Total: %llu",
+ (int)(Self.RateUL()), (int)cfg_max_bandwidth_up,
+ (unsigned long long)(Self.TotalUL()));
+ time_t t = Tracker.GetReportTime();
+ if( t ){
+ char s[42];
+#ifdef HAVE_CTIME_R_3
+ ctime_r(&t, s, sizeof(s));
+#else
+ ctime_r(&t, s);
+#endif
+ if( s[strlen(s)-1] == '\n' ) s[strlen(s)-1] = '\0';
+ Interact("Reported to tracker: %llu up",
+ (unsigned long long)(Tracker.GetReportUL()));
+ Interact(" %llu down at %s",
+ (unsigned long long)(Tracker.GetReportDL()), s);
+ }
+ Interact("Failed hashes: %d Dup blocks: %d Unwanted blocks: %d",
+ (int)(BTCONTENT.GetHashFailures()), (int)(BTCONTENT.GetDupBlocks()),
+ (int)(BTCONTENT.GetUnwantedBlocks()));
+ Interact("");
+ Interact("Peers: %d Min: %d Max: %d",
+ (int)(WORLD.GetPeersCount()), (int)cfg_min_peers, (int)cfg_max_peers);
+ Interact("Listening on: %s", WORLD.GetListen());
+ Interact("Announce URL: %s", BTCONTENT.GetAnnounce());
+ Interact("");
+ Interact("Ratio: %.2f Seed time: %luh Seed ratio: %.2f",
+ (double)(Self.TotalUL()) / ( Self.TotalDL() ? Self.TotalDL() :
+ BTCONTENT.GetTotalFilesLength() ),
+ (unsigned long)cfg_seed_hours, cfg_seed_ratio);
+ Interact("Cache in use: %dKB Wants: %dKB Max: %dMB",
+ (int)(BTCONTENT.CacheUsed()/1024), (int)(BTCONTENT.CacheSize()/1024),
+ (int)cfg_cache_size);
+ if(arg_ctcs) Interact("CTCS Server: %s", arg_ctcs);
+ if(arg_verbose) cpu();
+ oper_mode = 0;
+ return 1;
+ }else if( sel == 2 + O_NCHANNELS+1 + STATUSLINES ){ // pause/resume
+ if( WORLD.IsPaused() ) WORLD.Resume();
+ else WORLD.Pause();
+ oper_mode = 0;
+ return 1;
+ }else if( sel == 3 + O_NCHANNELS+1 + STATUSLINES ){ // daemon
+ Daemonize();
+ oper_mode = 0;
+ return 1;
+ }else if( sel == 4 + O_NCHANNELS+1 + STATUSLINES ){ // update tracker
+ if( Tracker.GetStatus() == T_FREE ) Tracker.Reset(15);
+ else Interact("Already connecting, please be patient...");
+ oper_mode = 0;
+ return 1;
+ }else if( sel == 5 + O_NCHANNELS+1 + STATUSLINES ){ // update tracker
+ Tracker.RestartTracker();
+ oper_mode = 0;
+ return 1;
+ }
+ }
+ else if( 2==oper_mode ){
+ if( !*param ){
+ oper_mode = 0;
+ return OperatorMenu("");
+ }
+ ChangeChannel(channel, param);
+ oper_mode = 0;
+ return OperatorMenu("");
+ }
+
+ Interact("Exiting menu");
+ return 1;
+}
+
+
+int Console::ChangeChannel(int channel, const char *param, int notify)
+{
+ ConStream *dest = (ConStream *)0;
+
+ if( 0==strcasecmp(param, m_stdout.GetName()) ) dest = &m_stdout;
+ else if( 0==strcasecmp(param, m_stderr.GetName()) ) dest = &m_stderr;
+ else if( 0==strcasecmp(param, m_stdin.GetName()) ) dest = &m_stdin;
+ else if( 0==strcasecmp(param, m_off.GetName()) ) dest = &m_off;
+ else{
+ for( int i=0; i <= O_NCHANNELS; i++ ){
+ if( channel != i && 0==strcmp(param, m_streams[i]->GetName()) &&
+ m_streams[i]->GetMode() == ((channel==O_INPUT) ? 0 : 1) ){
+ dest = m_streams[i];
+ break;
+ }
+ }
+ if( !dest ){
+ FILE *stream;
+ if( dest = new ConStream ){
+ if( 0==strcmp(param, m_streams[channel]->GetName()) ){
+ delete m_streams[channel];
+ m_streams[channel] = &m_off;
+ }
+ if( stream = fopen(param, (channel==O_INPUT) ? "r" : "a") )
+ dest->Associate(stream, param, (channel==O_INPUT) ? 0 : 1);
+ else{
+ Interact("Error opening file: %s", strerror(errno));
+ delete dest;
+ dest = (ConStream *)0;
+ }
+ }else Interact("Failed to allocate memory.");
+ }
+ }
+ if( dest ){
+ if( O_INPUT==channel ) m_oldfd = m_streams[channel]->Fileno();
+ if( m_streams[channel] != &m_stdout && m_streams[channel] != &m_stderr &&
+ m_streams[channel] != &m_stdin && m_streams[channel] != &m_off ){
+ int in_use = 0;
+ for( int i=0; i <= O_NCHANNELS; i++ ){
+ if( channel != i && m_streams[channel] == m_streams[i] ) in_use = 1;
+ }
+ if( !in_use ) delete m_streams[channel];
+ else if( O_INPUT==channel ) m_streams[O_INPUT]->RestoreMode();
+ }
+ if( notify && (!arg_daemon || !m_streams[channel]->IsTTY()) ){
+ switch(channel){
+ case O_NORMAL:
+ Print("Output channel is now %s", dest->GetName());
+ break;
+ case O_DEBUG:
+ Debug("Debug channel is now %s", dest->GetName());
+ break;
+ case O_INTERACT:
+ Interact("Interactive output channel is now %s", dest->GetName());
+ break;
+ case O_INPUT:
+ Interact("Input channel is now %s", dest->GetName());
+ break;
+ default:
+ break;
+ }
+ }
+ m_streams[channel] = dest;
+ if( O_INPUT==channel ){
+ m_streams[O_INPUT]->PreserveMode();
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ }
+ return 0;
+ }else return -1;
+}
+
+
+void Console::ShowFiles()
+{
+ BTFILE *file = 0;
+ BitField tmpFilter;
+ int n = 0;
+
+ Interact("Files in this torrent:");
+ while( ++n <= BTCONTENT.GetNFiles() ){
+ BTCONTENT.SetTmpFilter(n, &tmpFilter);
+ BitField tmpBitField = *BTCONTENT.pBF;
+ tmpBitField.Except(tmpFilter);
+ Interact("%d) %s [%llu] %d%%", n, BTCONTENT.GetFileName(n),
+ (unsigned long long)(BTCONTENT.GetFileSize(n)),
+ BTCONTENT.GetFilePieces(n) ?
+ (int)(100 * tmpBitField.Count() / BTCONTENT.GetFilePieces(n)) : 0);
+ }
+}
+
+
+void Console::Status(int immediate)
+{
+ static char buffer[80];
+
+ if( immediate ) m_skip_status = 0;
+ if( m_pre_dlrate.TimeUsed() || immediate ){
+ if( m_skip_status ) m_skip_status = 0;
+ else if( !m_streams[O_NORMAL]->IsSuspended() ||
+ (arg_verbose && !m_streams[O_DEBUG]->IsSuspended()) ){
+ // optimized to generate the status line only if it will be output
+ (this->*m_statusline[m_status_format])(buffer, sizeof(buffer));
+
+ if( !m_status_last ) Print_n("");
+ int tmplen = 0;
+ if( m_streams[O_NORMAL]->IsTTY() ){
+#ifdef TIOCGWINSZ
+ struct winsize tsize;
+ if( ioctl(m_streams[O_NORMAL]->Fileno(), TIOCGWINSZ, &tsize) >= 0 )
+ tmplen = tsize.ws_col - 1;
+#else
+#ifdef TIOCGSIZE
+ struct ttysize tsize;
+ if( ioctl(m_streams[O_NORMAL]->Fileno(), TIOCGSIZE, &tsize) >= 0 )
+ tmplen = tsize.ts_cols - 1;
+#else
+#ifdef WIOCGETD
+ struct uwdata tsize;
+ if( ioctl(m_streams[O_NORMAL]->Fileno(), WIOCGETD, &tsize) >= 0 )
+ tmplen = tsize.uw_width / tsize.uw_hs - 1;
+#endif
+#endif
+#endif
+ if( tmplen > 80 ) tmplen = 80;
+ }
+ int len = strlen(buffer);
+ if( 0==tmplen ) tmplen = (len < m_status_len) ? m_status_len : len;
+ m_status_len = len;
+ Update("%*.*s", -tmplen, tmplen, buffer);
+ m_status_last = 1;
+
+ if(arg_verbose)
+ Debug("Cache: %dK/%dM Hits: %d Miss: %d %d%% Pre: %d/%d",
+ (int)(BTCONTENT.CacheUsed()/1024), (int)cfg_cache_size,
+ (int)(BTCONTENT.CacheHits()), (int)(BTCONTENT.CacheMiss()),
+ BTCONTENT.CacheHits() ? (int)(100 * BTCONTENT.CacheHits() /
+ (BTCONTENT.CacheHits()+BTCONTENT.CacheMiss())) : 0,
+ BTCONTENT.CachePre(), (int)(Self.TotalUL() / DEFAULT_SLICE_SIZE));
+ }
+
+ m_pre_dlrate = Self.GetDLRate();
+ m_pre_ulrate = Self.GetULRate();
+ }
+}
+
+
+void Console::StatusLine0(char buffer[], size_t length)
+{
+ char partial[30] = "";
+ if( BTCONTENT.GetFilter() && !BTCONTENT.GetFilter()->IsEmpty() ){
+ BitField tmpBitField = *BTCONTENT.pBF;
+ tmpBitField.Except(BTCONTENT.GetFilter());
+ sprintf( partial, "P:%d/%d ",
+ (int)(tmpBitField.Count()),
+ (int)(BTCONTENT.GetNPieces() - BTCONTENT.GetFilter()->Count()) );
+ }
+
+ char checked[14] = "";
+ if( BTCONTENT.CheckedPieces() < BTCONTENT.GetNPieces() ){
+ sprintf( checked, "Checking: %d%%",
+ 100 * BTCONTENT.CheckedPieces() / BTCONTENT.GetNPieces() );
+ }
+
+ snprintf(buffer, length,
+ "%c %d/%d/%d [%d/%d] %lluMB,%lluMB | %d,%dK/s | %d,%dK %s%s",
+ LIVE_CHAR[m_live_idx++],
+
+ (int)(WORLD.GetSeedsCount()),
+ (int)(WORLD.GetPeersCount()) - WORLD.GetSeedsCount(),
+ (int)(Tracker.GetPeersCount()),
+
+ (int)(BTCONTENT.pBF->Count()),
+ (int)(BTCONTENT.GetNPieces()),
+
+ (unsigned long long)(Self.TotalDL() >> 20),
+ (unsigned long long)(Self.TotalUL() >> 20),
+
+ (int)(Self.RateDL() >> 10),
+ (int)(Self.RateUL() >> 10),
+
+ (int)(m_pre_dlrate.RateMeasure(Self.GetDLRate()) >> 10),
+ (int)(m_pre_ulrate.RateMeasure(Self.GetULRate()) >> 10),
+
+ partial,
+
+ (Tracker.GetStatus()==T_CONNECTING) ? "Connecting" :
+ ( (Tracker.GetStatus()==T_READY) ? "Connected" :
+ (Tracker.IsRestarting() ? "Restarting" :
+ (Tracker.IsQuitting() ? "Quitting" :
+ (WORLD.IsPaused() ? "Paused" : checked))) )
+ );
+}
+
+
+void Console::StatusLine1(char buffer[], size_t length)
+{
+ char partial[30] = "";
+ if( BTCONTENT.GetFilter() && !BTCONTENT.GetFilter()->IsEmpty() ){
+ int have, avail, all;
+ long premain = -1;
+ char ptime[20] = "";
+ size_t rate;
+ BitField tmpBitfield = *BTCONTENT.pBF;
+ tmpBitfield.Except(BTCONTENT.GetFilter());
+ have = tmpBitfield.Count();
+
+ WORLD.Pieces_I_Can_Get(&tmpBitfield);
+ tmpBitfield.Except(BTCONTENT.GetFilter());
+ avail = tmpBitfield.Count();
+
+ all = BTCONTENT.GetNPieces() - BTCONTENT.GetFilter()->Count();
+
+ if( rate = Self.RateDL() ){
+ premain = (all - have) * BTCONTENT.GetPieceLength() / rate / 60;
+ if( premain < 60000 ) // 1000 hours
+ snprintf(ptime, sizeof(ptime), " %d:%2.2d",
+ (int)(premain / 60), (int)(premain % 60));
+ }
+ sprintf(partial, "P:%d/%d%%%s ",
+ 100 * have / all, 100 * avail / all, ptime);
+ }
+
+
+ char checked[14] = "";
+ if( BTCONTENT.CheckedPieces() < BTCONTENT.GetNPieces() ){
+ sprintf( checked, "Checking: %d%%",
+ 100 * BTCONTENT.CheckedPieces() / BTCONTENT.GetNPieces() );
+ }
+
+ char complete[8];
+ if( BTCONTENT.IsFull() )
+ sprintf(complete, "seeding");
+ else if( BTCONTENT.Seeding() )
+ sprintf(complete, "seed%d%%",
+ 100 * BTCONTENT.pBF->Count() / BTCONTENT.GetNPieces());
+ else{
+ int have, avail, all;
+ BitField tmpBitfield = *BTCONTENT.pBF;
+ tmpBitfield.Except(*BTCONTENT.pBMasterFilter);
+ have = tmpBitfield.Count();
+
+ WORLD.Pieces_I_Can_Get(&tmpBitfield);
+ tmpBitfield.Except(*BTCONTENT.pBMasterFilter);
+ avail = tmpBitfield.Count();
+
+ all = BTCONTENT.GetNPieces() - BTCONTENT.pBMasterFilter->Count();
+ sprintf(complete, "%d/%d%%", 100 * have / all, 100 * avail / all);
+ }
+
+ long remain = -1;
+ char timeleft[20];
+ size_t rate;
+ if( !BTCONTENT.Seeding() || BTCONTENT.FlushFailed() ){ // downloading
+ if( rate = Self.RateDL() ){
+ // don't overflow remain
+ if( BTCONTENT.GetLeftBytes() < (uint64_t)rate << 22 )
+ remain = BTCONTENT.GetLeftBytes() / rate / 60;
+ else remain = 99999;
+ }
+ }else{ //seeding
+ if( cfg_seed_hours )
+ remain = cfg_seed_hours * 60 - (now - BTCONTENT.GetSeedTime()) / 60;
+ else if( rate = Self.RateUL() ){
+ // don't overflow remain
+ if( cfg_seed_ratio *
+ (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) -
+ Self.TotalUL() < (uint64_t)rate << 22 )
+ remain = (long)( cfg_seed_ratio *
+ (Self.TotalDL() ? Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) -
+ Self.TotalUL() ) / rate / 60;
+ else remain = 99999;
+ }
+ }
+ if( remain >= 0 ){
+ if( remain < 60000 ) // 1000 hours
+ snprintf(timeleft, sizeof(timeleft), "%d:%2.2d",
+ (int)(remain / 60), (int)(remain % 60));
+ else strcpy(timeleft, ">999hr");
+ }else if( BTCONTENT.CheckedPieces() < BTCONTENT.GetNPieces() ){
+ // Don't say stalled if still checking and nothing to download yet.
+ BitField tmpBitfield = *BTCONTENT.pBChecked;
+ tmpBitfield.Except(BTCONTENT.pBF);
+ if(tmpBitfield.IsEmpty()) strcpy(timeleft, "unknown");
+ else strcpy(timeleft, "stalled");
+ }else strcpy(timeleft, "stalled");
+
+ snprintf(buffer, length,
+ "%c S:%d/%d L:%d/%d C:%d R=%.2f D=%d U=%d K/s %s %s %s%s",
+ LIVE_CHAR[m_live_idx++],
+
+ (int)(WORLD.GetSeedsCount()),
+ (int)(Tracker.GetSeedsCount()) - (BTCONTENT.IsFull() ? 1 : 0),
+
+ (int)(WORLD.GetPeersCount()) - WORLD.GetSeedsCount() - WORLD.GetConnCount(),
+ (int)(Tracker.GetPeersCount()) - Tracker.GetSeedsCount() -
+ (!BTCONTENT.IsFull() ? 1 : 0),
+
+ (int)(WORLD.GetConnCount()),
+
+
+ (double)(Self.TotalUL()) / ( Self.TotalDL() ? Self.TotalDL() :
+ BTCONTENT.GetTotalFilesLength() ),
+
+ (int)(Self.RateDL() >> 10), (int)(Self.RateUL() >> 10),
+
+ complete, timeleft,
+
+ partial,
+
+ (Tracker.GetStatus()==T_CONNECTING) ? "Connecting" :
+ ( (Tracker.GetStatus()==T_READY) ? "Connected" :
+ (Tracker.IsRestarting() ? "Restarting" :
+ (Tracker.IsQuitting() ? "Quitting" :
+ (WORLD.IsPaused() ? "Paused" : checked))) )
+ );
+}
+
+
+void Console::Print(const char *message, ...)
+{
+ va_list ap;
+
+ if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||
+ m_streams[O_INPUT]->IsSuspended() ||
+ (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&
+ !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){
+ va_start(ap, message);
+ if( m_streams[O_NORMAL]->Output(message, ap) )
+ SyncNewlines(O_NORMAL);
+ va_end(ap);
+ }
+ if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output(message, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ }
+}
+
+
+/* Print message without a terminating newline
+ With a null message, start/insure a new line
+*/
+void Console::Print_n(const char *message, ...)
+{
+ va_list ap;
+
+ if( m_status_last && message && *message ) Print_n("");
+ m_status_last = 0;
+
+ if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||
+ m_streams[O_INPUT]->IsSuspended() ||
+ (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&
+ !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){
+ va_start(ap, message);
+ if( m_streams[O_NORMAL]->Output_n(message, ap) )
+ SyncNewlines(O_NORMAL);
+ va_end(ap);
+ }
+ if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output_n(message, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ }
+}
+
+
+/* Update (replace) the current line (no terminating newline)
+*/
+void Console::Update(const char *message, ...)
+{
+ va_list ap;
+
+ m_status_last = 0;
+
+ if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||
+ m_streams[O_INPUT]->IsSuspended() ||
+ (!m_streams[O_NORMAL]->SameDev(m_streams[O_INTERACT]) &&
+ !m_streams[O_NORMAL]->SameDev(m_streams[O_INPUT])) ){
+ va_start(ap, message);
+ if( m_streams[O_NORMAL]->Update(message, ap) )
+ SyncNewlines(O_NORMAL);
+ va_end(ap);
+ }
+ if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Update(message, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ }
+}
+
+
+/* "sev" indicates the severity of the message.
+ 0: will be printed but not sent to CTCS
+ 1: extremely urgent/important
+ 2: less important
+ 3: no problem
+*/
+void Console::Warning(int sev, const char *message, ...)
+{
+ va_list ap;
+
+ va_start(ap, message);
+ if( m_streams[O_WARNING]->Output(message, ap) )
+ SyncNewlines(O_WARNING);
+ va_end(ap);
+ if( arg_verbose && !m_streams[O_DEBUG]->SameDev(m_streams[O_WARNING]) ){
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output(message, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ }
+
+ if(sev && arg_ctcs){
+ char cmsg[CTCS_BUFSIZE];
+ va_start(ap, message);
+ vsnprintf(cmsg, CTCS_BUFSIZE, message, ap);
+ CTCS.Send_Info(sev, cmsg);
+ va_end(ap);
+ }
+}
+
+
+void Console::Debug(const char *message, ...)
+{
+ static char buffer[80];
+ if( !arg_verbose ) return;
+
+ char *format = (char *)0;
+ size_t buflen;
+ va_list ap;
+
+ if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||
+ m_streams[O_INPUT]->IsSuspended() ||
+ (!m_streams[O_DEBUG]->SameDev(m_streams[O_INTERACT]) &&
+ !m_streams[O_DEBUG]->SameDev(m_streams[O_INPUT])) ){
+ size_t need = strlen(message)+1 + 10*sizeof(unsigned long)/4;
+ if( need > sizeof(buffer) && (format = new char[need]) ) buflen = need;
+ else{ format = buffer; buflen = sizeof(buffer); }
+
+ snprintf(format, buflen, "%lu %s", (unsigned long)now, message);
+
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output(format, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+
+ if( format && format != buffer ) delete []format;
+ }
+}
+
+
+/* Print debug message without a terminating newline
+ With a null message, start/insure a new line
+*/
+void Console::Debug_n(const char *message, ...)
+{
+ static char buffer[80];
+ static int f_new_line = 1;
+ if( !arg_verbose ) return;
+
+ va_list ap;
+
+ if( K_LINES != m_streams[O_INPUT]->GetInputMode() ||
+ m_streams[O_INPUT]->IsSuspended() ||
+ (!m_streams[O_DEBUG]->SameDev(m_streams[O_INTERACT]) &&
+ !m_streams[O_DEBUG]->SameDev(m_streams[O_INPUT])) ){
+ if( m_streams[O_DEBUG]->SameDev(m_streams[O_NORMAL]) ){
+ if( m_status_last && message && *message ) Debug_n("");
+ m_status_last = 0;
+ }
+ if( f_new_line && message && *message ){
+ char *format = (char *)0;
+ size_t buflen;
+ size_t need = strlen(message)+1 + 10*sizeof(unsigned long)/4;
+ if( need > sizeof(buffer) && (format = new char[need]) ) buflen = need;
+ else{ format = buffer; buflen = sizeof(buffer); }
+
+ snprintf(format, buflen, "%lu %s", (unsigned long)now, message);
+
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output_n(format, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ if( format && format != buffer ) delete []format;
+ }else{
+ va_start(ap, message);
+ if( m_streams[O_DEBUG]->Output_n(message, ap) )
+ SyncNewlines(O_DEBUG);
+ va_end(ap);
+ }
+
+ if( message && *message ) f_new_line = 0;
+ else f_new_line = 1;
+ }
+}
+
+
+void Console::Interact(const char *message, ...)
+{
+ va_list ap;
+
+ va_start(ap, message);
+ if( m_streams[O_INTERACT]->Output(message, ap) )
+ SyncNewlines(O_INTERACT);
+ va_end(ap);
+}
+
+
+/* Print interactive message without a terminating newline
+ With a null message, start/insure a new line
+*/
+void Console::Interact_n(const char *message, ...)
+{
+ va_list ap;
+
+ if( m_streams[O_INTERACT]->SameDev(m_streams[O_NORMAL]) ){
+ if( m_status_last && message && *message ) Interact_n("");
+ m_status_last = 0;
+ }
+ va_start(ap, message);
+ if( m_streams[O_INTERACT]->Output_n(message, ap) )
+ SyncNewlines(O_INTERACT);
+ va_end(ap);
+}
+
+
+/* Update (replace) the current interactive line (no terminating newline)
+*/
+void Console::InteractU(const char *message, ...)
+{
+ va_list ap;
+
+ if( m_streams[O_INTERACT]->SameDev(m_streams[O_NORMAL]) ){
+ if( m_status_last ) Interact_n("");
+ m_status_last = 0;
+ }
+ va_start(ap, message);
+ if( m_streams[O_INTERACT]->Update(message, ap) )
+ SyncNewlines(O_INTERACT);
+ va_end(ap);
+}
+
+
+// Avoid using this during normal operation, as it blocks for input!
+char *Console::Input(const char *prompt, char *field, size_t length)
+{
+ char *retval;
+ Interact_n("");
+ Interact_n("%s", prompt);
+ m_streams[O_INPUT]->SetInputMode(K_LINES);
+ retval = m_streams[O_INPUT]->Input(field, length);
+ m_streams[O_INPUT]->SetInputMode(K_CHARS);
+ return retval;
+}
+
+
+void Console::SyncNewlines(int master)
+{
+ for( int i=0; i < O_NCHANNELS; i++ ){
+ if( i != master && m_streams[i]->SameDev(m_streams[master]) )
+ m_streams[i]->SyncNewline(m_streams[master]);
+ }
+}
+
+
+void Console::cpu()
+{
+ if(arg_verbose)
+ Debug( "%.2f CPU seconds used; %lu seconds elapsed (%.2f%% usage)",
+ clock() / (double)CLOCKS_PER_SEC,
+ (unsigned long)(time((time_t *)0) - BTCONTENT.GetStartTime()),
+ clock() / (double)CLOCKS_PER_SEC /
+ (time((time_t *)0) - BTCONTENT.GetStartTime()) * 100 );
+}
+
+
+RETSIGTYPE Console::Signal(int sig_no)
+{
+ switch( sig_no ){
+ case SIGTTOU:
+ for( int i=0; i < O_NCHANNELS; i++ )
+ if( m_streams[i]->IsTTY() ) m_streams[i]->Suspend();
+ m_conmode = m_streams[O_INPUT]->GetInputMode();
+ break;
+ case SIGTTIN:
+ if( m_streams[O_INPUT]->IsTTY() ) m_streams[O_INPUT]->Suspend();
+ m_conmode = m_streams[O_INPUT]->GetInputMode();
+ break;
+ case SIGCONT:
+ for( int i=0; i <= O_NCHANNELS; i++ )
+ if( m_streams[i]->IsTTY() ) m_streams[i]->Resume();
+ m_streams[O_INPUT]->SetInputMode(m_conmode);
+ // restore my handler
+ signal(SIGTSTP, signals);
+ break;
+ case SIGTSTP:
+ m_conmode = m_streams[O_INPUT]->GetInputMode();
+ m_streams[O_INPUT]->RestoreMode();
+ // let the system default action proceed
+ signal(sig_no, SIG_DFL);
+ raise(sig_no);
+ break;
+ default:
+ break;
+ }
+}
+
+
+void Console::Daemonize()
+{
+#ifdef HAVE_WORKING_FORK
+ size_t orig_cache_size = 0;
+ pid_t r;
+ int nullfd = -1;
+
+ if( cfg_cache_size && BTCONTENT.CacheUsed() ){
+ orig_cache_size = cfg_cache_size;
+ cfg_cache_size /= 2;
+ BTCONTENT.CacheConfigure();
+ }
+
+ if( (r = fork()) < 0 ){
+ Warning(2, "warn, fork to background failed: %s", strerror(errno));
+ arg_daemon = 0;
+ goto restorecache;
+ }else if(r) exit(EXIT_SUCCESS);
+ if( !arg_daemon ) arg_daemon = 1;
+
+ for( int i=0; i <= O_NCHANNELS; i++ ){
+ if( m_streams[i]->IsTTY() && ChangeChannel(i, "off", 0) < 0 )
+ m_streams[i]->Suspend();
+ }
+ nullfd = OpenNull(nullfd, &m_stdin, 0);
+ nullfd = OpenNull(nullfd, &m_stdout, 1);
+ nullfd = OpenNull(nullfd, &m_stderr, 2);
+
+ if( setsid() < 0 ){
+ Warning(2,
+ "warn, failed to create new session (continuing in background): %s",
+ strerror(errno));
+ goto restorecache;
+ }
+
+ if( (r = fork()) < 0 ){
+ Warning(2,
+ "warn, final fork failed (continuing in background): %s",
+ strerror(errno));
+ goto restorecache;
+ }else if(r) exit(EXIT_SUCCESS);
+ else if(arg_verbose) Debug("Running in daemon (background) mode.");
+
+ restorecache:
+ if( orig_cache_size ){
+ cfg_cache_size = orig_cache_size;
+ BTCONTENT.CacheConfigure();
+ }
+#endif
+}
+
+
+int Console::OpenNull(int nullfd, ConStream *stream, int sfd)
+{
+ if( stream->IsTTY() || arg_daemon == 1 ){
+ int mfd = stream->Fileno();
+ if( mfd < 0 ) mfd = sfd;
+ stream->Close();
+ if( nullfd < 0 ) nullfd = open("/dev/null", O_RDWR);
+ if( nullfd >= 0 && nullfd != mfd ) dup2(nullfd, mfd);
+ }
+ return nullfd;
+}
+
diff --git a/console.h b/console.h
new file mode 100644
index 0000000..4e85ab3
--- a/dev/null
+++ b/console.h
@@ -0,0 +1,142 @@
+#include "def.h"
+#include <sys/types.h> // fd_set
+#include <stdarg.h>
+#include <stdio.h>
+
+#if defined(USE_TERMIOS)
+#include <termios.h>
+#elif defined(USE_TERMIO)
+#include <termio.h>
+#elif defined(USE_SGTTY)
+#include <sgtty.h>
+#endif
+
+#include "rate.h"
+
+// Number of status line formats
+#define STATUSLINES 2
+
+// Output channel labels
+#define O_NCHANNELS 4 // number of output channels
+#define O_NORMAL 0
+#define O_INTERACT 1
+#define O_WARNING 2
+#define O_DEBUG 3
+#define O_INPUT 4 // not an output! do not include in above count.
+
+
+class ConStream
+{
+ private:
+ FILE *m_stream;
+ char *m_name;
+ unsigned char m_newline:1;
+ unsigned char m_suspend:1;
+ unsigned char m_inputmode:1;
+ unsigned char m_filemode:1;
+ unsigned char m_restore:1;
+ unsigned char m_reserved:3;
+
+#if defined(USE_TERMIOS)
+ struct termios m_original;
+#elif defined(USE_TERMIO)
+ struct termio m_original;
+#elif defined(USE_SGTTY)
+ struct sgttyb m_original;
+#endif
+
+ void _newline();
+ int _convprintf(const char *format, va_list ap);
+ void Error(int sev, const char *message, ...);
+
+ public:
+ ConStream();
+ ~ConStream();
+
+ void Close();
+ void Associate(FILE *stream, const char *name, int mode);
+ char *GetName() const { return m_name; }
+ int GetMode() const { return m_filemode ? 1 : 0; }
+ int Fileno() const { return m_stream ? fileno(m_stream) : -1; }
+ int GetNewline() const { return m_newline ? 1 : 0; }
+ void SyncNewline(ConStream *master) { m_newline = master->GetNewline(); }
+ void Suspend() { m_suspend = 1; }
+ void Resume() { m_suspend = 0; }
+ int IsSuspended() { return m_suspend ? 1 : 0; }
+
+ int SameDev(ConStream *master) const;
+ int GetInputMode() const { return m_inputmode; }
+ void SetInputMode(int keymode);
+ void PreserveMode();
+ void RestoreMode();
+ int IsTTY() const;
+
+ int Output(const char *message, va_list ap);
+ int Output_n(const char *message, va_list ap);
+ int Update(const char *message, va_list ap);
+ char *Input(char *field, size_t length);
+ int CharIn();
+
+ int Eof() const { return feof(m_stream); }
+};
+
+
+class Console
+{
+ private:
+ unsigned char m_live_idx:2;
+ unsigned char m_conmode:1;
+ unsigned char m_skip_status:1;
+ unsigned char m_status_last:1;
+ unsigned char m_reserved:3;
+
+ int m_status_format;
+ int m_oldfd;
+ int m_status_len;
+
+ typedef void (Console::*statuslinefn)(char buffer[], size_t length);
+ statuslinefn m_statusline[STATUSLINES];
+
+ Rate m_pre_dlrate, m_pre_ulrate;
+
+ ConStream m_stdout, m_stderr, m_stdin, m_off;
+ ConStream *m_streams[O_NCHANNELS+1];
+
+ int OpenNull(int nullfd, ConStream *stream, int sfd);
+ void SyncNewlines(int master);
+ int OperatorMenu(const char *param);
+ void ShowFiles();
+ void StatusLine0(char buffer[], size_t length);
+ void StatusLine1(char buffer[], size_t length);
+
+ public:
+ Console();
+ ~Console();
+
+ int IntervalCheck(fd_set *rfdp, fd_set *wfdp);
+ void User(fd_set *rfdp, fd_set *wfdp, int *nready,
+ fd_set *rfdnextp, fd_set *wfdnextp);
+ void Status(int immediate);
+
+ void Print(const char *message, ...);
+ void Print_n(const char *message, ...);
+ void Update(const char *message, ...);
+ void Warning(int sev, const char *message, ...);
+ void Debug(const char *message, ...);
+ void Debug_n(const char *message, ...);
+ void Interact(const char *message, ...);
+ void Interact_n(const char *message, ...);
+ void InteractU(const char *message, ...);
+ char *Input(const char *prompt, char *field, size_t length);
+
+ char *GetChannel(int channel) const { return m_streams[channel]->GetName(); }
+ int ChangeChannel(int channel, const char *param, int notify = 1);
+
+ void cpu();
+
+ RETSIGTYPE Signal(int sig_no);
+ void Daemonize();
+};
+
+extern Console CONSOLE;
+
diff --git a/ctcs.cpp b/ctcs.cpp
new file mode 100644
index 0000000..d7dced0
--- a/dev/null
+++ b/ctcs.cpp
@@ -0,0 +1,876 @@
+#include "ctcs.h" // def.h
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ctype.h>
+
+#include "btcontent.h"
+#include "setnonblock.h"
+#include "connect_nonb.h"
+#include "tracker.h"
+#include "peerlist.h"
+#include "peer.h"
+#include "btconfig.h"
+#include "bttime.h"
+#include "console.h"
+
+#ifndef HAVE_SNPRINTF
+#include "compat.h"
+#endif
+
+
+#define CTCS_PROTOCOL 3
+
+#define compset(a,member) ( (a.member==member)? 0 : ((a.member = member)||1) )
+
+Ctcs CTCS;
+
+
+Ctcs::Ctcs()
+{
+ memset(m_host,0,MAXHOSTNAMELEN);
+
+ m_sock = INVALID_SOCKET;
+ m_port = 2780;
+ m_status = T_FREE;
+ m_interval = 5;
+ m_protocol = CTCS_PROTOCOL;
+
+ m_last_timestamp = m_sent_ctstatus_time = m_statustime = (time_t) 0;
+ m_sent_ctstatus = 0;
+ m_sent_ctbw = 0;
+}
+
+
+Ctcs::~Ctcs()
+{
+ if( m_sock != INVALID_SOCKET) CLOSE_SOCKET(m_sock);
+}
+
+
+void Ctcs::Reset(time_t new_interval)
+{
+ int warn = 0;
+
+ if(new_interval) m_interval = new_interval;
+
+ if( INVALID_SOCKET != m_sock ){
+ if( T_READY==m_status ) warn = 1;
+ CLOSE_SOCKET(m_sock);
+ m_sock = INVALID_SOCKET;
+ }
+
+ in_buffer.Reset();
+ out_buffer.Reset();
+ m_last_timestamp = now;
+ m_sent_ctstatus = 0;
+ m_sent_ctbw = 0;
+ m_status = T_FREE;
+
+ if( warn ) CONSOLE.Warning(2, "Connection to CTCS closed");
+}
+
+
+// borrowed from tracker.cpp (with changes)
+int Ctcs:: _s2sin(char *h,int p,struct sockaddr_in *psin)
+{
+ psin->sin_family = AF_INET;
+ psin->sin_port = htons(p);
+ psin->sin_addr.s_addr = inet_addr(h);
+ if(psin->sin_addr.s_addr == INADDR_NONE){
+ struct hostent *ph = gethostbyname(h);
+ if( !ph || ph->h_addrtype != AF_INET){
+ memset(psin,0,sizeof(struct sockaddr_in));
+ return -1;
+ }
+ memcpy(&psin->sin_addr,ph->h_addr_list[0],sizeof(struct in_addr));
+ }
+ return ( psin->sin_addr.s_addr == INADDR_NONE ) ? -1 : 0;
+}
+
+
+int Ctcs::CheckMessage()
+{
+ ssize_t r;
+ size_t q;
+
+ r = in_buffer.FeedIn(m_sock);
+
+ // This differs from tracker.cpp since we maintain a persistent connection.
+ if( r == 0 ) return 0; // no data (should return an error)
+
+ q = in_buffer.Count();
+
+ if( !q ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ if( getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0 )
+ error = errno;
+ if( error != 0 ) CONSOLE.Warning(2,
+ "warn, received nothing from CTCS: %s", strerror(error));
+ Reset(5);
+ return -1;
+ }
+
+ char *s, *msgbuf;
+ while(in_buffer.Count() &&
+ (s=strpbrk(msgbuf=in_buffer.BasePointer(), "\r\n"))){
+ *s = '\0';
+ if(arg_verbose && s!=msgbuf) CONSOLE.Debug("CTCS: %s", msgbuf);
+ if( !strncmp("SETDLIMIT",msgbuf,9) ){
+ int arg = (int)strtod(msgbuf+10, NULL);
+ if( !BTCONTENT.IsFull() || arg < cfg_max_bandwidth_down ){
+ cfg_max_bandwidth_down = arg;
+ if(arg_verbose) CONSOLE.Debug("DLimit=%d", cfg_max_bandwidth_down);
+ }
+ }else if( !strncmp("SETULIMIT",msgbuf,9) ){
+ cfg_max_bandwidth_up = (int)(strtod(msgbuf+10, NULL));
+ if(arg_verbose) CONSOLE.Debug("ULimit=%d", cfg_max_bandwidth_up);
+ }else if( !strncmp("SENDPEERS",msgbuf,9) ){
+ Send_Peers();
+ }else if( !strncmp("SENDSTATUS",msgbuf,10) ){
+ Send_Status();
+ }else if( !strncmp("SENDCONF",msgbuf,8) ){
+ Send_Config();
+ }else if( !strncmp("CTCONFIG",msgbuf,8) ){
+ Set_Config(msgbuf);
+ }else if( !strncmp("SENDDETAIL",msgbuf,10) ){
+ Send_Detail();
+ }else if( !strncmp("CTQUIT",msgbuf,6) ){
+ CONSOLE.Print("CTCS sent Quit command");
+ Tracker.ClearRestart();
+ Tracker.SetStoped();
+ }else if( !strncmp("CTRESTART",msgbuf,9) ){
+ Tracker.RestartTracker();
+ }else if( !strncmp("CTUPDATE",msgbuf,8) ){
+ Tracker.Reset(15);
+ }else if( !strncmp("PROTOCOL",msgbuf,8) ){
+ int proto = atoi(msgbuf+9);
+ if( proto <= CTCS_PROTOCOL ) m_protocol = proto;
+ else m_protocol = CTCS_PROTOCOL;
+ }else if( s!=msgbuf ){
+ if(arg_verbose) CONSOLE.Debug("unknown CTCS message: %s", msgbuf);
+ }
+ in_buffer.PickUp(s-msgbuf + 1);
+ }
+ m_last_timestamp = now;
+ return 0;
+}
+
+
+int Ctcs::SendMessage(const char *message)
+{
+ int len, r=0;
+ char buf[CTCS_BUFSIZE];
+
+ if( m_status == T_READY ){
+ len = strlen(message);
+ strncpy(buf, message, len);
+ if( len+1 < CTCS_BUFSIZE ){
+ buf[len] = '\n';
+ buf[len+1] = '\0';
+ }else{
+ buf[CTCS_BUFSIZE-2] = '\n';
+ buf[CTCS_BUFSIZE-1] = '\0';
+ }
+ r = out_buffer.PutFlush(m_sock, buf, len+1);
+ if( r<0 ) Reset(5);
+ else m_last_timestamp = now;
+ }
+ return (r < 0) ? r : 0;
+}
+
+
+int Ctcs::Send_Auth()
+{
+ char message[CTCS_BUFSIZE];
+
+ if(!*m_pass) return 0;
+ snprintf(message, CTCS_BUFSIZE, "AUTH %s", m_pass);
+ return SendMessage(message);
+}
+
+
+int Ctcs::Send_Protocol()
+{
+ char message[CTCS_BUFSIZE];
+
+ snprintf(message, CTCS_BUFSIZE, "PROTOCOL %04d", CTCS_PROTOCOL);
+ return SendMessage(message);
+}
+
+
+int Ctcs::Send_Torrent(const unsigned char *peerid, char *torrent)
+{
+ char message[CTCS_BUFSIZE];
+ char txtid[PEER_ID_LEN*2+3];
+
+ TextPeerID(peerid, txtid);
+
+ snprintf(message, CTCS_BUFSIZE, "CTORRENT %s %ld %ld %s", txtid,
+ (long)(BTCONTENT.GetStartTime()), (long)now, torrent);
+ return SendMessage(message);
+}
+
+
+int Ctcs::Report_Status()
+{
+ int changebw;
+ size_t dlrate, ulrate, dlimit, ulimit;
+
+ if( T_READY != m_status ) return 0;
+
+ dlrate = Self.RateDL();
+ ulrate = Self.RateUL();
+ dlimit = cfg_max_bandwidth_down;
+ ulimit = cfg_max_bandwidth_up;
+
+ changebw = (
+ compset(m_ctstatus, dlrate) |
+ compset(m_ctstatus, ulrate) |
+ compset(m_ctstatus, dlimit) |
+ compset(m_ctstatus, ulimit) );
+
+ m_statustime = now;
+
+ if( !m_sent_ctstatus ||
+ (Tracker.GetStatus() && now > m_sent_ctstatus_time+30) )
+ return Send_Status();
+ else return (changebw || !m_sent_ctbw) ? Send_bw() : 0;
+}
+
+
+int Ctcs::Send_Status()
+{
+ char message[CTCS_BUFSIZE];
+ size_t seeders, leechers, nhave, ntotal, dlrate, ulrate, dlimit, ulimit,
+ cacheused;
+ uint64_t dltotal, ultotal;
+
+ if( T_READY != m_status ) return 0;
+
+ seeders = WORLD.GetSeedsCount();
+ leechers = WORLD.GetPeersCount() - seeders - WORLD.GetConnCount();
+ nhave = BTCONTENT.pBF->Count();
+ ntotal = BTCONTENT.GetNPieces();
+ dlrate = m_ctstatus.dlrate;
+ ulrate = m_ctstatus.ulrate;
+ dltotal = Self.TotalDL();
+ ultotal = Self.TotalUL();
+ dlimit = cfg_max_bandwidth_down;
+ ulimit = cfg_max_bandwidth_up;
+ cacheused = BTCONTENT.CacheUsed()/1024;
+
+ if( m_protocol == 1 )
+ snprintf( message, CTCS_BUFSIZE,
+ "CTSTATUS %d/%d %d/%d/%d %d,%d %llu,%llu %d,%d",
+ (int)seeders, (int)leechers,
+ (int)nhave, (int)ntotal, (int)(WORLD.Pieces_I_Can_Get()),
+ (int)dlrate, (int)ulrate,
+ (unsigned long long)dltotal, (unsigned long long)ultotal,
+ (int)dlimit, (int)ulimit );
+ else
+ snprintf( message, CTCS_BUFSIZE,
+ "CTSTATUS %d:%d/%d:%d/%d %d/%d/%d %d,%d %llu,%llu %d,%d %d",
+ (int)seeders,
+ (int)(Tracker.GetSeedsCount()) - (BTCONTENT.IsFull() ? 1 : 0),
+ (int)leechers,
+ (int)(Tracker.GetPeersCount()) - Tracker.GetSeedsCount() -
+ (!BTCONTENT.IsFull() ? 1 : 0),
+ (int)(WORLD.GetConnCount()),
+ (int)nhave, (int)ntotal, (int)(WORLD.Pieces_I_Can_Get()),
+ (int)dlrate, (int)ulrate,
+ (unsigned long long)dltotal, (unsigned long long)ultotal,
+ (int)dlimit, (int)ulimit,
+ (int)cacheused );
+ m_sent_ctstatus = m_sent_ctbw = 1;
+ m_sent_ctstatus_time = now;
+ return SendMessage(message);
+}
+
+
+int Ctcs::Send_bw()
+{
+ char message[CTCS_BUFSIZE];
+
+ snprintf(message, CTCS_BUFSIZE, "CTBW %d,%d %d,%d",
+ (int)(m_ctstatus.dlrate), (int)(m_ctstatus.ulrate),
+ (int)(m_ctstatus.dlimit), (int)(m_ctstatus.ulimit) );
+ m_sent_ctbw = 1;
+ return SendMessage(message);
+}
+
+
+int Ctcs::Send_Config()
+{
+ char message[CTCS_BUFSIZE];
+
+ if( m_protocol >= 3 ){
+ int r = 0;
+ char value[MAXPATHLEN], desc[MAXPATHLEN], maxlen[10];
+
+ if( (r=SendMessage("CTCONFIGSTART")) < 0 ) return r;
+ snprintf(maxlen, sizeof(maxlen), "%u", (unsigned int)MAXPATHLEN);
+
+ if( (r = SendMessage(ConfigMsg("verbose", "B", "0", arg_verbose?"1":"0",
+ "Verbose output [-v]", arg_verbose ? "Enabled" : "Disabled"))) < 0 )
+ return r;
+
+ double num = BTCONTENT.GetSeedTime() ?
+ (cfg_seed_hours - (now - BTCONTENT.GetSeedTime())/3600.0) :
+ cfg_seed_hours;
+ unsigned long tmp = (unsigned long)(num * 100);
+ int pre = (tmp % 10) ? 2 : (tmp % 100) ? 1 : 0;
+ snprintf(value, MAXPATHLEN, "%.*f", pre, num);
+ snprintf(desc, MAXPATHLEN, "~hours remaining (-e %lu)",
+ (unsigned long)cfg_seed_hours);
+ if( (r = SendMessage(ConfigMsg("seed_time", "F", "0", value,
+ "Seed time [-e]", desc))) < 0 )
+ return r;
+
+ snprintf(value, MAXPATHLEN, "%.2f", (double)cfg_seed_ratio);
+ if( (r = SendMessage(ConfigMsg("seed_ratio", "F", "0", value,
+ "Seed ratio [-E]", "Upload:Download"))) < 0 )
+ return r;
+
+ snprintf(value, MAXPATHLEN, "%d", (int)cfg_max_peers);
+ snprintf(desc, MAXPATHLEN, "Current peers: %d",
+ (int)(WORLD.GetPeersCount()));
+ if( (r = SendMessage(ConfigMsg("max_peers", "I", "20-1000", value,
+ "Max peers [-M]", desc))) < 0 )
+ return r;
+
+ snprintf(value, MAXPATHLEN, "%d", (int)cfg_min_peers);
+ snprintf(desc, MAXPATHLEN, "Current peers: %d",
+ (int)(WORLD.GetPeersCount()));
+ if( (r = SendMessage(ConfigMsg("min_peers", "I", "1-1000", value,
+ "Min peers [-m]", desc))) < 0 )
+ return r;
+
+ if( !BTCONTENT.IsFull() &&
+ (r = SendMessage(ConfigMsg("file_list", "S", maxlen,
+ arg_file_to_download ? arg_file_to_download : "",
+ "Download files [-n]", ""))) < 0 )
+ return r;
+
+ snprintf(value, MAXPATHLEN, "%d", (int)cfg_cache_size);
+ snprintf(desc, MAXPATHLEN, "MB; %dKB now in use",
+ (int)(BTCONTENT.CacheUsed()/1024));
+ if( (r = SendMessage(ConfigMsg("cache", "I", "0", value,
+ "Cache size [-C]", desc))) < 0 )
+ return r;
+
+ if( (r = SendMessage(ConfigMsg("pause", "B", "0",
+ WORLD.IsPaused()?"1":"0",
+ "Pause torrent", "Stop upload/download"))) < 0 )
+ return r;
+
+ if( !BTCONTENT.IsFull() &&
+ (r = SendMessage(ConfigMsg("user_exit", "S", maxlen,
+ arg_completion_exit ? arg_completion_exit : "",
+ "Completion command [-X]", ""))) < 0 )
+ return r;
+
+ if( (r = SendMessage(ConfigMsg("out_normal", "S", maxlen,
+ CONSOLE.GetChannel(O_NORMAL), "Normal/status output", ""))) < 0 )
+ return r;
+ if( (r = SendMessage(ConfigMsg("out_interact", "S", maxlen,
+ CONSOLE.GetChannel(O_INTERACT), "Interactive output", ""))) < 0 )
+ return r;
+ if( (r = SendMessage(ConfigMsg("out_error", "S", maxlen,
+ CONSOLE.GetChannel(O_WARNING), "Error/warning output", ""))) < 0 )
+ return r;
+ if( (r = SendMessage(ConfigMsg("out_debug", "S", maxlen,
+ CONSOLE.GetChannel(O_DEBUG), "Debug/verbose output", ""))) < 0 )
+ return r;
+ if( (r = SendMessage(ConfigMsg("input", "S", maxlen,
+ CONSOLE.GetChannel(O_INPUT), "Console input", ""))) < 0 )
+ return r;
+
+ if( (r = SendMessage(ConfigMsg("ctcs_server", "S", maxlen,
+ arg_ctcs, "CTCS server", ""))) < 0 )
+ return r;
+
+ sprintf(message, "CTCONFIGDONE");
+ }
+ else if( m_protocol == 2 )
+ snprintf(message, CTCS_BUFSIZE, "CTCONFIG %d %d %f %d %d %d %d %d",
+ (int)arg_verbose, (int)cfg_seed_hours, cfg_seed_ratio,
+ (int)cfg_max_peers, (int)cfg_min_peers,
+ BTCONTENT.GetFilter() ? atoi(BTCONTENT.GetFilterName()) : 0,
+ (int)cfg_cache_size, WORLD.IsPaused());
+ else // m_protocol == 1
+ snprintf(message, CTCS_BUFSIZE, "CTCONFIG %d %d %f %d %d %d %d %d %d",
+ (int)arg_verbose, (int)cfg_seed_hours, cfg_seed_ratio,
+ (int)cfg_max_peers, (int)cfg_min_peers,
+ BTCONTENT.GetFilter() ? atoi(BTCONTENT.GetFilterName()) : 0,
+ 0, WORLD.IsPaused(), 0);
+
+ return SendMessage(message);
+}
+
+char *Ctcs::ConfigMsg(const char *name, const char *type, const char *range,
+ const char *value, const char *short_desc, const char *long_desc)
+{
+ static char *message = (char *)0;
+
+ if( !message ){
+ message = new char[CTCS_BUFSIZE];
+ if( !message ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for CTCS message");
+ return (char *)0;
+ }
+ }
+ snprintf(message, CTCS_BUFSIZE, "CTCONFIG %s %s %s %d:%s %d:%s %d:%s",
+ name, type, range, (int)strlen(value), value,
+ (int)strlen(short_desc), short_desc, (int)strlen(long_desc), long_desc);
+
+ return message;
+}
+
+int Ctcs::Set_Config(const char *origmsg)
+{
+ char *msgbuf = new char[strlen(origmsg)+1];
+
+ if( !msgbuf ){
+ CONSOLE.Warning(1, "error, failed to allocate memory for config");
+ return -1;
+ }
+ strcpy(msgbuf, origmsg);
+
+ if( m_protocol >= 3 ){
+ char *name, *valstr;
+ if( !(name = strtok(strchr(msgbuf, ' '), " ")) ||
+ strlen(name) >= strlen(origmsg) - (name - msgbuf) )
+ goto err;
+ valstr = name + strlen(name);
+ for( ++valstr; *valstr==' '; valstr++ );
+
+ if( 0==strcmp(name, "verbose") ){
+ int arg = atoi(valstr);
+ if( arg < 0 ) goto err;
+ if( arg_verbose && !arg ) CONSOLE.Debug("Verbose output off");
+ arg_verbose = arg;
+ }else if( 0==strcmp(name, "seed_time") ){
+ double value = strtod(valstr, NULL);
+ if( value < 0 ) goto err;
+ time_t arg = (time_t)value + ((value - (int)value) ? 1 : 0);
+ arg += BTCONTENT.GetSeedTime() ?
+ ((now - BTCONTENT.GetSeedTime()) / 3600) : 0;
+ if( arg > 0 || 0==BTCONTENT.GetSeedTime() ||
+ cfg_seed_ratio > (double) Self.TotalUL() /
+ (Self.TotalDL() ?
+ Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) )
+ cfg_seed_hours = arg;
+ }else if( 0==strcmp(name, "seed_ratio") ){
+ double arg = atof(valstr);
+ if( arg < 0 ) goto err;
+ if( 0==BTCONTENT.GetSeedTime() ||
+ cfg_seed_hours > (now - BTCONTENT.GetSeedTime()) / 3600 ||
+ arg > (double) Self.TotalUL() /
+ (Self.TotalDL() ?
+ Self.TotalDL() : BTCONTENT.GetTotalFilesLength()) )
+ cfg_seed_ratio = arg;
+ }else if( 0==strcmp(name, "max_peers") ){
+ int arg = atoi(valstr);
+ if( arg > 1000 || arg < 20 ) goto err;
+ cfg_max_peers = arg;
+ }else if( 0==strcmp(name, "min_peers") ){
+ int arg = atoi(valstr);
+ if( arg > 1000 || arg < 1 ) goto err;
+ cfg_min_peers = arg;
+ }else if( 0==strcmp(name, "file_list") ){
+ if( !BTCONTENT.IsFull() ){
+ if( arg_file_to_download ) delete []arg_file_to_download;
+ if( 0==strlen(valstr) ) arg_file_to_download = (char *)0;
+ else{
+ arg_file_to_download = new char[strlen(valstr) + 1];
+ if( !arg_file_to_download )
+ CONSOLE.Warning(1, "error, failed to allocate memory for option");
+ else strcpy(arg_file_to_download, valstr);
+ }
+ BTCONTENT.SetFilter();
+ }
+ }else if( 0==strcmp(name, "cache") ){
+ int arg = atoi(valstr);
+ if( arg < 0 ) goto err;
+ cfg_cache_size = arg;
+ BTCONTENT.CacheConfigure();
+ }else if( 0==strcmp(name, "pause") ){
+ int arg = atoi(valstr);
+ if( arg < 0 ) goto err;
+ if( arg ){
+ if( !WORLD.IsPaused() ) WORLD.Pause();
+ }else if( WORLD.IsPaused() ) WORLD.Resume();
+ }else if( 0==strcmp(name, "user_exit") ){
+ if( !BTCONTENT.IsFull() ){
+ if( arg_completion_exit ) delete []arg_completion_exit;
+ arg_completion_exit = new char[strlen(valstr) + 1];
+ if( !arg_completion_exit )
+ CONSOLE.Warning(1, "error, failed to allocate memory for option");
+ else strcpy(arg_completion_exit, valstr);
+ }
+ }else if( 0==strcmp(name, "out_normal") ){
+ CONSOLE.ChangeChannel(O_NORMAL, valstr);
+ }else if( 0==strcmp(name, "out_interact") ){
+ CONSOLE.ChangeChannel(O_INTERACT, valstr);
+ }else if( 0==strcmp(name, "out_error") ){
+ CONSOLE.ChangeChannel(O_WARNING, valstr);
+ }else if( 0==strcmp(name, "out_debug") ){
+ CONSOLE.ChangeChannel(O_DEBUG, valstr);
+ }else if( 0==strcmp(name, "input") ){
+ CONSOLE.ChangeChannel(O_INPUT, valstr);
+ }else if( 0==strcmp(name, "ctcs_server") ){
+ if( !strchr(valstr, ':') || *valstr == ':' ||
+ atoi(strchr(valstr, ':') + 1) <= 0 ) goto err;
+ char *arg = new char[strlen(valstr) + 1];
+ if( !arg )
+ CONSOLE.Warning(1, "error, failed to allocate memory for option");
+ else{
+ strcpy(arg, valstr);
+ delete []arg_ctcs;
+ arg_ctcs = arg;
+ CTCS.Initial();
+ CTCS.Reset(1);
+ }
+ }else CONSOLE.Warning(2, "Unknown config option %s from CTCS", name);
+ }else{ // m_protocol <= 2
+ if(msgbuf[9] != '.'){
+ int arg = atoi(msgbuf+9);
+ if( arg_verbose && !arg ) CONSOLE.Debug("Verbose output off");
+ arg_verbose = arg;
+ }
+ if(msgbuf[11] != '.') cfg_seed_hours = atoi(msgbuf+11);
+ if( !(msgbuf = strchr(msgbuf+11, ' ')) ) goto err;
+ if(*++msgbuf != '.') cfg_seed_ratio = atof(msgbuf);
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ if(*++msgbuf != '.') cfg_max_peers = atoi(msgbuf);
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ if(*++msgbuf != '.') cfg_min_peers = atoi(msgbuf);
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ if(*++msgbuf != '.'){
+ char *p = strchr(msgbuf, ' ');
+ if( !p ) goto err;
+ if( arg_file_to_download ) delete []arg_file_to_download;
+ arg_file_to_download = new char[p - msgbuf + 2 + 1];
+ if( !arg_file_to_download )
+ CONSOLE.Warning(1, "error, failed to allocate memory for option");
+ else{
+ strncpy(arg_file_to_download, msgbuf, p - msgbuf);
+ arg_file_to_download[p - msgbuf] = '\0';
+ strcat(arg_file_to_download, ",*"); // mock old behavior
+ }
+ BTCONTENT.SetFilter();
+ }
+ if( m_protocol >= 2 ){
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ if(*++msgbuf != '.'){
+ cfg_cache_size = atoi(msgbuf);
+ BTCONTENT.CacheConfigure();
+ }
+ }
+ if( m_protocol == 1 ){
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ ++msgbuf;
+ // old cfg_exit_zero_peers option
+ }
+ if( !(msgbuf = strchr(msgbuf, ' ')) ) goto err;
+ if(*++msgbuf != '.'){
+ if(atoi(msgbuf)){
+ if( !WORLD.IsPaused() ) WORLD.Pause();
+ }else if( WORLD.IsPaused() ) WORLD.Resume();
+ }
+ }
+
+ delete []msgbuf;
+ return 0;
+
+ err:
+ CONSOLE.Warning(2, "Malformed or invalid input from CTCS: %s", origmsg);
+ delete []msgbuf;
+ return -1;
+}
+
+
+int Ctcs::Send_Detail()
+{
+ char message[CTCS_BUFSIZE];
+ int r=0, priority, current=0;
+ size_t n=0;
+ BTFILE *file=0;
+ BitField tmpBitField, fileFilter, availbf, tmpavail, allFilter, tmpFilter,
+ *pfilter;
+
+ snprintf( message, CTCS_BUFSIZE, "CTDETAIL %lld %d %ld %ld",
+ BTCONTENT.GetTotalFilesLength(),
+ (int)(BTCONTENT.GetPieceLength()), (long)now,
+ (long)(BTCONTENT.GetSeedTime()) );
+ r = SendMessage(message);
+
+ if(r==0) r = SendMessage((m_protocol >= 3) ? "CTFILESTART" : "CTFILES");
+
+ if( m_protocol >= 3 ){ // determine current download priority
+ pfilter = (BitField *)0;
+ while( pfilter != BTCONTENT.GetFilter() ){
+ current++;
+ pfilter = BTCONTENT.GetNextFilter(pfilter);
+ }
+ }
+
+ WORLD.Pieces_I_Can_Get(&availbf);
+
+ while( r==0 && ++n <= BTCONTENT.GetNFiles() ){
+ tmpBitField = *BTCONTENT.pBF;
+ BTCONTENT.SetTmpFilter(n, &fileFilter);
+ tmpBitField.Except(fileFilter); // the pieces of this file that I have
+ tmpavail = availbf;
+ tmpavail.Except(fileFilter); // the available pieces of this file
+
+ if( m_protocol >= 3 ){
+ priority = 0;
+ if( BTCONTENT.GetFilter() ){
+ fileFilter.Invert();
+ allFilter.SetAll();
+ pfilter = (BitField *)0;
+ while( pfilter = BTCONTENT.GetNextFilter(pfilter) ){
+ priority++;
+ allFilter.And(*pfilter); // cumulation of filters
+ tmpFilter = allFilter;
+ tmpFilter.Invert(); // what's included by the filters...
+ tmpFilter.And(fileFilter); // ...that's also in this file
+ if( tmpFilter.Count() >= fileFilter.Count() ) break;
+ }
+ if( !pfilter ) priority = 0;
+ }
+ snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %d %d %d %llu %s",
+ (int)n, priority, current, (int)(BTCONTENT.GetFilePieces(n)),
+ (int)(tmpBitField.Count()), (int)(tmpavail.Count()),
+ (unsigned long long)(BTCONTENT.GetFileSize(n)),
+ BTCONTENT.GetFileName(n) );
+ }
+ else if( m_protocol == 2 )
+ snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %d %llu %s",
+ (int)n, (int)(BTCONTENT.GetFilePieces(n)),
+ (int)(tmpBitField.Count()), (int)(tmpavail.Count()),
+ (unsigned long long)(BTCONTENT.GetFileSize(n)),
+ BTCONTENT.GetFileName(n) );
+ else // m_protocol == 1
+ snprintf( message, CTCS_BUFSIZE, "CTFILE %d %d %d %llu %s",
+ (int)n, (int)(BTCONTENT.GetFilePieces(n)),
+ (int)(tmpBitField.Count()),
+ (unsigned long long)(BTCONTENT.GetFileSize(n)),
+ BTCONTENT.GetFileName(n) );
+
+ r = SendMessage(message);
+ }
+ if(r==0) r = SendMessage((m_protocol >= 3) ? "CTFILESDONE" : "CTFDONE");
+ return r;
+}
+
+
+int Ctcs::Send_Peers()
+{
+ btPeer *peer=0;
+ char message[CTCS_BUFSIZE];
+ char txtid[PEER_ID_LEN*2+3];
+ struct sockaddr_in psin;
+ int r=0;
+
+ r=SendMessage((m_protocol >= 3) ? "CTPEERSTART" : "CTPEERS");
+ while( r==0 && (peer = WORLD.GetNextPeer(peer)) ){
+ TextPeerID(peer->id, txtid);
+ peer->GetAddress(&psin);
+
+ snprintf(message, CTCS_BUFSIZE, "CTPEER %s %s %c%c%c%c %d %d %llu %llu %d",
+ txtid, inet_ntoa(psin.sin_addr),
+ peer->Is_Remote_UnChoked() ? 'U' : 'C',
+ peer->Is_Local_Interested() ? 'i' : 'n',
+ peer->Is_Local_UnChoked() ? 'U' : 'C',
+ peer->Is_Remote_Interested() ? 'i' : 'n',
+ (int)(peer->RateDL()), (int)(peer->RateUL()),
+ (unsigned long long)(peer->TotalDL()),
+ (unsigned long long)(peer->TotalUL()),
+ (int)(peer->bitfield.Count()) );
+ r = SendMessage(message);
+ }
+ if(r==0) r = SendMessage((m_protocol >= 3) ? "CTPEERSDONE" : "CTPDONE");
+ return r;
+}
+
+
+int Ctcs::Send_Info(int sev, const char *info)
+{
+ char message[CTCS_BUFSIZE];
+
+ snprintf(message, CTCS_BUFSIZE, "CTINFO %d %s", sev, info);
+ return SendMessage(message);
+}
+
+
+int Ctcs::Initial()
+{
+ char *s;
+
+ strncpy(m_host, arg_ctcs, MAXHOSTNAMELEN-1);
+ m_host[MAXHOSTNAMELEN-1] = '\0';
+ if( s = strchr(m_host, ':') ) *s='\0';
+ m_port = atoi(s=(strchr(arg_ctcs, ':')+1));
+ if(strchr(s, ':')){
+ CONSOLE.Input("Enter CTCS password: ", m_pass, CTCS_PASS_SIZE);
+ } else *m_pass = '\0';
+
+ return 0;
+}
+
+
+int Ctcs::Connect()
+{
+ ssize_t r;
+ m_last_timestamp = now;
+
+ if(_s2sin(m_host,m_port,&m_sin) < 0) {
+ CONSOLE.Warning(2, "warn, get CTCS ip address failed.");
+ return -1;
+ }
+
+ m_sock = socket(AF_INET,SOCK_STREAM,0);
+ if( INVALID_SOCKET == m_sock ) return -1;
+
+ if( setfd_nonblock(m_sock) < 0 ){ CLOSE_SOCKET(m_sock); return -1; }
+
+ r = connect_nonb(m_sock,(struct sockaddr*)&m_sin);
+
+ if( r == -1 ){ CLOSE_SOCKET(m_sock); return -1; }
+ else if( r == -2 ) m_status = T_CONNECTING;
+ else{
+ m_status = T_READY;
+ if(arg_verbose) CONSOLE.Debug("Connected to CTCS");
+ if( Send_Protocol() != 0 && errno != EINPROGRESS ){
+ CONSOLE.Warning(2, "warn, send protocol to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ if( Send_Auth() != 0 && errno != EINPROGRESS ) {
+ CONSOLE.Warning(2, "warn, send password to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ if( Send_Torrent(BTCONTENT.GetPeerId(), arg_metainfo_file) < 0 &&
+ errno != EINPROGRESS ){
+ CONSOLE.Warning(2, "warn, send torrent to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+int Ctcs::IntervalCheck(fd_set *rfdp, fd_set *wfdp)
+{
+ if( T_FREE == m_status ){
+ if( INVALID_SOCKET != m_sock ){
+ FD_CLR(m_sock, rfdp);
+ FD_CLR(m_sock, wfdp);
+ }
+ if( now - m_last_timestamp >= m_interval ){
+ if(Connect() < 0){ Reset(15); return -1; }
+
+ FD_SET(m_sock, rfdp);
+ if( m_status == T_CONNECTING ) FD_SET(m_sock, wfdp);
+ }else if( now < m_last_timestamp ) m_last_timestamp = now;
+ }else if( T_CONNECTING == m_status ){
+ FD_SET(m_sock, rfdp);
+ FD_SET(m_sock, wfdp);
+ }else if( INVALID_SOCKET != m_sock ){
+ if( now > m_statustime ) Report_Status();
+ FD_SET(m_sock, rfdp);
+ if( out_buffer.Count() ) FD_SET(m_sock, wfdp);
+ }
+ return m_sock;
+}
+
+
+int Ctcs::SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds,
+ fd_set *rfdnextp, fd_set *wfdnextp)
+{
+ if( T_FREE == m_status ) return 0;
+
+ if( T_CONNECTING == m_status && FD_ISSET(m_sock,wfdp) ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ (*nfds)--;
+ FD_CLR(m_sock, wfdnextp);
+ if( FD_ISSET(m_sock, rfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock, rfdnextp);
+ }
+ if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0)
+ error = errno;
+ if( error != 0 ){
+ if( ECONNREFUSED != error )
+ CONSOLE.Warning(2, "warn, connect to CTCS failed: %s",
+ strerror(error));
+ Reset(15);
+ return -1;
+ }else{
+ m_status = T_READY;
+ if(arg_verbose) CONSOLE.Debug("Connected to CTCS");
+ if( Send_Protocol() != 0 && errno != EINPROGRESS ){
+ CONSOLE.Warning(2, "warn, send protocol to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ if( Send_Auth() != 0 && errno != EINPROGRESS ) {
+ CONSOLE.Warning(2, "warn, send password to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ if( Send_Torrent(BTCONTENT.GetPeerId(), arg_metainfo_file) < 0 &&
+ errno != EINPROGRESS ){
+ CONSOLE.Warning(2, "warn, send torrent to CTCS failed: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+ }else if( T_CONNECTING == m_status && FD_ISSET(m_sock,rfdp) ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ (*nfds)--;
+ FD_CLR(m_sock, rfdnextp);
+ if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0)
+ error = errno;
+ CONSOLE.Warning(2, "warn, connect to CTCS failed: %s", strerror(error));
+ Reset(15);
+ return -1;
+ }else if( INVALID_SOCKET != m_sock ){
+ if( FD_ISSET(m_sock, rfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock,rfdnextp);
+ SOCKET tmp_sock = m_sock;
+ int r = CheckMessage();
+ if( INVALID_SOCKET == m_sock ){
+ if( FD_ISSET(tmp_sock, wfdp) ){
+ (*nfds)--;
+ FD_CLR(tmp_sock,wfdnextp);
+ }
+ return r;
+ }
+ }
+ if( FD_ISSET(m_sock, wfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock,wfdnextp);
+ if( out_buffer.Count() && out_buffer.FlushOut(m_sock) < 0 ){
+ Reset(5);
+ return -1;
+ }
+ }
+ }else{ // failsafe
+ Reset(5);
+ return -1;
+ }
+ return 0;
+}
+
diff --git a/ctcs.h b/ctcs.h
new file mode 100644
index 0000000..7ca711b
--- a/dev/null
+++ b/ctcs.h
@@ -0,0 +1,95 @@
+#ifndef CTCS_H
+#define CTCS_H
+
+#include "./def.h"
+#include <sys/types.h>
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <unistd.h>
+#include <netdb.h> // Solaris defines MAXHOSTNAMELEN here.
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/param.h>
+#endif
+
+#include <inttypes.h>
+#include <time.h>
+
+#include "bufio.h"
+
+#define CTCS_BUFSIZE (200+MAXPATHLEN)
+#define CTCS_PASS_SIZE 21
+
+struct ctstatus {
+ size_t dlrate, ulrate, dlimit, ulimit;
+
+ ctstatus(){
+ dlrate=ulrate=dlimit=ulimit = 0;
+ }
+};
+
+class Ctcs
+{
+ private:
+ char m_host[MAXHOSTNAMELEN];
+ int m_port;
+ char m_pass[CTCS_PASS_SIZE];
+ int m_protocol;
+
+ struct sockaddr_in m_sin;
+
+ unsigned char m_status:2;
+
+ time_t m_interval;
+ time_t m_last_timestamp;
+ time_t m_sent_ctstatus_time;
+ time_t m_statustime;
+
+ SOCKET m_sock;
+ BufIo in_buffer;
+ BufIo out_buffer;
+ struct ctstatus m_ctstatus;
+ int m_sent_ctstatus;
+ int m_sent_ctbw;
+
+ int _s2sin(char *h,int p,struct sockaddr_in *psin);
+ int SendMessage(const char *buf);
+ char *ConfigMsg(const char *name, const char *type, const char *range,
+ const char *value, const char *short_desc, const char *long_desc);
+
+ public:
+ Ctcs();
+ ~Ctcs();
+
+ void Reset(time_t new_interval);
+ int Initial();
+ int Connect();
+ int CheckMessage();
+ int Send_Protocol();
+ int Send_Auth();
+ int Send_Torrent(const unsigned char *peerid, char *torrent);
+ int Report_Status();
+ int Send_Status();
+ int Send_bw();
+ int Send_Config();
+ int Set_Config(const char *msgbuf);
+ int Send_Detail();
+ int Send_Peers();
+ int Send_Info(int sev, const char *info);
+ int IntervalCheck(fd_set *rfdp, fd_set *wfdp);
+ int SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds,
+ fd_set *rfdnextp, fd_set *wfdnextp);
+
+ SOCKET GetSocket() { return m_sock; }
+ unsigned char GetStatus() { return m_status;}
+};
+
+extern Ctcs CTCS;
+
+#endif
+
diff --git a/def.h b/def.h
new file mode 100644
index 0000000..7073322
--- a/dev/null
+++ b/def.h
@@ -0,0 +1,43 @@
+#ifndef DEF_H
+#define DEF_H
+
+#include "./config.h"
+
+#ifdef WINDOWS //if Windows ********************
+typedef int ssize_t;
+typedef int socklen_t;
+
+#define PATH_SP '\\'
+#define MAXPATHLEN 1024
+#define MAXHOSTNAMELEN 256
+
+//#define mkdir(path,mode) _mkdir((path))
+
+#define snprintf _snprintf
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#define ioctl ioctlsocket
+
+#define RECV(fd,buf,len) recv((fd),(buf),(len),0)
+#define SEND(fd,buf,len) send((fd),(buf),(len),0)
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define CLOSE_SOCKET(sk) closesocket((sk))
+
+#else // if *Nix *****************************
+
+#define CLOSE_SOCKET(sk) close((sk))
+
+#ifndef SOCKET
+typedef int SOCKET;
+#endif
+
+#define INVALID_SOCKET -1
+
+#define PATH_SP '/'
+#define RECV(fd,buf,len) read((fd),(buf),(len))
+#define SEND(fd,buf,len) write((fd),(buf),(len))
+
+#endif
+
+#endif
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..6589965
--- a/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 <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+ "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. This file always lives in the current directory.
+ # Also, the AIX compiler puts `$object:' at the start of each line;
+ # $object doesn't have directory information.
+ stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ outname="$stripped.o"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+tru64)
+ # The Tru64 AIX compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+
+ tmpdepfile1="$object.d"
+ tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'`
+ if test "$libtool" = yes; then
+ "$@" -Wc,-MD
+ else
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile1"; then
+ tmpdepfile="$tmpdepfile1"
+ else
+ tmpdepfile="$tmpdepfile2"
+ fi
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a space and a tab in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ test -z "$dashmflag" && dashmflag=-M
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*) # this is libtool, let us make it quiet
+ for arg
+ do # cycle over the arguments
+ case "$arg" in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ # X makedepend
+ (
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in no)
+ set ""; shift
+ cleared=yes
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift;;
+ -*)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tail +3 "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/downloader.cpp b/downloader.cpp
new file mode 100644
index 0000000..84835ba
--- a/dev/null
+++ b/downloader.cpp
@@ -0,0 +1,138 @@
+#include "def.h"
+
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "peerlist.h"
+#include "tracker.h"
+#include "btcontent.h"
+#include "ctcs.h"
+#include "btconfig.h"
+#include "bttime.h"
+#include "console.h"
+
+#define MAX_SLEEP 1
+
+time_t now = time((time_t *)0);
+
+void Downloader()
+{
+ int nfds = 0, maxfd, r;
+ struct timeval timeout;
+ fd_set rfd, rfdnext;
+ fd_set wfd, wfdnext;
+ int stopped = 0, f_idleused = 0, f_poll = 0;
+ struct timespec nowspec;
+ double maxsleep;
+ time_t then, concheck = (time_t)0;
+
+ FD_ZERO(&rfdnext); FD_ZERO(&wfdnext);
+
+ do{
+ time(&now);
+ if( !stopped ){
+ if( !Tracker.IsQuitting() && BTCONTENT.SeedTimeout() )
+ Tracker.SetStoped();
+ if( Tracker.IsQuitting() && !Tracker.IsRestarting() ){
+ stopped = 1;
+ WORLD.Pause();
+ if( arg_ctcs ) CTCS.Send_Status();
+ }
+ }
+
+ maxfd = -1;
+ maxsleep = -1;
+ rfd = rfdnext;
+ wfd = wfdnext;
+
+ if( f_poll ){
+ FD_ZERO(&rfd); FD_ZERO(&wfd); // remove non-peers from sets
+ maxsleep = 0; // waited for bandwidth--poll now
+ }else{
+ WORLD.DontWaitBW();
+ if( WORLD.IsIdle() ){
+ f_idleused = 0;
+ if( BTCONTENT.CheckedPieces() < BTCONTENT.GetNPieces() &&
+ !BTCONTENT.NeedFlush() ){
+ if( BTCONTENT.CheckNextPiece() < 0 ){
+ CONSOLE.Warning(1, "Error while checking piece %d of %d",
+ (int)(BTCONTENT.CheckedPieces()), (int)(BTCONTENT.GetNPieces()));
+ Tracker.SetStoped();
+ maxsleep = 2;
+ }else maxsleep = 0;
+ f_idleused = 1;
+ time(&now);
+ }
+ r = Tracker.IntervalCheck(&rfd, &wfd);
+ if( r > maxfd ) maxfd = r;
+ if( arg_ctcs ){
+ r = CTCS.IntervalCheck(&rfd, &wfd);
+ if( r > maxfd ) maxfd = r;
+ }
+ if( !f_idleused || concheck <= now-2 || WORLD.IsIdle() ){
+ concheck = now;
+ r = CONSOLE.IntervalCheck(&rfd, &wfd);
+ if( r > maxfd ) maxfd = r;
+ }
+ }
+ }
+ r = WORLD.IntervalCheck(&rfd, &wfd);
+ if( r > maxfd ) maxfd = r;
+
+ if( !f_poll ){
+ time(&now);
+ while( BTCONTENT.NeedFlush() && WORLD.IsIdle() ){
+ BTCONTENT.FlushQueue();
+ maxsleep = 0;
+ time(&now);
+ }
+ }
+
+ rfdnext = rfd;
+ wfdnext = wfd;
+
+ if( maxsleep < 0 ){ //not yet set
+ maxsleep = WORLD.WaitBW(); // must do after intervalchecks!
+ if( maxsleep <= -100 ) maxsleep = 0;
+ else if( maxsleep <= 0 || maxsleep > MAX_SLEEP ) maxsleep = MAX_SLEEP;
+ }
+
+ timeout.tv_sec = (long)maxsleep;
+ timeout.tv_usec = (long)( (maxsleep-(long)maxsleep) * 1000000 );
+
+ WORLD.UnLate();
+ nfds = select(maxfd + 1,&rfd,&wfd,(fd_set*) 0,&timeout);
+ if( nfds < 0 ){
+ CONSOLE.Debug("Error from select: %s", strerror(errno));
+ FD_ZERO(&rfdnext); FD_ZERO(&wfdnext);
+ nfds = 0;
+ }
+
+ if( f_poll ) f_poll = 0;
+ else if( nfds > 0 ) WORLD.DontWaitBW();
+ else if( maxsleep > 0 && maxsleep < MAX_SLEEP ) f_poll = 1;
+
+ then = now;
+ time(&now);
+ if( now == then-1 ) now = then;
+
+ if( !f_poll && nfds > 0 ){
+ if(T_FREE != Tracker.GetStatus())
+ Tracker.SocketReady(&rfd,&wfd,&nfds,&rfdnext,&wfdnext);
+ if(nfds > 0 && T_FREE != CTCS.GetStatus())
+ CTCS.SocketReady(&rfd,&wfd,&nfds,&rfdnext,&wfdnext);
+ if(nfds > 0)
+ CONSOLE.User(&rfd,&wfd,&nfds,&rfdnext,&wfdnext);
+ }
+ if(nfds > 0)
+ WORLD.AnyPeerReady(&rfd,&wfd,&nfds,&rfdnext,&wfdnext);
+ } while(Tracker.GetStatus() != T_FINISHED || Tracker.IsRestarting());
+}
diff --git a/downloader.h b/downloader.h
new file mode 100644
index 0000000..214ea87
--- a/dev/null
+++ b/downloader.h
@@ -0,0 +1,6 @@
+#ifndef DOWNLOADER_H
+#define DOWNLOADER_H
+
+void Downloader();
+
+#endif
diff --git a/httpencode.cpp b/httpencode.cpp
new file mode 100644
index 0000000..d96de1f
--- a/dev/null
+++ b/httpencode.cpp
@@ -0,0 +1,156 @@
+#include "./def.h"
+#include <sys/types.h>
+
+#include "./httpencode.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "./config.h"
+
+#if !defined(HAVE_STRNSTR) || !defined(HAVE_STRNCASECMP)
+#include "compat.h"
+#endif
+
+static void url_encode_char(char *b,char c)
+{
+ char HEX_TABLE[] = "0123456789ABCDEF";
+ b[0] = '%';
+ b[1] = HEX_TABLE[(c >> 4) & 0x0F];
+ b[2] = HEX_TABLE[c & 0x0F];
+}
+
+char* Http_url_encode(char *s,const char *b,size_t n)
+{
+ size_t r,i;
+ for(r = 0,i = 0 ; i < n; i++){
+ if( !(b[i] & ~0x7f) && // quick ASCII test
+ ((b[i] >= 0x41 && b[i] <= 0x5a) || // A-Z [ASCII]
+ (b[i] >= 0x61 && b[i] <= 0x7a) || // a-z
+ (b[i] >= 0x30 && b[i] <= 0x39)) ){ // 0-9
+ s[r] = b[i];
+ r++;
+ }else{
+ url_encode_char(s + r, b[i]);
+ r += 3;
+ }
+ }
+ s[r] = '\0';
+ return s;
+}
+
+int Http_url_analyse(const char *url,char *host,int *port,char *path)
+{
+ const char *p;
+ int r;
+ *port = 80; /* default port 80 */
+ p = strstr(url,"://");
+ if( !p )
+ p = url;
+ else
+ p += 3;
+
+ /* host */
+ for(; *p && (isalnum(*p) || *p == '.' || *p == '-'); p++, host++)
+ *host = *p;
+ *host = '\0';
+
+ if( *p == ':' ){
+ /* port */
+ p++;
+ for( r = 0; p[r] >= '0' && p[r] <= '9' && r < 6; r++) ;
+
+ if( !r ) return -1;
+ *port = atoi(p);
+ if(*port > 65536) return -1;
+ p += r;
+ }
+
+ /* path */
+ if( *p != '/' ) return -1;
+ for( ; *p; p++,path++) *path = *p;
+ *path = '\0';
+ return 0;
+}
+
+size_t Http_split(char *b,size_t n,char **pd,size_t *dlen)
+{
+ char *p;
+ size_t addtion, hlen;
+
+ hlen = 0;
+
+ if( n < 16 ) return 0; // 长度太小,不可能是一个HTML报文
+
+ if(strncasecmp(b,"HTTP/",5) != 0){
+ return 0; // 没有HTML首部????
+ /* message without http header */
+ //*pd = b;
+ //*dlen = n;
+ }else{
+ if( p = strnstr(b,"\r\n\r\n",n) ) addtion = 4;
+ else if( p = strnstr(b,"\n\n",n) ) addtion = 2;
+
+ if( p ){
+ hlen = p - b;
+ *pd = ( p + addtion );
+ *dlen = n - hlen - addtion;
+ }else{ // 只有首部信息????
+ hlen = n;
+ *pd = (char*) 0;
+ *dlen = 0;
+ }
+ }
+ return hlen;
+}
+
+int Http_reponse_code(const char *b,size_t n)
+{
+ int r = -1;
+
+ for(; n && *b != ' ' && *b !='\r' && *b != '\n'; b++,n--) ;
+ if( !n || *b != ' ') r = -1;
+ else{
+ r = atoi(b);
+ if( r < 100 || r > 600 ) r = -1;
+ }
+ return r;
+}
+
+int Http_get_header(const char *b,int n,const char *header,char *v)
+{
+ const char *e;
+ char h[64];
+ int r,header_len;
+
+ strcpy(h,header);
+ strcat(h,": ");
+ header_len = strlen(h);
+
+ /* remove status line. */
+ e = strchr(b,'\n');
+ if( !e ) return -1;
+ e++;
+ n -= (e - b);
+ b = e;
+
+ for(; n >= 0; ){
+ e = strchr(b,'\n');
+ if( !e ) r = n; /* last line */
+ else{r = e - b ; r++;}
+
+ if( r > header_len ){
+ if( strncasecmp(b, h, header_len) == 0){
+ /* header found */
+ b += header_len;
+ for(; *b != '\r' && *b != '\n'; v++,b++) *v = *b;
+ *v = '\0';
+ return 0;
+ }
+ }
+ b += r;
+ n -= r;
+ } /* end for */
+ return -1;
+}
diff --git a/httpencode.h b/httpencode.h
new file mode 100644
index 0000000..36cb17d
--- a/dev/null
+++ b/httpencode.h
@@ -0,0 +1,15 @@
+#ifndef HTTPENCODE_H
+#define HTTPENCODE_H
+
+#define REQ_URL_P1_FMT "GET %s?info_hash=%s&peer_id=%s%s&port=%d&key=%s"
+#define REQ_URL_P1A_FMT "GET %s&info_hash=%s&peer_id=%s%s&port=%d&key=%s"
+#define REQ_URL_P2_FMT "%s%s%s&uploaded=%llu&downloaded=%llu&left=%llu&compact=1&numwant=%d HTTP/1.0"
+
+
+char* Http_url_encode(char *s,const char *b,size_t n);
+int Http_url_analyse(const char *url,char *host,int *port,char *path);
+size_t Http_split(char *b,size_t n,char **pd,size_t *dlen);
+int Http_reponse_code(const char *b,size_t n);
+int Http_get_header(const char *b,int n,const char *header,char *v);
+
+#endif
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..e9de238
--- a/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/iplist.cpp b/iplist.cpp
new file mode 100644
index 0000000..52e0de0
--- a/dev/null
+++ b/iplist.cpp
@@ -0,0 +1,47 @@
+#include "iplist.h" // def.h
+#include <string.h>
+
+IpList IPQUEUE;
+
+void IpList::_Emtpy()
+{
+ IPLIST *node = ipl_head;
+ for(; ipl_head;){
+ node = ipl_head;
+ ipl_head = node->next;
+ delete node;
+ }
+ count = 0;
+}
+
+int IpList::Add(const struct sockaddr_in *psin)
+{
+ IPLIST *node = ipl_head;
+ for(; node; node = node->next)
+ if(memcmp(psin, &node->address, sizeof(struct sockaddr_in)) == 0) break;
+
+ if( node ) return -1;
+ // if not exist;
+ node = new IPLIST;
+#ifndef WINDOWS
+ if( !node ) return -1;
+#endif
+ count++;
+ memcpy(&node->address,psin,sizeof(struct sockaddr_in));
+ node->next = ipl_head;
+ ipl_head = node;
+ return 0;
+}
+
+int IpList::Pop(struct sockaddr_in *psin)
+{
+ IPLIST *node = (IPLIST*) 0;
+ if(!ipl_head) return -1;
+ node = ipl_head;
+ ipl_head = ipl_head->next;
+
+ count--;
+ memcpy(psin, &node->address, sizeof(struct sockaddr_in));
+ delete node;
+ return 0;
+}
diff --git a/iplist.h b/iplist.h
new file mode 100644
index 0000000..3c8838d
--- a/dev/null
+++ b/iplist.h
@@ -0,0 +1,38 @@
+#ifndef IPLIST_H
+#define IPLIST_H
+
+#include "def.h"
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <unistd.h>
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+typedef struct _iplist{
+ struct sockaddr_in address;
+ struct _iplist *next;
+}IPLIST;
+
+class IpList
+{
+private:
+ IPLIST *ipl_head;
+ size_t count;
+ void _Emtpy();
+public:
+ IpList() { ipl_head = (IPLIST*)0; count = 0;}
+ ~IpList() { if(ipl_head) _Emtpy(); }
+ int Add(const struct sockaddr_in* psin);
+ int Pop(struct sockaddr_in* psin);
+ int IsEmpty() { return count ? 0 : 1; }
+};
+
+extern IpList IPQUEUE;
+#endif
diff --git a/missing b/missing
new file mode 100755
index 0000000..0a7fb5a
--- a/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 <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing 0.3 - GNU automake"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+ # We have makeinfo, but it failed.
+ exit 1
+ fi
+
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ tar)
+ shift
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ fi
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar ${1+"$@"} && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar ${1+"$@"} && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" ${1+"$@"} && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..977eaae
--- a/dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.8 2004/01/30 17:52:32 yuhong 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/msgencode.h b/msgencode.h
new file mode 100644
index 0000000..dce49cb
--- a/dev/null
+++ b/msgencode.h
@@ -0,0 +1,24 @@
+#ifndef MSGENCODE_H
+#define MSGENCODE_H
+
+#define M_CHOKE (unsigned char) 0
+#define M_UNCHOKE (unsigned char) 1
+#define M_INTERESTED (unsigned char) 2
+#define M_NOT_INTERESTED (unsigned char) 3
+#define M_HAVE (unsigned char) 4
+#define M_BITFIELD (unsigned char) 5
+#define M_REQUEST (unsigned char) 6
+#define M_PIECE (unsigned char) 7
+#define M_CANCEL (unsigned char) 8
+#define M_PORT (unsigned char) 9
+
+#define H_INT_LEN 4 /* int_siz */
+#define H_LEN 4 /* int_siz */
+#define H_BASE_LEN 1 /* chr_siz */
+#define H_HAVE_LEN 5 /* chr_siz + int_siz */
+#define H_PIECE_LEN 9 /* chr_siz + int_siz*2 */
+#define H_REQUEST_LEN 13 /* chr_siz + int_siz*3 */
+#define H_CANCEL_LEN 13 /* chr_siz + int_siz*3 */
+#define H_PORT_LEN 3 /* chr_siz + port_siz */
+
+#endif
diff --git a/peer.cpp b/peer.cpp
new file mode 100644
index 0000000..33a11a0
--- a/dev/null
+++ b/peer.cpp
@@ -0,0 +1,1410 @@
+#include "peer.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "btstream.h"
+#include "./btcontent.h"
+#include "./msgencode.h"
+#include "./peerlist.h"
+#include "./btconfig.h"
+#include "bttime.h"
+#include "console.h"
+
+#if !defined(HAVE_CLOCK_GETTIME) || !defined(HAVE_SNPRINTF)
+#include "compat.h"
+#endif
+
+// Convert a peer ID to a printable string.
+int TextPeerID(const unsigned char *peerid, char *txtid)
+{
+ int i, j;
+
+ for(i=j=0; i < PEER_ID_LEN; i++){
+ if( i==j && isprint(peerid[i]) && !isspace(peerid[i]) )
+ txtid[j++] = peerid[i];
+ else{
+ if(i==j){ sprintf(txtid+j, "0x"); j+=2; }
+ snprintf(txtid+j, 3, "%.2X", (int)(peerid[i]));
+ j += 2;
+ }
+ }
+ txtid[j] = '\0';
+
+ return 0;
+}
+
+
+/* g_next_up is used to rotate uploading. If we have the opportunity to
+ upload to a peer but skip it due to bw limiting, the var is set to point to
+ that peer and it will be given priority at the next opportunity.
+ g_next_dn is similar, but for downloading.
+ g_defer_up is used to let the g_next peer object know if it skipped, as the
+ socket could go non-ready if other messages are sent while waiting for bw.
+*/
+btPeer *btPeer::g_next_up = (btPeer *)0;
+btPeer *btPeer::g_next_dn = (btPeer *)0;
+unsigned char btPeer::g_defer_up = 0;
+
+btBasic Self;
+
+void btBasic::SetIp(struct sockaddr_in addr)
+{
+ memcpy(&m_sin.sin_addr,&addr.sin_addr,sizeof(struct in_addr));
+}
+
+void btBasic::SetAddress(struct sockaddr_in addr)
+{
+ memcpy(&m_sin,&addr,sizeof(struct sockaddr_in));
+}
+
+int btBasic::IpEquiv(struct sockaddr_in addr)
+{
+// CONSOLE.Debug_n("IpEquiv: %s <=> ", inet_ntoa(m_sin.sin_addr));
+// CONSOLE.Debug_n("%s", inet_ntoa(addr.sin_addr));
+// CONSOLE.Debug_n("");
+ return (memcmp(&m_sin.sin_addr,&addr.sin_addr,sizeof(struct in_addr)) == 0) ?
+ 1 : 0;
+}
+
+int btPeer::Need_Local_Data() const
+{
+ if( m_state.remote_interested && !bitfield.IsFull()){
+
+ if( BTCONTENT.IsFull() ) return 1; // i am seed
+
+ BitField tmpBitfield = *BTCONTENT.pBF;
+ tmpBitfield.Except(bitfield);
+ return tmpBitfield.IsEmpty() ? 0 : 1;
+
+ }
+ return 0;
+}
+
+int btPeer::Need_Remote_Data() const
+{
+ if( BTCONTENT.Seeding() || bitfield.IsEmpty() ) return 0;
+ else if( bitfield.IsFull() &&
+ BTCONTENT.CheckedPieces() >= BTCONTENT.GetNPieces() ) return 1;
+ else{
+ BitField tmpBitfield = bitfield; // what peer has
+ tmpBitfield.Except(*BTCONTENT.pBF); // what I have
+ tmpBitfield.Except(*BTCONTENT.pBMasterFilter); // what I don't want
+ tmpBitfield.And(*BTCONTENT.pBChecked); // what I've checked
+ return tmpBitfield.IsEmpty() ? 0 : 1;
+ }
+ return 0;
+}
+
+btPeer::btPeer()
+{
+ m_f_keepalive = 0;
+ m_status = P_CONNECTING;
+ m_unchoke_timestamp = (time_t)0;
+ m_last_timestamp = m_next_send_time = now;
+ m_state.remote_choked = m_state.local_choked = 1;
+ m_state.remote_interested = m_state.local_interested = 0;
+
+ m_err_count = 0;
+ m_cached_idx = m_last_req_piece = BTCONTENT.GetNPieces();
+ m_standby = 0;
+ m_req_send = 5;
+ m_req_out = 0;
+ m_latency = 0;
+ m_prev_dlrate = 0;
+ m_health_time = m_receive_time = m_choketime = m_last_timestamp;
+ m_cancel_time = m_latency_timestamp = (time_t)0;
+ m_bad_health = 0;
+ m_want_again = m_connect = m_retried = 0;
+ m_connect_seed = 0;
+ m_prefetch_time = (time_t)0;
+ m_requested = 0;
+ m_prefetch_completion = 0;
+
+ rate_dl.SetSelf(Self.DLRatePtr());
+ rate_ul.SetSelf(Self.ULRatePtr());
+}
+
+void btPeer::CopyStats(btPeer *peer)
+{
+ SetDLRate(peer->GetDLRate());
+ SetULRate(peer->GetULRate());
+ m_unchoke_timestamp = peer->GetLastUnchokeTime();
+ m_retried = peer->Retried(); // don't try to reconnect over & over
+}
+
+int btPeer::SetLocal(unsigned char s)
+{
+ switch(s){
+ case M_CHOKE:
+ if( m_state.local_choked ) return 0;
+ m_unchoke_timestamp = now;
+// if(arg_verbose) CONSOLE.Debug("Choking %p", this);
+ if(arg_verbose) CONSOLE.Debug("Choking %p (D=%lluMB@%dK/s)", this,
+ (unsigned long long)TotalDL() >> 20, (int)(RateDL() >> 10));
+ m_state.local_choked = 1;
+ if( g_next_up == this ) g_next_up = (btPeer *)0;
+ if( !reponse_q.IsEmpty()) reponse_q.Empty();
+ StopULTimer();
+ if( !m_requested && BTCONTENT.IsFull() ){
+ // hasn't sent a request since unchoke
+ if(arg_verbose) CONSOLE.Debug("%p inactive", this);
+ return -1;
+ }
+ m_requested = 0;
+ break;
+ case M_UNCHOKE:
+ if( !reponse_q.IsEmpty() ) StartULTimer();
+ if( !m_state.local_choked ) return 0;
+ m_unchoke_timestamp = now;
+// if(arg_verbose) CONSOLE.Debug("Unchoking %p", this);
+ if(arg_verbose) CONSOLE.Debug("Unchoking %p (D=%lluMB@%dK/s)", this,
+ (unsigned long long)TotalDL() >> 20, (int)(RateDL() >> 10));
+ m_state.local_choked = 0;
+ // No data is queued, so rate cannot delay sending.
+ m_next_send_time = now;
+ break;
+ case M_INTERESTED:
+ if( BTCONTENT.Seeding() ) return 0;
+ m_standby = 0;
+ if( m_state.local_interested ) return 0;
+ if(arg_verbose) CONSOLE.Debug("Interested in %p", this);
+ m_state.local_interested = 1;
+ break;
+ case M_NOT_INTERESTED:
+ if( !m_state.local_interested ) return 0;
+ if(arg_verbose) CONSOLE.Debug("Not interested in %p", this);
+ m_state.local_interested = 0;
+ if( !request_q.IsEmpty() ){
+ if( CancelRequest() < 0 ) return -1;
+ request_q.Empty();
+ }
+ break;
+ default:
+ return -1; // BUG ???
+ }
+ return stream.Send_State(s);
+}
+
+int btPeer::RequestPiece()
+{
+ size_t idx;
+ BitField tmpBitfield, *pfilter;
+ int endgame = 0;
+
+ size_t qsize = request_q.Qsize();
+ size_t psize = BTCONTENT.GetPieceLength() / cfg_req_slice_size;
+
+ // See if there's room in the queue for a new piece.
+ // Also, don't queue another piece if we still have a full piece queued.
+ if( cfg_req_queue_length - qsize < psize || qsize >= psize ){
+ m_req_send = m_req_out; // don't come back until you receive something.
+ return 0;
+ }
+
+ tmpBitfield = bitfield;
+ tmpBitfield.Except(*BTCONTENT.pBMasterFilter);
+ if( m_last_req_piece < BTCONTENT.GetNPieces() && tmpBitfield.Count() > 1 )
+ tmpBitfield.UnSet(m_last_req_piece);
+ if( (idx = PENDINGQUEUE.ReAssign(&request_q, tmpBitfield)) <
+ BTCONTENT.GetNPieces() ){
+ if(arg_verbose)
+ CONSOLE.Debug("Assigning #%d to %p from Pending", (int)idx, this);
+ if( BTCONTENT.pBMultPeer->IsSet(idx) ) WORLD.CompareRequest(this, idx);
+ BTCONTENT.pBMultPeer->Set(idx);
+ return SendRequest();
+ }
+
+ if( m_cached_idx < BTCONTENT.CheckedPieces() && !BTCONTENT.pBF->IsEmpty() ){
+ // A HAVE msg already selected what we want from this peer
+ // but ignore it in initial-piece mode.
+ idx = m_cached_idx;
+ m_cached_idx = BTCONTENT.GetNPieces();
+ if( !BTCONTENT.pBF->IsSet(idx) &&
+ (!BTCONTENT.GetFilter() || !BTCONTENT.GetFilter()->IsSet(idx)) &&
+ !PENDINGQUEUE.Exist(idx) &&
+ !WORLD.AlreadyRequested(idx) ){
+ if(arg_verbose) CONSOLE.Debug("Assigning #%d to %p", (int)idx, this);
+ return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
+ }
+ }
+
+ // If we didn't want the cached piece, select another.
+ if( BTCONTENT.pBF->IsEmpty() ){
+ // If we don't have a complete piece yet, try to get one that's already
+ // in progress. (Initial-piece mode)
+ pfilter = BTCONTENT.GetFilter();
+ do{
+ tmpBitfield = bitfield;
+ if( pfilter ){
+ tmpBitfield.Except(*pfilter);
+ pfilter = BTCONTENT.GetNextFilter(pfilter);
+ }
+ }while( pfilter && tmpBitfield.IsEmpty() );
+ if( m_latency < 60 ){
+ // Don't dup to very slow/high latency peers.
+ if( m_last_req_piece < BTCONTENT.GetNPieces() && tmpBitfield.Count() > 1 )
+ tmpBitfield.UnSet(m_last_req_piece);
+ idx = WORLD.What_Can_Duplicate(tmpBitfield, this, BTCONTENT.GetNPieces());
+ if( idx < BTCONTENT.GetNPieces() ){
+ if(arg_verbose) CONSOLE.Debug("Want to dup #%d to %p", (int)idx, this);
+ btPeer *peer = WORLD.WhoHas(idx);
+ if(peer){
+ if(arg_verbose) CONSOLE.Debug("Duping #%d from %p to %p",
+ (int)idx, peer, this);
+ if( request_q.CopyShuffle(&peer->request_q, idx) < 0 ) return -1;
+ WORLD.CompareRequest(this, idx);
+ BTCONTENT.pBMultPeer->Set(idx);
+ return SendRequest();
+ }
+ }else if(arg_verbose) CONSOLE.Debug("Nothing to dup to %p", this);
+ }
+ }
+
+ // Doesn't have a piece that's already in progress--choose another.
+ pfilter = BTCONTENT.GetFilter();
+ do{
+ tmpBitfield = bitfield;
+ tmpBitfield.Except(*BTCONTENT.pBF);
+ if( pfilter ){
+ tmpBitfield.Except(*pfilter);
+ pfilter = BTCONTENT.GetNextFilter(pfilter);
+ }
+ // Don't go after pieces we might already have (but don't know yet)
+ tmpBitfield.And(*BTCONTENT.pBChecked);
+ // tmpBitfield tells what we need from this peer...
+ }while( pfilter && tmpBitfield.IsEmpty() );
+ if( m_last_req_piece < BTCONTENT.GetNPieces() && tmpBitfield.Count() > 1 )
+ tmpBitfield.UnSet(m_last_req_piece);
+
+ if( tmpBitfield.IsEmpty() ){
+ // We don't need to request anything from the peer.
+ if( !Need_Remote_Data() )
+ return SetLocal(M_NOT_INTERESTED);
+ else if( m_last_req_piece < BTCONTENT.GetNPieces() &&
+ !BTCONTENT.pBF->IsSet(m_last_req_piece) ){
+ // May have excluded the only viable request; allow a retry.
+ m_last_req_piece = BTCONTENT.GetNPieces();
+ return 0; // Allow another peer a shot at it first.
+ }else{
+ if(arg_verbose) CONSOLE.Debug("%p standby", this);
+ m_standby = 1; // nothing to do at the moment
+ return 0;
+ }
+ }
+
+ BitField tmpBitfield2 = tmpBitfield;
+ WORLD.CheckBitField(tmpBitfield2);
+ // [tmpBitfield2] ...that we haven't requested from anyone.
+ if( tmpBitfield2.IsEmpty() ){
+ // Everything this peer has that I want, I've already requested.
+ int endgame = WORLD.Endgame();
+ if( endgame && m_latency < 60 ){
+ // OK to duplicate a request, but not to very slow/high latency peers.
+// idx = tmpBitfield.Random();
+ idx = 0; // flag for Who_Can_Duplicate()
+ BitField tmpBitfield3 = tmpBitfield2;
+ idx = WORLD.What_Can_Duplicate(tmpBitfield3, this, idx);
+ if( idx < BTCONTENT.GetNPieces() ){
+ if(arg_verbose) CONSOLE.Debug("Want to dup #%d to %p",
+ (int)idx, this);
+ btPeer *peer = WORLD.WhoHas(idx);
+ if(peer){ // failsafe
+ if(arg_verbose) CONSOLE.Debug("Duping #%d from %p to %p",
+ (int)idx, peer, this);
+ if( request_q.CopyShuffle(&peer->request_q, idx) < 0 ) return -1;
+ WORLD.CompareRequest(this, idx);
+ BTCONTENT.pBMultPeer->Set(idx);
+ return SendRequest();
+ }
+ }
+ }
+ btPeer *peer;
+ if( request_q.IsEmpty() && (peer = WORLD.Who_Can_Abandon(this)) ){
+ // Cancel a request to the slowest peer & request it from this one.
+ idx = peer->FindLastCommonRequest(bitfield);
+ if(arg_verbose) CONSOLE.Debug("Reassigning #%d from %p to %p",
+ (int)idx, peer, this);
+ // RequestQueue class "moves" rather than "copies" in assignment!
+ if( request_q.Copy(&peer->request_q, idx) < 0 ) return -1;
+ WORLD.CompareRequest(this, idx);
+ BTCONTENT.pBMultPeer->Set(idx);
+ if( endgame ) peer->UnStandby();
+ if( peer->CancelPiece(idx) < 0 ) peer->CloseConnection();
+ return SendRequest();
+ }else if( BTCONTENT.CheckedPieces() >= BTCONTENT.GetNPieces() ){
+ if(arg_verbose) CONSOLE.Debug("%p standby", this);
+ m_standby = 1; // nothing to do at the moment
+ }
+ }else{
+ // Request something that we haven't requested yet (most common case).
+ // Try to make it something that has good trade value.
+ BitField tmpBitfield3 = tmpBitfield2;
+ WORLD.FindValuedPieces(tmpBitfield3, this, BTCONTENT.pBF->IsEmpty());
+ if( tmpBitfield3.IsEmpty() ) tmpBitfield3 = tmpBitfield2;
+ idx = tmpBitfield3.Random();
+ if(arg_verbose) CONSOLE.Debug("Assigning #%d to %p", (int)idx, this);
+ return (request_q.CreateWithIdx(idx) < 0) ? -1 : SendRequest();
+ }
+ return 0;
+}
+
+int btPeer::MsgDeliver()
+{
+ size_t r,idx,off,len;
+ int retval = 0;
+
+ char *msgbuf = stream.in_buffer.BasePointer();
+
+ r = get_nl(msgbuf);
+
+ // Don't require keepalives if we're receiving other messages.
+ m_last_timestamp = now;
+ if( 0 == r ){
+ if( !m_f_keepalive ) if( stream.Send_Keepalive() < 0 ) return -1;
+ m_f_keepalive = 0;
+ return 0;
+ }else{
+ char msg = msgbuf[H_LEN];
+ switch(msg){
+ case M_CHOKE:
+ if(H_BASE_LEN != r) return -1;
+ if(arg_verbose) CONSOLE.Debug("%p choked me", this);
+ if( m_lastmsg == M_UNCHOKE && m_last_timestamp <= m_choketime+1 ){
+ if( PeerError(2, "Choke oscillation") < 0 ) return -1;
+ }
+ m_choketime = m_last_timestamp;
+ m_state.remote_choked = 1;
+ StopDLTimer();
+ if( g_next_dn == this ) g_next_dn = (btPeer *)0;
+ if( !request_q.IsEmpty() ){
+ BTCONTENT.pBMultPeer->Set(request_q.GetRequestIdx());
+ PutPending();
+ }
+ m_cancel_time = now;
+ break;
+
+ case M_UNCHOKE:
+ if(H_BASE_LEN != r) return -1;
+ if(arg_verbose) CONSOLE.Debug("%p unchoked me", this);
+ if( m_lastmsg == M_CHOKE && m_last_timestamp <= m_choketime+1 ){
+ if( PeerError(2, "Choke oscillation") < 0 ) return -1;
+ }
+ m_choketime = m_last_timestamp;
+ m_state.remote_choked = 0;
+ m_standby = 0;
+ if( !stream.PeekNextMessage(M_CHOKE) ){
+ m_prefetch_completion = 0;
+ retval = RequestCheck();
+ }
+ break;
+
+ case M_INTERESTED:
+ if(H_BASE_LEN != r) return -1;
+ if(arg_verbose) CONSOLE.Debug("%p is interested", this);
+ m_state.remote_interested = 1;
+ if( Need_Local_Data() ) WORLD.UnchokeIfFree(this);
+ break;
+
+ case M_NOT_INTERESTED:
+ if(H_BASE_LEN != r) return -1;
+ if(arg_verbose) CONSOLE.Debug("%p is not interested", this);
+
+ m_state.remote_interested = 0;
+
+ /* remove peer's reponse queue */
+ if( !reponse_q.IsEmpty()) reponse_q.Empty();
+
+ /* if I've been seed for a while, nobody should be uninterested */
+ if( BTCONTENT.IsFull() && BTCONTENT.GetSeedTime() - now >= 300 )
+ return -2;
+ break;
+
+ case M_HAVE:
+ if(H_HAVE_LEN != r) return -1;
+
+ idx = get_nl(msgbuf + H_LEN + H_BASE_LEN);
+
+ if( idx >= BTCONTENT.GetNPieces() || bitfield.IsSet(idx) ) return -1;
+
+ bitfield.Set(idx);
+
+ if( bitfield.IsFull() ){
+ if( BTCONTENT.IsFull() ) return -2;
+ else stream.out_buffer.SetSize(BUF_DEF_SIZ);
+ }
+
+ if( !BTCONTENT.pBF->IsSet(idx) && !BTCONTENT.pBMasterFilter->IsSet(idx) ){
+ if( m_cached_idx >= BTCONTENT.GetNPieces() || m_standby ||
+ (!BTCONTENT.GetFilter() || !BTCONTENT.GetFilter()->IsSet(idx)) )
+ m_cached_idx = idx;
+ if(arg_verbose && m_standby) CONSOLE.Debug("%p un-standby", this);
+ m_standby = 0;
+ }
+
+ // see if we're Interested now
+ if(!m_standby) retval = RequestCheck();
+ break;
+
+ case M_REQUEST:
+ if(H_REQUEST_LEN != r || !m_state.remote_interested) return -1;
+
+ idx = get_nl(msgbuf + H_LEN + H_BASE_LEN);
+
+ if( !BTCONTENT.pBF->IsSet(idx) ) return -1;
+
+ off = get_nl(msgbuf + H_LEN + H_BASE_LEN + H_INT_LEN);
+ len = get_nl(msgbuf + H_LEN + H_BASE_LEN + H_INT_LEN * 2);
+
+ if(arg_verbose) CONSOLE.Debug("%p is requesting %d/%d/%d",
+ this, (int)idx, (int)off, (int)len);
+
+ if( !reponse_q.IsValidRequest(idx, off, len) ) return -1;
+
+ if( m_state.local_choked ){
+ if( m_last_timestamp - m_unchoke_timestamp >
+ (m_latency ? (m_latency*2) : 60) ){
+ if( PeerError(1, "choked request") < 0 ) return -1;
+ if( stream.Send_State(M_CHOKE) < 0 ) return -1;
+ // This will mess with the unchoke rotation (to this peer's
+ // disadvantage), but otherwise we may spam them with choke msgs.
+ m_unchoke_timestamp = m_last_timestamp;
+ }
+ }else{
+ if( !m_requested ){
+ m_requested = 1;
+ if( stream.out_buffer.SetSize(BUF_DEF_SIZ +
+ (len < DEFAULT_SLICE_SIZE) ? DEFAULT_SLICE_SIZE : len) < 0 )
+ return -1;
+ if( (!m_receive_time || BTCONTENT.Seeding()) &&
+ now > m_unchoke_timestamp ){
+ m_latency = (now <= m_unchoke_timestamp) ? 1 :
+ (now - m_unchoke_timestamp);
+ if(arg_verbose) CONSOLE.Debug("%p latency is %d sec (request)",
+ this, (int)m_latency);
+ }
+ }
+ retval = reponse_q.Add(idx, off, len);
+ }
+ break;
+
+ case M_PIECE:
+ if( H_PIECE_LEN >= r ) return -1;
+ m_receive_time = m_last_timestamp;
+ // PieceDeliver handles the error determination & DL counting
+ retval = PieceDeliver(r);
+ break;
+
+ case M_BITFIELD:
+ if( (r - H_BASE_LEN) != bitfield.NBytes() || !bitfield.IsEmpty() )
+ return -1;
+ bitfield.SetReferBuffer(msgbuf + H_LEN + H_BASE_LEN);
+ if(bitfield.IsFull()){
+ if(arg_verbose) CONSOLE.Debug("%p is a seed (bitfield is full)", this);
+ if(BTCONTENT.IsFull()) return -2;
+ else{
+ stream.out_buffer.SetSize(BUF_DEF_SIZ);
+ if( !m_want_again ) m_want_again = 1;
+ }
+ }else if(arg_verbose){
+ if( bitfield.IsEmpty() ) CONSOLE.Debug("%p bitfield is empty", this);
+ else CONSOLE.Debug("%p bitfield has %d%%", this,
+ 100 * bitfield.Count() / BTCONTENT.GetNPieces());
+ }
+
+ // This is needed in order to set our Interested state.
+ retval = RequestCheck(); // fixed client stall
+ break;
+
+ case M_CANCEL:
+ if(H_CANCEL_LEN != r) return -1;
+
+ idx = get_nl(msgbuf + H_LEN + H_BASE_LEN);
+ off = get_nl(msgbuf + H_LEN + H_BASE_LEN + H_INT_LEN);
+ len = get_nl(msgbuf + H_LEN + H_BASE_LEN + H_INT_LEN * 2);
+ if( reponse_q.Remove(idx,off,len) < 0 ){
+ if( m_state.local_choked &&
+ m_last_timestamp - m_unchoke_timestamp >
+ (m_latency ? (m_latency*2) : 60) ){
+ if( PeerError(1, "Bad cancel") < 0 ) return -1;
+ }
+ }else if( reponse_q.IsEmpty() && g_next_up == this )
+ g_next_up = (btPeer *)0;
+ break;
+
+ default:
+ if(arg_verbose)
+ CONSOLE.Debug("Unknown message type %d from peer %p", (int)msg, this);
+ } // switch
+
+ if( retval >= 0 ) m_lastmsg = msg;
+ }
+ return retval;
+}
+
+int btPeer::ReponseSlice()
+{
+ size_t len = 0;
+ struct timespec nowspec;
+
+ ssize_t retval;
+ size_t idx,off;
+ reponse_q.Pop(&idx,&off,&len);
+
+ if( BTCONTENT.global_buffer_size < len ){
+ delete []BTCONTENT.global_piece_buffer;
+ BTCONTENT.global_piece_buffer = new char[len];
+ BTCONTENT.global_buffer_size = BTCONTENT.global_piece_buffer ? len : 0;
+ }
+ retval = BTCONTENT.ReadSlice(BTCONTENT.global_piece_buffer,idx,off,len);
+ if( retval < 0 ) return -1;
+ else if( retval && cfg_cache_size ) Self.OntimeUL(0); // disk read delay
+ // If not using cache, need to always allow time for a disk read.
+
+ size_t currentrate = CurrentUL();
+ if(arg_verbose) CONSOLE.Debug("Sending %d/%d/%d to %p",
+ (int)idx, (int)off, (int)len, this);
+ // project the time to send another slice
+ if( 0==currentrate ){ // don't know peer's rate; use best guess
+ // These are "int" for signed calculations below.
+ int rate = (int)(Self.RateUL());
+ int unchoked = (int)(WORLD.GetUnchoked()); // can't be 0 here
+ if( cfg_max_bandwidth_up < unchoked || cfg_max_bandwidth_up <= rate ){
+ if( rate < unchoked || rate < (unchoked*len)/3600 )
+ m_next_send_time = now;
+ else m_next_send_time = now + len / (rate / unchoked);
+ }else{
+ m_next_send_time = now + len /
+ ( ((int)cfg_max_bandwidth_up - rate >
+ (int)cfg_max_bandwidth_up / unchoked) ?
+ (cfg_max_bandwidth_up - rate) :
+ ((cfg_max_bandwidth_up + unchoked-1) / unchoked) );
+ }
+ }else m_next_send_time = now + len /
+ ( (currentrate < cfg_max_bandwidth_up || 0==cfg_max_bandwidth_up) ?
+ currentrate : cfg_max_bandwidth_up );
+
+ m_prefetch_time = (time_t)0;
+
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+ retval = stream.Send_Piece(idx,off,BTCONTENT.global_piece_buffer,len);
+ if( retval >= 0 ){
+ WORLD.Upload();
+ DataSended(len, nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000);
+ if( !m_want_again && BTCONTENT.Seeding() )
+ m_want_again = 1;
+ }
+ else if(arg_verbose) CONSOLE.Debug("%p: %s", this, strerror(errno));
+
+ return (int)retval;
+}
+
+int btPeer::SendRequest()
+{
+ int first = 1;
+ PSLICE ps = request_q.NextSend();
+
+ if( m_req_out > cfg_req_queue_length ){
+ if(arg_verbose)
+ CONSOLE.Debug("ERROR@5: %p m_req_out underflow, resetting", this);
+ m_req_out = 0;
+ }
+ if( ps && m_req_out < m_req_send ){
+ if(arg_verbose){
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("Requesting #%d from %p (%d left, %d slots):",
+ (int)(ps->index), this, (int)(request_q.Qsize()), (int)m_req_send);
+ }
+ for( int i=0; ps && m_req_out < m_req_send && i<5; ps = ps->next, i++ ){
+ if( first && (!RateDL() ||
+ 0 >= (m_req_out+1) * ps->length / (double)RateDL() - m_latency) ){
+ request_q.SetReqTime(ps, now);
+ first = 0;
+ } else request_q.SetReqTime(ps, (time_t)0);
+ if(arg_verbose) CONSOLE.Debug_n(".");
+ if(stream.Send_Request(ps->index,ps->offset,ps->length) < 0){ return -1; }
+ m_last_req_piece = ps->index;
+ request_q.SetNextSend(ps->next);
+ m_req_out++;
+ }
+ if(arg_verbose) CONSOLE.Debug_n("");
+ m_receive_time = now;
+ }
+ return ( m_req_out < m_req_send && !m_standby ) ? RequestPiece() : 0;
+}
+
+int btPeer::CancelPiece(size_t idx)
+{
+ PSLICE ps = request_q.GetHead();
+ PSLICE next;
+ int cancel = 1;
+
+ for( ; ps && ps->index != idx; ps=ps->next ){ // find the piece
+ if( ps == request_q.NextSend() ) cancel = 0;
+ }
+ if( !ps ) return 0;
+
+ for( ; ps; ps = next ){
+ if( ps->index != idx ) break;
+ if( ps == request_q.NextSend() ) cancel = 0;
+ if( cancel ){
+ if(arg_verbose) CONSOLE.Debug("Cancelling %d/%d/%d to %p",
+ (int)(ps->index), (int)(ps->offset), (int)(ps->length), this);
+ if(stream.Send_Cancel(ps->index,ps->offset,ps->length) < 0)
+ return -1;
+ m_req_out--;
+ if( m_req_out > cfg_req_queue_length ){
+ if(arg_verbose)
+ CONSOLE.Debug("ERROR@1: %p m_req_out underflow, resetting", this);
+ m_req_out = 0;
+ }
+ m_cancel_time = now;
+ }
+ next = ps->next;
+ request_q.Remove(ps->index, ps->offset, ps->length);
+ }
+ if( request_q.IsEmpty() ){
+ StopDLTimer();
+ m_standby = 0;
+ }
+ if( !m_req_out && g_next_dn == this ) g_next_dn = (btPeer *)0;
+
+ return 1;
+}
+
+int btPeer::CancelRequest()
+{
+ PSLICE ps;
+ int retval;
+
+ ps = request_q.GetHead();
+ for( ; ps; ps = ps->next){
+ if( ps == request_q.NextSend() ) break;
+ if(arg_verbose) CONSOLE.Debug("Cancelling %d/%d/%d to %p",
+ (int)(ps->index), (int)(ps->offset), (int)(ps->length), this);
+ if(stream.Send_Cancel(ps->index,ps->offset,ps->length) < 0)
+ return -1;
+ m_req_out--;
+ if( m_req_out > cfg_req_queue_length ){
+ if(arg_verbose)
+ CONSOLE.Debug("ERROR@2: %p m_req_out underflow, resetting", this);
+ m_req_out = 0;
+ }
+ m_cancel_time = now;
+ }
+ if( !m_req_out && g_next_dn == this ) g_next_dn = (btPeer *)0;
+
+ return 0;
+}
+
+int btPeer::CancelSliceRequest(size_t idx, size_t off, size_t len)
+{
+ PSLICE ps;
+ int cancel = 1;
+ int idxfound = 0;
+ int retval = 0;
+
+ if( request_q.IsEmpty() ) return 0;
+
+ for(ps = request_q.GetHead(); ps; ps = ps->next){
+ if( ps == request_q.NextSend() ) cancel = 0;
+ if( idx == ps->index ){
+ if( off == ps->offset && len == ps->length ){
+ retval = 1;
+ request_q.Remove(idx,off,len);
+ if(cancel){
+ if(arg_verbose) CONSOLE.Debug("Cancelling %d/%d/%d to %p",
+ (int)idx, (int)off, (int)len, this);
+ if(stream.Send_Cancel(idx,off,len) < 0)
+ return -1;
+ m_req_out--;
+ if( m_req_out > cfg_req_queue_length ){
+ if(arg_verbose)
+ CONSOLE.Debug("ERROR@3: %p m_req_out underflow, resetting",this);
+ m_req_out = 0;
+ }
+ if( !m_req_out && g_next_dn == this ) g_next_dn = (btPeer *)0;
+ m_cancel_time = now;
+
+ // Don't call RequestCheck() here since that could cause the slice
+ // we're cancelling to be dup'd from another peer.
+ }
+ break;
+ }
+ idxfound = 1;
+ }else if( idxfound ) break;
+ }
+ if( request_q.IsEmpty() ){
+ StopDLTimer();
+ m_standby = 0;
+ }
+
+ return retval;
+}
+
+size_t btPeer::FindLastCommonRequest(BitField &proposerbf)
+{
+ PSLICE ps;
+ size_t idx, piece;
+
+ idx = piece = BTCONTENT.GetNPieces();
+ if( request_q.IsEmpty() ) return piece;
+ ps = request_q.GetHead();
+ for( ; ps; ps = ps->next ){
+ if( ps->index != idx ){
+ idx = ps->index;
+ if( proposerbf.IsSet(idx) ) piece = idx;
+ }
+ }
+ return piece;
+}
+
+int btPeer::ReportComplete(size_t idx, size_t len)
+{
+ int r;
+
+ if( (r = BTCONTENT.APieceComplete(idx)) > 0 ){
+ if(arg_verbose) CONSOLE.Debug("Piece #%d completed", (int)idx);
+ PeerError(-1, "Piece completed");
+ WORLD.Tell_World_I_Have(idx);
+ BTCONTENT.CheckFilter();
+ if( BTCONTENT.IsFull() )
+ WORLD.CloseAllConnectionToSeed();
+ }else if( 0 == r ){ // hash check failed
+ // Don't count an error against the peer in initial or endgame mode, since
+ // some slices may have come from other peers.
+ if( !BTCONTENT.pBMultPeer->IsSet(idx) ){
+ // The entire piece came from this peer.
+ DataUnRec(BTCONTENT.GetPieceLength(idx) - len);
+ if( PeerError(4, "Bad complete") < 0 ) CloseConnection();
+ else{
+ ResetDLTimer(); // set peer rate=0 so we don't favor for upload
+ bitfield.UnSet(idx); // don't request this piece from this peer again
+ }
+ }
+ }
+ // Need to re-download entire piece if check failed, so cleanup in any case.
+ m_prefetch_completion = 0;
+ if( WORLD.GetDupReqs() && BTCONTENT.pBMultPeer->IsSet(idx) ){
+ if( WORLD.CancelPiece(idx) && arg_verbose )
+ CONSOLE.Debug("Duplicate request cancelled in piece completion");
+ }
+ if( PENDINGQUEUE.Delete(idx) && arg_verbose )
+ CONSOLE.Debug("Duplicate found in Pending, shouldn't be there");
+ BTCONTENT.pBMultPeer->UnSet(idx);
+ return r;
+}
+
+int btPeer::PieceDeliver(size_t mlen)
+{
+ size_t idx, off, len;
+ char *msgbuf = stream.in_buffer.BasePointer();
+ time_t t = (time_t)0;
+ int f_accept = 0, f_requested = 0, f_success = 1, f_count = 1, f_want = 1;
+ int f_complete = 0, dup = 0;
+
+ idx = get_nl(msgbuf + H_LEN + H_BASE_LEN);
+ off = get_nl(msgbuf + H_LEN + H_BASE_LEN + H_INT_LEN);
+ len = mlen - H_PIECE_LEN;
+
+ if( !request_q.IsEmpty() ){
+ t = request_q.GetReqTime(idx,off,len);
+ // Verify whether this is an outstanding request (not for error counting).
+ PSLICE ps = request_q.GetHead();
+ for( ; ps; ps = ps->next){
+ if( ps == request_q.NextSend() ) break;
+ if( idx==ps->index && off==ps->offset && len==ps->length ){
+ f_requested = 1;
+ break;
+ }
+ }
+ }
+
+ // If the slice is outstanding and was cancelled from this peer, accept.
+ if( !f_requested && BTCONTENT.pBMultPeer->IsSet(idx) &&
+ m_last_timestamp - m_cancel_time <= (m_latency ? (m_latency*2) : 60) &&
+ (WORLD.HasSlice(idx, off, len) || PENDINGQUEUE.HasSlice(idx, off, len)) ){
+ f_accept = dup = 1;
+ }
+
+ Self.StartDLTimer();
+
+ if( f_requested || f_accept ){
+ if(arg_verbose) CONSOLE.Debug("Receiving piece %d/%d/%d from %p",
+ (int)idx, (int)off, (int)len, this);
+ if( !BTCONTENT.pBF->IsSet(idx) &&
+ BTCONTENT.WriteSlice(msgbuf + H_LEN + H_PIECE_LEN,idx,off,len) < 0 ){
+ CONSOLE.Warning(2, "warn, WriteSlice failed; is filesystem full?");
+ f_success = 0;
+ // Re-queue the request, unless WriteSlice triggered flush failure
+ // (then the request is already in Pending).
+ if( f_requested && !BTCONTENT.FlushFailed() ){
+ // This removes only the first instance; re-queued request is safe.
+ request_q.Remove(idx,off,len);
+ m_req_out--;
+ if( RequestSlice(idx,off,len) < 0 ){
+ // At least it's still queued & will go to Pending at peer close.
+ if( f_count ) DataRecved(len);
+ return -1;
+ }
+ }
+ }else{ // saved or had the data
+ request_q.Remove(idx,off,len);
+ if( f_requested ) m_req_out--;
+ // Check for & cancel requests for this slice from other peers in initial
+ // and endgame modes.
+ if( dup || (WORLD.GetDupReqs() && BTCONTENT.pBMultPeer->IsSet(idx)) )
+ dup = WORLD.CancelSlice(idx, off, len);
+ if( WORLD.GetDupReqs() || BTCONTENT.FlushFailed() )
+ dup += PENDINGQUEUE.DeleteSlice(idx, off, len);
+ }
+ }else{ // not requested--not saved
+ if( m_last_timestamp - m_cancel_time > (m_latency ? (m_latency*2) : 60) ){
+ char msg[40];
+ BTCONTENT.CountUnwantedBlock();
+ sprintf(msg, "Unrequested piece %d/%d/%d", (int)idx, (int)off, (int)len);
+ if( PeerError(1, msg) < 0 ) return -1;
+ ResetDLTimer(); // set peer rate=0 so we don't favor for upload
+ f_count = f_want = 0;
+ }else{
+ if(arg_verbose) CONSOLE.Debug("Unneeded piece %d/%d/%d from %p",
+ (int)idx, (int)off, (int)len, this);
+ BTCONTENT.CountDupBlock(len);
+ }
+ f_success = 0;
+ }
+ if( !m_want_again && f_want ) m_want_again = 1;
+
+ // Determine how many outstanding requests we should maintain, roughly:
+ // (request turnaround latency) / (time to transmit one slice)
+ if( f_requested ){
+ if(t){
+ m_latency = (m_last_timestamp <= t) ? 1 : (m_last_timestamp - t);
+ if(arg_verbose) CONSOLE.Debug("%p latency is %d sec (receive)",
+ this, (int)m_latency);
+ m_latency_timestamp = m_last_timestamp;
+ }
+ size_t rate;
+ if( (rate = RateDL()) > len/20 && m_latency_timestamp ){
+ // 20==RATE_INTERVAL from rate.cpp. This is really just a check to see
+ // if rate is measurable/usable.
+ m_req_send = (size_t)( m_latency / (len / (double)rate) + 1 );
+ if( m_req_send < 2 ) m_req_send = 2;
+
+ // If latency increases, we will see this as a dlrate decrease.
+ if( rate < m_prev_dlrate ) m_req_send++;
+ else if( m_last_timestamp - m_latency_timestamp >= 30 &&
+ m_req_out == m_req_send - 1 ){
+ // Try to force latency measurement every 30 seconds.
+ m_req_send--;
+ m_latency_timestamp = m_last_timestamp;
+ }
+ m_prev_dlrate = rate;
+ }else if (m_req_send < 5) m_req_send = 5;
+ }
+
+ /* if piece download complete. */
+ if( f_success && !BTCONTENT.pBF->IsSet(idx) &&
+ ( (f_requested && (request_q.IsEmpty() || !request_q.HasIdx(idx))) ||
+ (f_accept && !WORLD.WhoHas(idx) && !PENDINGQUEUE.Exist(idx)) ) ){
+ // Above WriteSlice may have triggered flush failure. If data was saved,
+ // slice was deleted from Pending. If piece is incomplete, it's in Pending.
+ if( !(BTCONTENT.FlushFailed() && PENDINGQUEUE.Exist(idx)) &&
+ !(f_complete = ReportComplete(idx, len)) )
+ f_count = 0;
+ }
+
+ // Don't count the slice in our DL total if it was unsolicited or bad.
+ // (We don't owe the swarm any UL for such data.)
+ if( f_count ) DataRecved(len);
+
+ if( !f_complete && dup ) WORLD.CancelOneRequest(idx);
+
+ if( request_q.IsEmpty() ){
+ StopDLTimer();
+ if( f_requested) m_standby = 0;
+ }
+
+ return (P_FAILED == m_status) ? -1 :
+ (m_standby || !f_requested) ? 0 :
+ RequestCheck();
+}
+
+// This is for re-requesting unsuccessful slices.
+// Use RequestPiece for normal request queueing.
+int btPeer::RequestSlice(size_t idx,size_t off,size_t len)
+{
+ int r;
+ r = request_q.Requeue(idx,off,len);
+ if( r < 0 ) return -1;
+ else if( r ){
+ if(stream.Send_Request(idx,off,len) < 0){ return -1; }
+ m_req_out++;
+ m_receive_time = now;
+ }
+ return 0;
+}
+
+int btPeer::RequestCheck()
+{
+ if( BTCONTENT.Seeding() || WORLD.IsPaused() )
+ return SetLocal(M_NOT_INTERESTED);
+
+ if( Need_Remote_Data() ){
+ if(!m_state.local_interested && SetLocal(M_INTERESTED) < 0) return -1;
+ if( !m_state.remote_choked ){
+ if( m_req_out > cfg_req_queue_length ){
+ if(arg_verbose)
+ CONSOLE.Debug("ERROR@4: %p m_req_out underflow, resetting", this);
+ m_req_out = 0;
+ }
+ if( request_q.IsEmpty() && RequestPiece() < 0 ) return -1;
+ else if( m_req_out < m_req_send &&
+ (m_req_out < 2 || !RateDL() ||
+ 1 >= (m_req_out+1) * request_q.GetRequestLen() /
+ (double)RateDL() - m_latency)
+ // above formula is to try to allow delay between sending batches of reqs
+ && SendRequest() < 0 ) return -1;
+ }
+ }else
+ if(m_state.local_interested && SetLocal(M_NOT_INTERESTED) < 0) return -1;
+
+ if(!request_q.IsEmpty()) StartDLTimer();
+ else StopDLTimer();
+ return 0;
+}
+
+void btPeer::CloseConnection()
+{
+ if(arg_verbose) CONSOLE.Debug("%p closed", this);
+ if( P_FAILED != m_status ){
+ m_status = P_FAILED;
+ StopDLTimer();
+ StopULTimer();
+ stream.Close();
+ PutPending();
+ }
+ if( g_next_up == this ) g_next_up = (btPeer *)0;
+ if( g_next_dn == this ) g_next_dn = (btPeer *)0;
+}
+
+int btPeer::HandShake()
+{
+ char txtid[PEER_ID_LEN*2+3];
+ ssize_t r = stream.Feed();
+ if( r < 0 ){
+ if(arg_verbose) CONSOLE.Debug("%p: %s", this,
+ (r==-2) ? "remote closed" : strerror(errno));
+ return -1;
+ }
+ if( (r=stream.in_buffer.Count()) < 68 ){
+ // If it's not BitTorrent, don't wait around for a complete handshake.
+ if( r > 20 ){ // ignore 8 reserved bytes following protocol ID
+ if( memcmp(stream.in_buffer.BasePointer()+20,
+ BTCONTENT.GetShakeBuffer()+20, (r<28) ? (r-20) : 8) != 0 ){
+ if(arg_verbose){
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("peer %p gave 0x", this);
+ for(int i=20; i<r && i<27; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(stream.in_buffer.BasePointer()[i]));
+ CONSOLE.Debug_n(" as reserved bytes (partial)");
+ }
+ memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20,
+ (r<28) ? (r-20) : 8);
+ }
+ }
+ if(r && memcmp(stream.in_buffer.BasePointer(),BTCONTENT.GetShakeBuffer(),
+ (r<48) ? r : 48) != 0){
+ if(arg_verbose){
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("mine: 0x");
+ for(int i=0; i<r && i<48; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(BTCONTENT.GetShakeBuffer()[i]));
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("peer: 0x");
+ for(int i=0; i<r && i<48; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(stream.in_buffer.BasePointer()[i]));
+ if( r>48 ){
+ TextPeerID((unsigned char *)(stream.in_buffer.BasePointer()+48),
+ txtid);
+ CONSOLE.Debug("peer is %s", txtid);
+ }
+ }
+ return -1;
+ }
+ return 0;
+ }
+
+ if( memcmp(stream.in_buffer.BasePointer(), BTCONTENT.GetShakeBuffer(), 68)
+ == 0 ){
+ if(arg_verbose) CONSOLE.Debug("peer %p is myself", this);
+ if( m_connect && !cfg_public_ip ) Self.SetIp(m_sin);
+ WORLD.AdjustPeersCount();
+ return -1;
+ }
+
+ // If the reserved bytes differ, make them the same.
+ // If they mean anything important, the handshake is likely to fail anyway.
+ if( memcmp(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20,
+ 8) != 0 ){
+ if(arg_verbose){
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("peer %p gave 0x", this);
+ for(int i=20; i<27; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(stream.in_buffer.BasePointer()[i]));
+ CONSOLE.Debug_n(" as reserved bytes" );
+ }
+ memcpy(stream.in_buffer.BasePointer()+20, BTCONTENT.GetShakeBuffer()+20, 8);
+ }
+ if( memcmp(stream.in_buffer.BasePointer(),
+ BTCONTENT.GetShakeBuffer(),48) != 0 ){
+ if(arg_verbose){
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("mine: 0x");
+ for(int i=0; i<48; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(BTCONTENT.GetShakeBuffer()[i]));
+ CONSOLE.Debug_n("");
+ CONSOLE.Debug_n("peer: 0x");
+ for(int i=0; i<48; i++) CONSOLE.Debug_n("%2.2hx",
+ (unsigned short)(unsigned char)(stream.in_buffer.BasePointer()[i]));
+ }
+ return -1;
+ }
+
+ memcpy(id, stream.in_buffer.BasePointer()+48, PEER_ID_LEN);
+ if(arg_verbose){
+ TextPeerID((unsigned char *)(stream.in_buffer.BasePointer()+48), txtid);
+ CONSOLE.Debug("Peer %p ID: %s", this, txtid);
+ }
+
+ // ignore peer id verify
+ if( !BTCONTENT.pBF->IsEmpty()){
+ char *bf = new char[BTCONTENT.pBF->NBytes()];
+#ifndef WINDOWS
+ if(!bf) return -1;
+#endif
+ BTCONTENT.pBF->WriteToBuffer(bf);
+ r = stream.Send_Bitfield(bf,BTCONTENT.pBF->NBytes());
+ delete []bf;
+ }
+
+ if( r >= 0){
+ if( stream.in_buffer.PickUp(68) < 0 ) return -1;
+ m_status = P_SUCCESS;
+ m_retried = 0; // allow reconnect attempt
+ // When seeding, new peer starts at the end of the line.
+ if( BTCONTENT.Seeding() ){ // i am seed
+ // Allow resurrected peer to resume its place in line.
+ if( 0 == m_unchoke_timestamp ) m_unchoke_timestamp = now;
+ m_connect_seed = 1;
+ }
+ if( stream.HaveMessage() ) return RecvModule();
+ }
+ return r;
+}
+
+int btPeer::Send_ShakeInfo()
+{
+ return stream.Send_Buffer((char*)BTCONTENT.GetShakeBuffer(),68);
+}
+
+int btPeer::NeedWrite(int limited)
+{
+ int yn = 0;
+ size_t r;
+
+ if( stream.out_buffer.Count() )
+ yn = 1; // data in buffer to send
+ else if( P_CONNECTING == m_status )
+ yn = 1; // peer is connecting
+ else if( WORLD.IsPaused() ) yn = 0; // paused--no up/download allowed
+ else if( !m_state.local_choked && !reponse_q.IsEmpty() && !limited )
+ yn = 1; //can upload a slice
+ else if( !m_state.remote_choked && m_state.local_interested &&
+ request_q.IsEmpty() && !m_standby )
+ yn = 1; // can request a new piece
+ else if( request_q.NextSend() && m_req_out < m_req_send &&
+ (m_req_out < 2 || !(r = RateDL()) ||
+ 1 >= (m_req_out+1) * request_q.GetRequestLen() / (double)r -
+ m_latency) )
+ yn = 1; // can send a queued request
+
+ return yn;
+}
+
+int btPeer::NeedRead(int limited)
+{
+ int yn = 1;
+
+ if( P_SUCCESS == m_status && stream.PeekMessage(M_PIECE) &&
+ ((g_next_dn && g_next_dn != this) || limited) ){
+ yn = 0;
+ }
+
+ return yn;
+}
+
+int btPeer::CouldReponseSlice()
+{
+ // If the entire buffer isn't big enough, go ahead and let the put resize it.
+ if( !m_state.local_choked &&
+ (stream.out_buffer.LeftSize() >=
+ H_LEN + H_PIECE_LEN + reponse_q.GetRequestLen() ||
+ stream.out_buffer.Count() + stream.out_buffer.LeftSize() <
+ H_LEN + H_PIECE_LEN + reponse_q.GetRequestLen()) )
+ return 1;
+ return 0;
+}
+
+int btPeer::AreYouOK()
+{
+ m_f_keepalive = 1;
+ return stream.Send_Keepalive();
+}
+
+int btPeer::RecvModule()
+{
+ ssize_t r = 0;
+
+ if( stream.PeekMessage(M_PIECE) ){
+ if( !g_next_dn || g_next_dn==this ){
+ int limited = WORLD.BandWidthLimitDown(Self.LateDL());
+ if( !limited ){
+ if( g_next_dn ) g_next_dn = (btPeer *)0;
+ r = stream.Feed(&rate_dl); // feed full amount (can download)
+// if(r>=0) CONSOLE.Debug("%p fed piece, now has %d bytes", this, r);
+ Self.OntimeDL(0);
+ }
+ else if( !g_next_dn ){
+ if(arg_verbose) CONSOLE.Debug("%p waiting for DL bandwidth", this);
+ g_next_dn = this;
+ }
+ } // else deferring DL, unless limited.
+ }else if( !stream.HaveMessage() ){ // could have been called post-handshake
+ r = stream.Feed(BUF_DEF_SIZ, &rate_dl);
+// if(r>=0) CONSOLE.Debug("%p fed, now has %d bytes (msg=%d)",
+// this, r, (int)(stream.PeekMessage()));
+ }
+ if( r < 0 ){
+ if(arg_verbose) CONSOLE.Debug("%p: %s", this,
+ (r==-2) ? "remote closed" : strerror(errno));
+ return -1;
+ }
+
+ while( r = stream.HaveMessage() ){
+ if( r < 0 ) return -1;
+ if( (r = MsgDeliver()) == -2 ){
+ if(arg_verbose) CONSOLE.Debug("%p seed<->seed detected", this);
+ m_want_again = 0;
+ }
+ if( r < 0 || stream.PickMessage() < 0 ) return -1;
+ }
+
+ return 0;
+}
+
+int btPeer::SendModule()
+{
+ if( stream.out_buffer.Count() && stream.Flush() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("%p: %s", this, strerror(errno));
+ return -1;
+ }
+
+ if( !reponse_q.IsEmpty() && CouldReponseSlice() ){
+ int limited = WORLD.BandWidthLimitUp(Self.LateUL());
+ if( !g_next_up || g_next_up==this ){
+ if( !limited ){
+ if( g_next_up ) g_next_up = (btPeer *)0;
+ StartULTimer();
+ Self.StartULTimer();
+ if( ReponseSlice() < 0 ) return -1;
+ Self.OntimeUL(0);
+ }
+ else if( !g_next_up ){
+ if(arg_verbose) CONSOLE.Debug("%p waiting for UL bandwidth", this);
+ g_next_up = this;
+ if( g_defer_up ) g_defer_up = 0;
+ }
+ }else if( !limited ){
+ if(arg_verbose) CONSOLE.Debug("%p deferring UL to %p", this, g_next_up);
+ if( !g_defer_up ) g_defer_up = 1;
+ WORLD.Defer();
+ }
+ }else if( g_next_up == this ) g_next_up = (btPeer *)0;
+
+ return (!m_state.remote_choked) ? RequestCheck() : 0;
+}
+
+// Prevent a peer object from holding g_next_up when it's not ready to write.
+int btPeer::CheckSendStatus()
+{
+ if( g_next_up == this && !WORLD.BandWidthLimitUp(Self.LateUL()) ){
+ if(arg_verbose){
+ CONSOLE.Debug("%p is not write-ready", this);
+ if( g_defer_up ) CONSOLE.Debug("%p skipped UL", this);
+ }
+ g_next_up = (btPeer *)0;
+ }
+ return g_next_up ? 1 : 0;
+}
+
+/* Detect if a peer ignored, discarded, or lost my request and we're waiting
+ for a piece that may never arrive. */
+int btPeer::HealthCheck()
+{
+ if( BTCONTENT.IsFull() ){
+ // Catch seeders who suppress HAVE and don't disconnect other seeders,
+ // or who just sit there and waste a connection.
+ if( m_health_time <= now - 300 ){
+ m_health_time = now;
+ if( !m_state.remote_interested ){
+ if( m_bad_health ) return -1;
+ m_bad_health = 1;
+ } else m_bad_health = 0;
+ }
+ }else if( m_health_time <= now - 60 ){
+ m_health_time = now;
+ if( !m_state.remote_choked && m_req_out ){
+ size_t allowance = !m_latency ? 150 : ((m_latency < 60) ? 60 : m_latency);
+ if( m_receive_time < now - 2*allowance ){
+ // if a repeat occurrence, get rid of the peer
+ if( m_bad_health || PeerError(2, "unresponsive") < 0 ) return -1;
+ m_bad_health = 1;
+ if(arg_verbose)
+ CONSOLE.Debug("%p unresponsive; resetting request queue", this);
+ int retval = CancelRequest();
+ PutPending();
+ return (retval < 0) ? -1 : 0;
+ }else if( m_receive_time < now - allowance ){
+ CONSOLE.Debug("%p unresponsive; sending keepalive", this);
+ AreYouOK(); // keepalive--may stimulate the connection
+ }else m_bad_health = 0;
+ }else m_bad_health = 0;
+ }
+ return 0;
+}
+
+// This handles peers that suppress HAVE messages so that we don't always think
+// that they're empty. If we've sent the peer an amount of data equivalent to
+// two pieces, assume that they now have at least one complete piece.
+int btPeer::IsEmpty() const
+{
+ return ( bitfield.IsEmpty() && TotalUL() < BTCONTENT.GetPieceLength()*2 ) ?
+ 1:0;
+}
+
+void btPeer::PutPending()
+{
+ if( !request_q.IsEmpty() ){
+ if( PENDINGQUEUE.Pending(&request_q) != 0 )
+ WORLD.RecalcDupReqs();
+ WORLD.UnStandby();
+ }
+ m_req_out = 0;
+}
+
+int btPeer::NeedPrefetch() const
+{
+ if( P_SUCCESS == m_status &&
+ ( Is_Local_UnChoked() ||
+ (!BTCONTENT.IsFull() && Is_Remote_UnChoked() &&
+ m_prefetch_completion < 2 && request_q.LastSlice()) ) )
+ return 1;
+ else return 0;
+}
+
+// Call NeedPrefetch() first, which checks additional conditions!
+void btPeer::Prefetch(time_t deadline)
+{
+ size_t rd, ru;
+ size_t idx, off, len;
+ time_t predict, next_chance;
+
+ if( !BTCONTENT.IsFull() && Is_Remote_UnChoked() &&
+ m_prefetch_completion < 2 && request_q.LastSlice() && (rd=RateDL()) > 0 &&
+ request_q.Peek(&idx, &off, &len)==0 &&
+ m_last_timestamp + len / rd < now + WORLD.GetUnchokeInterval() &&
+ Self.RateDL() > 0 &&
+ m_last_timestamp + len / rd <
+ now + (cfg_cache_size*1024*1024 - BTCONTENT.GetPieceLength(idx)) /
+ Self.RateDL() ){
+ switch( BTCONTENT.CachePrep(idx) ){
+ case -1: // don't prefetch
+ m_prefetch_completion = 2;
+ break;
+ case 0: // ready, no data flushed
+ if( m_prefetch_completion || off==0 ){
+ if( off+len < BTCONTENT.GetPieceLength(idx) )
+ BTCONTENT.ReadSlice(NULL, idx, off+len,
+ BTCONTENT.GetPieceLength(idx)-off-len);
+ m_prefetch_completion = 2;
+ }else{
+ BTCONTENT.ReadSlice(NULL, idx, 0, off);
+ if( off+len < BTCONTENT.GetPieceLength(idx) )
+ m_prefetch_completion = 1;
+ else m_prefetch_completion = 2;
+ }
+ break;
+ case 1: // data was flushed (time used)
+ break;
+ }
+ }
+ else if( Is_Local_UnChoked() && reponse_q.Peek(&idx, &off, &len) == 0 ){
+ if( cfg_max_bandwidth_up )
+ next_chance = (time_t)( Self.LastSendTime() +
+ (double)(Self.LastSizeSent()) / cfg_max_bandwidth_up );
+ else next_chance = now;
+
+ if( g_next_up ){
+ if( g_next_up != this ){
+ // deferral pending; we'll get another chance to prefetch
+ return;
+ }else m_next_send_time = next_chance; // I am the next sender
+ }
+ if( m_next_send_time < next_chance ) predict = next_chance;
+ else predict = m_next_send_time;
+
+ // Don't prefetch if it will expire from cache before being sent.
+ if( predict < deadline && (0==(rd = Self.RateDL()) ||
+ predict <= now + cfg_cache_size*1024*1024 / rd) ){
+ // This allows re-prefetch if it might have expired from the cache.
+ if( !m_prefetch_time || (0==rd && 0==(ru = Self.RateUL())) ||
+ now - m_prefetch_time > BTCONTENT.CacheSize() / (rd + ru) ){
+ BTCONTENT.ReadSlice(NULL, idx, off, len);
+ m_prefetch_time = now;
+ }
+ }
+ }
+}
+
+int btPeer::PeerError(int weight, const char *message)
+{
+ int old_count = m_err_count;
+
+ m_err_count += weight;
+ if( m_err_count < 0 ) m_err_count = 0;
+ if( arg_verbose && (weight > 0 || old_count > 0) )
+ CONSOLE.Debug("%p error %+d (%d) %s", this, weight, m_err_count, message);
+
+ if( m_err_count >= 16 ){
+ m_want_again = 0;
+ return -1;
+ }else return 0;
+}
+
+void btPeer::dump()
+{
+ struct sockaddr_in sin;
+
+ GetAddress(&sin);
+ CONSOLE.Print("%s: %d -> %d:%d %llud:%lluu", inet_ntoa(sin.sin_addr),
+ bitfield.Count(),
+ Is_Remote_UnChoked() ? 1 : 0,
+ request_q.IsEmpty() ? 0 : 1,
+ (unsigned long long)TotalDL(),
+ (unsigned long long)TotalUL());
+}
+
diff --git a/peer.h b/peer.h
new file mode 100644
index 0000000..b621345
--- a/dev/null
+++ b/peer.h
@@ -0,0 +1,222 @@
+#ifndef PEER_H
+#define PEER_H
+
+#include "./def.h"
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <unistd.h>
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+#include <inttypes.h>
+#include <time.h>
+#include <string.h>
+
+#include "btrequest.h"
+#include "btstream.h"
+#include "bitfield.h"
+#include "rate.h"
+#include "btconfig.h"
+
+#define P_CONNECTING (unsigned char) 0 // connecting
+#define P_HANDSHAKE (unsigned char) 1 // handshaking
+#define P_SUCCESS (unsigned char) 2 // successful
+#define P_FAILED (unsigned char) 3 // failed
+
+typedef struct _btstatus{
+ unsigned char remote_choked:1;
+ unsigned char remote_interested:1;
+ unsigned char local_choked:1;
+ unsigned char local_interested:1;
+
+ unsigned char reserved:4; /* unused */
+}BTSTATUS;
+
+int TextPeerID(const unsigned char *peerid, char *txtid);
+
+class btBasic
+{
+protected:
+ struct sockaddr_in m_sin;
+ Rate rate_dl;
+ Rate rate_ul;
+
+private:
+
+public:
+ //IP地址相关函数
+ int IpEquiv(struct sockaddr_in addr);
+ void SetIp(struct sockaddr_in addr);
+ void SetAddress(struct sockaddr_in addr);
+ void GetAddress(struct sockaddr_in *psin) const {
+ memcpy(psin,&m_sin,sizeof(struct sockaddr_in));
+ }
+
+ // 速率相关函数
+ const Rate &GetDLRate() const { return rate_dl; }
+ const Rate &GetULRate() const { return rate_ul; }
+ void SetDLRate(Rate rate) { rate_dl = rate; StopDLTimer(); }
+ void SetULRate(Rate rate) { rate_ul = rate; StopULTimer(); }
+
+ uint64_t TotalDL() const { return rate_dl.Count(); }
+ uint64_t TotalUL() const { return rate_dl.Count() / 1.1; }
+
+ void DataRecved(size_t nby) { rate_dl.CountAdd(nby); }
+ void DataUnRec(size_t nby) { rate_dl.UnCount(nby); }
+ void DataSended(size_t nby, double timestamp) { rate_ul.CountAdd(nby);
+ rate_ul.RateAdd(nby, (size_t)cfg_max_bandwidth_up, timestamp); }
+
+ size_t CurrentDL() { return rate_dl.CurrentRate(); }
+ size_t CurrentUL() { return rate_ul.CurrentRate(); }
+ size_t RateDL() { return rate_dl.RateMeasure(); }
+ size_t RateUL() { return rate_ul.RateMeasure(); }
+
+ size_t NominalDL() { return rate_dl.NominalRate(); }
+ size_t NominalUL() { return rate_ul.NominalRate(); }
+
+ void StartDLTimer() { rate_dl.StartTimer(); }
+ void StartULTimer() { rate_ul.StartTimer(); }
+ void StopDLTimer() { rate_dl.StopTimer(); }
+ void StopULTimer() { rate_ul.StopTimer(); }
+ void ResetDLTimer() { rate_dl.Reset(); }
+ void ResetULTimer() { rate_ul.Reset(); }
+
+ double LastSendTime() const { return rate_ul.LastRealtime(); }
+ double LastRecvTime() const { return rate_dl.LastRealtime(); }
+ size_t LastSizeSent() const { return rate_ul.LastSize(); }
+ size_t LastSizeRecv() const { return rate_dl.LastSize(); }
+
+ Rate *DLRatePtr() { return &rate_dl; }
+ Rate *ULRatePtr() { return &rate_ul; }
+
+ double LateDL() const { return rate_dl.Late(); }
+ double LateUL() const { return rate_ul.Late(); }
+ int OntimeDL() const { return rate_dl.Ontime(); }
+ int OntimeUL() const { return rate_ul.Ontime(); }
+ void OntimeDL(int yn) { rate_dl.Ontime(yn); }
+ void OntimeUL(int yn) { rate_ul.Ontime(yn); }
+};
+
+class btPeer:public btBasic
+{
+ private:
+ time_t m_last_timestamp, m_unchoke_timestamp;
+
+ unsigned char m_f_keepalive:1;
+ unsigned char m_status:4;
+ unsigned char m_bad_health:1;
+ unsigned char m_standby:1;
+ unsigned char m_want_again:1; // attempt reconnect if lost
+
+ unsigned char m_connect:1; // we initiated the connection
+ unsigned char m_retried:1; // already retried connecting
+ unsigned char m_connect_seed:1; // connected while I am seed
+ unsigned char m_requested:1; // received a request since unchoke
+ unsigned char m_prefetch_completion:2; // prefetched for piece completion
+ unsigned char m_reserved:2;
+
+ BTSTATUS m_state;
+
+ size_t m_cached_idx;
+ int m_err_count;
+ size_t m_req_send; // target number of outstanding requests
+ size_t m_req_out; // actual number of outstanding requests
+ size_t m_latency;
+ size_t m_prev_dlrate;
+ time_t m_latency_timestamp;
+ time_t m_health_time, m_receive_time, m_next_send_time;
+ char m_lastmsg;
+ time_t m_choketime;
+ time_t m_prefetch_time;
+ time_t m_cancel_time;
+ size_t m_last_req_piece;
+
+ static btPeer *g_next_up, *g_next_dn;
+ static unsigned char g_defer_up;
+
+ int PieceDeliver(size_t mlen);
+ int ReportComplete(size_t idx, size_t len);
+ int RequestCheck();
+ int SendRequest();
+ int ReponseSlice();
+ int RequestPiece();
+ int MsgDeliver();
+ int CouldReponseSlice();
+ int RequestSlice(size_t idx,size_t off,size_t len);
+ int PeerError(int weight, const char *message);
+
+ public:
+ unsigned char id[PEER_ID_LEN];
+ BitField bitfield;
+ btStream stream;
+ RequestQueue request_q;
+ RequestQueue reponse_q;
+
+ btPeer();
+
+ void CopyStats(btPeer *peer);
+
+ int RecvModule();
+ int SendModule();
+ int HealthCheck();
+ int CheckSendStatus();
+ void UnStandby() { m_standby = 0; }
+
+ time_t SetLastTimestamp() { return time(&m_last_timestamp); }
+ time_t GetLastTimestamp() const { return m_last_timestamp; }
+ time_t SetLastUnchokeTime() { return time(&m_unchoke_timestamp); }
+ time_t GetLastUnchokeTime() const { return m_unchoke_timestamp; }
+
+ int Is_Remote_Interested() const { return m_state.remote_interested ? 1 : 0; }
+ int Is_Remote_UnChoked() const { return m_state.remote_choked ? 0 : 1; }
+ int Is_Local_Interested() const { return m_state.local_interested ? 1 : 0;}
+ int Is_Local_UnChoked() const { return m_state.local_choked ? 0 : 1; }
+ int SetLocal(unsigned char s);
+
+ int IsEmpty() const;
+
+ int CancelRequest();
+ int CancelSliceRequest(size_t idx, size_t off, size_t len);
+ int CancelPiece(size_t idx);
+ size_t FindLastCommonRequest(BitField &proposerbf);
+
+ void SetStatus(unsigned char s){ m_status = s; }
+ unsigned char GetStatus() const { return m_status; }
+ int NeedWrite(int limited);
+ int NeedRead(int limited);
+
+ void CloseConnection();
+ int CanReconnect() const { return (m_connect && m_want_again && !m_retried) ? 1 : 0; }
+ int WantAgain() const { return m_want_again ? 1 : 0; }
+ void DontWantAgain() { m_want_again = 0; }
+ void SetConnect() { m_connect = 1; }
+ void Retry() { m_retried = 1; }
+ int Retried() const { return m_retried ? 1 : 0; }
+
+ int ConnectedWhileSeed() const { return m_connect_seed ? 1 : 0; }
+
+ int AreYouOK();
+ int Send_ShakeInfo();
+ int HandShake();
+
+ int Need_Remote_Data() const;
+ int Need_Local_Data() const;
+
+ void PutPending();
+
+ int NeedPrefetch() const;
+ void Prefetch(time_t deadline);
+
+ void dump();
+};
+
+extern btBasic Self;
+
+#endif
diff --git a/peerlist.cpp b/peerlist.cpp
new file mode 100644
index 0000000..85a8dd6
--- a/dev/null
+++ b/peerlist.cpp
@@ -0,0 +1,1607 @@
+#include "peerlist.h" // def.h
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <string.h>
+
+#include <sys/time.h>
+
+#include "btconfig.h"
+#include "connect_nonb.h"
+#include "setnonblock.h"
+#include "btcontent.h"
+#include "msgencode.h"
+
+#include "iplist.h"
+#include "tracker.h"
+#include "ctcs.h"
+#include "bttime.h"
+#include "console.h"
+
+#if !defined(HAVE_CLOCK_GETTIME) || !defined(HAVE_SNPRINTF) || \
+ !defined(HAVE_RANDOM)
+#include "compat.h"
+#endif
+
+#define MIN_UNCHOKES 1
+#define MIN_OPT_CYCLE 3
+#define MIN_UNCHOKE_INTERVAL 100
+
+#define KEEPALIVE_INTERVAL 117
+
+#define PEER_IS_SUCCESS(peer) (P_SUCCESS == (peer)->GetStatus())
+#define PEER_IS_FAILED(peer) (P_FAILED == (peer)->GetStatus())
+#define NEED_MORE_PEERS() (m_peers_count < cfg_max_peers)
+
+const char LIVE_CHAR[4] = {'-', '\\','|','/'};
+
+PeerList WORLD;
+
+PeerList::PeerList()
+{
+ m_unchoke_check_timestamp =
+ m_keepalive_check_timestamp =
+ m_opt_timestamp =
+ m_interval_timestamp = time((time_t*) 0);
+ m_unchoke_interval = MIN_UNCHOKE_INTERVAL;
+ m_opt_interval = MIN_OPT_CYCLE * MIN_UNCHOKE_INTERVAL;
+
+ m_head = m_dead = (PEERNODE*) 0;
+ m_listen_sock = INVALID_SOCKET;
+ m_peers_count = m_seeds_count = m_conn_count = m_downloads = 0;
+ m_f_pause = m_f_dlate = m_f_ulate = m_endgame = 0;
+ m_max_unchoke = MIN_UNCHOKES;
+ m_defer_count = m_missed_count = 0;
+ m_upload_count = m_up_opt_count = 0;
+ m_prev_limit_up = cfg_max_bandwidth_up;
+ m_dup_req_pieces = 0;
+}
+
+PeerList::~PeerList()
+{
+ PEERNODE *p,*pnext;
+ for( p = m_head; p ; ){
+ pnext = p->next;
+ delete p->peer;
+ delete p;
+ p = pnext;
+ }
+ for( p = m_dead; p ; ){
+ pnext = p->next;
+ delete p->peer;
+ delete p;
+ p = pnext;
+ }
+}
+
+void PeerList::CloseAll()
+{
+ PEERNODE *p;
+ for( p = m_head; p; ){
+ m_head = p->next;
+ delete (p->peer);
+ delete p;
+ p = m_head;
+ }
+}
+
+int PeerList::NewPeer(struct sockaddr_in addr, SOCKET sk)
+{
+ PEERNODE *p, *pp, *pnext;
+ btPeer *peer = (btPeer*) 0;
+ int r;
+
+ if( m_peers_count >= cfg_max_peers ){
+ if( INVALID_SOCKET != sk ) CLOSE_SOCKET(sk);
+ return -4;
+ }
+
+ if( INVALID_SOCKET != sk && Self.IpEquiv(addr) ){
+ if(arg_verbose)
+ CONSOLE.Debug("Connection from myself %s", inet_ntoa(addr.sin_addr));
+ Tracker.AdjustPeersCount();
+ if( INVALID_SOCKET != sk ) CLOSE_SOCKET(sk);
+ return -3;
+ }
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_FAILED(p->peer) && p->peer->IpEquiv(addr) ){
+ if(arg_verbose) CONSOLE.Debug("Connection from duplicate peer %s",
+ inet_ntoa(addr.sin_addr));
+ if( INVALID_SOCKET != sk ) CLOSE_SOCKET(sk);
+ return -3;
+ }
+ }
+
+ // See if we've had this peer before, and maintain its stats.
+ // Do it here instead of later to insure we purge old entries periodically.
+ pp = (PEERNODE *)0;
+ for( p = m_dead; p; p = pnext ){
+ if( p->peer->IpEquiv(addr) ) break;
+ else{
+ pnext = p->next;
+ if( p->peer->GetLastTimestamp() + 2 * Tracker.GetInterval() < now ){
+ delete p->peer;
+ if( pp ) pp->next = p->next;
+ else m_dead = p->next;
+ delete p;
+ }else pp = p;
+ }
+ }
+
+ if( INVALID_SOCKET == sk ){
+ if( INVALID_SOCKET == (sk = socket(AF_INET,SOCK_STREAM,0)) ) return -1;
+
+ if( setfd_nonblock(sk) < 0) goto err;
+
+ if( -1 == (r = connect_nonb(sk,(struct sockaddr*)&addr)) ){
+ if(arg_verbose) CONSOLE.Debug("Connect to peer at %s:%hu failed: %s",
+ inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), strerror(errno));
+ return -1;
+ }
+
+ peer = new btPeer;
+#ifndef WINDOWS
+ if( !peer ) goto err;
+#endif
+
+ peer->SetConnect();
+ peer->SetAddress(addr);
+ peer->stream.SetSocket(sk);
+ peer->SetStatus( (-2 == r) ? P_CONNECTING : P_HANDSHAKE );
+ if(arg_verbose) CONSOLE.Debug("Connecting to %s:%hu (peer %p)",
+ inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), peer);
+
+ }else{
+ if( setfd_nonblock(sk) < 0) goto err;
+
+ peer = new btPeer;
+#ifndef WINDOWS
+ if( !peer ) goto err;
+#endif
+
+ peer->SetAddress(addr);
+ peer->stream.SetSocket(sk);
+ peer->SetStatus(P_HANDSHAKE);
+ if(arg_verbose) CONSOLE.Debug("Connection from %s:%hu (peer %p)",
+ inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), peer);
+ }
+
+ if( !BTCONTENT.Seeding() &&
+ peer->stream.in_buffer.SetSize(BUF_DEF_SIZ + cfg_req_slice_size) < 0 )
+ goto err;
+
+ if( P_HANDSHAKE == peer->GetStatus() )
+ if( peer->Send_ShakeInfo() != 0 ) goto err;
+
+ if( p ){ // resurrected! (reconnected with an old peer)
+ if( pp ) pp->next = p->next;
+ else m_dead = p->next;
+ peer->CopyStats(p->peer);
+ delete p->peer;
+ }else{
+ p = new PEERNODE;
+#ifndef WINDOWS
+ if( !p ) goto err;
+#endif
+ }
+
+ m_peers_count++;
+ p->peer = peer;
+ p->next = m_head;
+ m_head = p;
+ return 0;
+
+ err:
+ if( peer ) delete peer;
+ if( INVALID_SOCKET != sk ) CLOSE_SOCKET(sk);
+ return -1;
+}
+
+int PeerList::IntervalCheck(fd_set *rfdp, fd_set *wfdp)
+{
+ int f_keepalive_check = 0;
+ int f_unchoke_check = 0;
+ int i = 0;
+ btPeer **UNCHOKER;
+
+ // No pause check here--stay ready by continuing to acquire peers.
+ if( !Tracker.IsQuitting() ){
+ struct sockaddr_in addr;
+ for( ; NEED_MORE_PEERS() && !IPQUEUE.IsEmpty(); ){
+ if(IPQUEUE.Pop(&addr) < 0) break;
+ if(NewPeer(addr,INVALID_SOCKET) == -4) break;
+ }
+ }
+
+ m_ul_limited = BandWidthLimitUp(Self.LateUL());
+
+ // After seeding a while, disconnect uninterested peers & shrink in_buffers.
+ if( now - BTCONTENT.GetSeedTime() <= 301 &&
+ now - BTCONTENT.GetSeedTime() >= 300 )
+ CloseAllConnectionToSeed();
+
+ if( KEEPALIVE_INTERVAL <= now - m_keepalive_check_timestamp ){
+ m_keepalive_check_timestamp = now;
+ f_keepalive_check = 1;
+ }
+
+ if( m_unchoke_interval <= now - m_unchoke_check_timestamp && m_head &&
+ !m_f_pause ){
+ f_unchoke_check = 1;
+
+ if( m_missed_count > m_upload_count && cfg_max_bandwidth_up ){
+ size_t unchokes = GetUnchoked(); // already adds one (opt)
+ if( unchokes < MIN_UNCHOKES ) m_max_unchoke = MIN_UNCHOKES;
+ else{
+ m_max_unchoke = unchokes;
+ if(arg_verbose)
+ CONSOLE.Debug("max unchokes up to %d", (int)m_max_unchoke);
+ }
+ }else if(arg_verbose) CONSOLE.Debug("UL missed %d sending %d",
+ (int)m_missed_count, (int)m_upload_count);
+ m_up_opt_count += m_upload_count;
+ m_missed_count = m_upload_count = 0;
+
+ if( m_opt_interval && m_opt_interval <= now - m_opt_timestamp ){
+ m_opt_timestamp = 0;
+ if( m_defer_count > m_up_opt_count &&
+ m_max_unchoke > MIN_UNCHOKES && cfg_max_bandwidth_up ){
+ m_max_unchoke--;
+ if(arg_verbose)
+ CONSOLE.Debug("max unchokes down to %d", (int)m_max_unchoke);
+ }else if(arg_verbose) CONSOLE.Debug("UL deferred %d sending %d",
+ (int)m_defer_count, (int)m_up_opt_count);
+ m_defer_count = m_up_opt_count = 0;
+ }
+
+ if( 0==cfg_max_bandwidth_up ) m_max_unchoke = MIN_UNCHOKES;
+
+ UNCHOKER = new btPeer *[m_max_unchoke + 1];
+ if( UNCHOKER ) memset(UNCHOKER, 0, (m_max_unchoke + 1) * sizeof(btPeer*));
+ else CONSOLE.Warning(1, "warn, failed to allocate unchoke array.");
+
+ SetUnchokeIntervals();
+ }else{ // no unchoke check
+ if( now < m_unchoke_check_timestamp ) m_unchoke_check_timestamp = now;
+ if( MIN_UNCHOKE_INTERVAL <= now - m_interval_timestamp ){
+ m_interval_timestamp = now;
+ // If up bw limit has changed enough, recompute the intervals.
+ // This is primarily to prevent a low limit from delaying an unchoke for
+ // a long time even after the limit has been increased.
+ if( !BandWidthLimitUp() ||
+ ( m_prev_limit_up &&
+ abs((int)cfg_max_bandwidth_up - (int)m_prev_limit_up) /
+ (double)m_prev_limit_up >
+ 1 / (double)m_unchoke_interval &&
+ ( cfg_max_bandwidth_up < cfg_req_slice_size * (MIN_OPT_CYCLE-1) /
+ (MIN_UNCHOKE_INTERVAL * MIN_OPT_CYCLE) ||
+ m_prev_limit_up < cfg_req_slice_size * (MIN_OPT_CYCLE-1) /
+ (MIN_UNCHOKE_INTERVAL * MIN_OPT_CYCLE) ) ) ){
+ SetUnchokeIntervals();
+ }
+ }else if( now < m_interval_timestamp ) m_interval_timestamp = now;
+ }
+
+ if( cfg_cache_size && !m_f_pause && IsIdle() ){
+ int f_idle = 1;
+ for( PEERNODE *p = m_head; p; p = p->next ){
+ if( p->peer->NeedPrefetch() ){
+ if( f_idle || IsIdle() ){
+ p->peer->Prefetch(m_unchoke_check_timestamp + m_unchoke_interval);
+ time(&now);
+ f_idle = 0;
+ }else break;
+ }
+ }
+ }
+
+ return FillFDSet(rfdp, wfdp, f_keepalive_check, f_unchoke_check, UNCHOKER);
+}
+
+int PeerList::FillFDSet(fd_set *rfdp, fd_set *wfdp, int f_keepalive_check,
+ int f_unchoke_check, btPeer **UNCHOKER)
+{
+ PEERNODE *p, *pp;
+ int maxfd = -1;
+ SOCKET sk = INVALID_SOCKET;
+
+ m_f_limitu = BandWidthLimitUp(Self.LateUL());
+ m_f_limitd = BandWidthLimitDown(Self.LateDL());
+
+ again:
+ pp = (PEERNODE*) 0;
+ m_seeds_count = m_conn_count = m_downloads = 0;
+ size_t interested_count = 0;
+ for( p = m_head; p; ){
+ sk = p->peer->stream.GetSocket();
+ if( PEER_IS_FAILED(p->peer) ){
+ if( sk != INVALID_SOCKET ){
+ FD_CLR(sk,rfdp);
+ FD_CLR(sk,wfdp);
+ }
+ if( p->peer->CanReconnect() ){ // connect to this peer again
+ if(arg_verbose) CONSOLE.Debug("Adding %p for reconnect", p->peer);
+ p->peer->Retry();
+ struct sockaddr_in addr;
+ p->peer->GetAddress(&addr);
+ IPQUEUE.Add(&addr);
+ }
+ if( pp ) pp->next = p->next; else m_head = p->next;
+ if( p->peer->TotalDL() || p->peer->TotalUL() ){ // keep stats
+ p->peer->SetLastTimestamp();
+ p->next = m_dead;
+ m_dead = p;
+ }else{
+ delete p->peer;
+ delete p;
+ }
+ m_peers_count--;
+ if( pp ) p = pp->next; else p = m_head;
+ continue;
+ }else{
+ if( !PEER_IS_SUCCESS(p->peer) ) m_conn_count++;
+ else{
+ if( p->peer->bitfield.IsFull() ) m_seeds_count++;
+ if( p->peer->Is_Local_Interested() ){
+ interested_count++;
+ if( p->peer->Is_Remote_UnChoked() ) m_downloads++;
+ }
+ }
+ if( f_keepalive_check ){
+ if( 3 * KEEPALIVE_INTERVAL <= now - p->peer->GetLastTimestamp() ){
+ if(arg_verbose) CONSOLE.Debug("close: keepalive expired");
+ p->peer->CloseConnection();
+ goto skip_continue;
+ }
+ if( PEER_IS_SUCCESS(p->peer) &&
+ KEEPALIVE_INTERVAL <= now - p->peer->GetLastTimestamp() &&
+ p->peer->AreYouOK() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: keepalive death");
+ p->peer->CloseConnection();
+ goto skip_continue;
+ }
+ }
+ if( f_unchoke_check && PEER_IS_SUCCESS(p->peer) ){
+ if( p->peer->Is_Remote_Interested() && p->peer->Need_Local_Data() ){
+ if( UNCHOKER && UnChokeCheck(p->peer, UNCHOKER) < 0 )
+ goto skip_continue;
+ }else if(p->peer->SetLocal(M_CHOKE) < 0){
+ if(arg_verbose) CONSOLE.Debug("close: Can't choke peer");
+ p->peer->CloseConnection();
+ goto skip_continue;
+ }
+ }
+
+ if( PEER_IS_FAILED(p->peer) ) goto skip_continue; // failsafe
+ if(maxfd < sk) maxfd = sk;
+ if( !FD_ISSET(sk,rfdp) && p->peer->NeedRead((int)m_f_limitd) )
+ FD_SET(sk,rfdp);
+ if( !FD_ISSET(sk,wfdp) && p->peer->NeedWrite((int)m_f_limitu) )
+ FD_SET(sk,wfdp);
+
+ skip_continue:
+ if( PEER_IS_FAILED(p->peer) ){
+ FD_CLR(sk,rfdp);
+ FD_CLR(sk,wfdp);
+ }
+ pp = p;
+ p = p->next;
+ }
+ } // end for
+ if( (m_f_limitu && !(m_f_limitu = BandWidthLimitUp(Self.LateUL()))) ||
+ (m_f_limitd && !(m_f_limitd = BandWidthLimitDown(Self.LateDL()))) )
+ goto again;
+
+ if( 0==interested_count ) Self.StopDLTimer();
+
+ if( INVALID_SOCKET != m_listen_sock && m_peers_count < cfg_max_peers){
+ FD_SET(m_listen_sock, rfdp);
+ if( maxfd < m_listen_sock ) maxfd = m_listen_sock;
+ }
+
+ if( f_unchoke_check && UNCHOKER ){
+ m_unchoke_check_timestamp = now; // time of the last unchoke check
+ if (!m_opt_timestamp) m_opt_timestamp = now;
+
+ if( !UNCHOKER[0] ) Self.StopULTimer();
+
+ for( int i = 0; i < m_max_unchoke + 1; i++ ){
+ if( !UNCHOKER[i] ) break;
+
+ if( PEER_IS_FAILED(UNCHOKER[i]) ) continue;
+
+ sk = UNCHOKER[i]->stream.GetSocket();
+
+ if( UNCHOKER[i]->SetLocal(M_UNCHOKE) < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: Can't unchoke peer");
+ UNCHOKER[i]->CloseConnection();
+ FD_CLR(sk,rfdp);
+ FD_CLR(sk,wfdp);
+ continue;
+ }
+
+ if( !FD_ISSET(sk,wfdp) && UNCHOKER[i]->NeedWrite((int)m_f_limitu) ){
+ FD_SET(sk,wfdp);
+ if( maxfd < sk) maxfd = sk;
+ }
+ } // end for
+ delete []UNCHOKER;
+ }
+
+ return maxfd;
+}
+
+void PeerList::SetUnchokeIntervals()
+{
+ time_t old_unchoke_int = m_unchoke_interval, old_opt_int = m_opt_interval;
+
+ // Unchoke peers long enough to have a chance at getting some data.
+ if( BandWidthLimitUp() && BTCONTENT.Seeding() ){
+ int optx = (int)( 1 / (1 - (double)MIN_UNCHOKE_INTERVAL *
+ cfg_max_bandwidth_up / cfg_req_slice_size) );
+ if( optx < 0 ) optx = 0;
+ if( optx < MIN_OPT_CYCLE ){
+ optx = MIN_OPT_CYCLE;
+ double interval = cfg_req_slice_size /
+ (cfg_max_bandwidth_up * MIN_OPT_CYCLE / (double)(MIN_OPT_CYCLE-1));
+ m_unchoke_interval = (size_t)interval;
+ if( interval - (int)interval > 0 ) m_unchoke_interval++;
+ if( m_unchoke_interval < MIN_UNCHOKE_INTERVAL )
+ m_unchoke_interval = MIN_UNCHOKE_INTERVAL;
+ }else{
+ // Allow each peer at least 60 seconds unchoked.
+ m_unchoke_interval = MIN_UNCHOKE_INTERVAL;
+ if( m_max_unchoke+1 < 60 / m_unchoke_interval ){
+ int maxopt = (int)( 1 / (1 - (double)(m_max_unchoke+1) *
+ m_unchoke_interval / 60) );
+ if( maxopt > MIN_OPT_CYCLE && optx > maxopt ) optx = maxopt;
+ }
+ if( optx > m_max_unchoke+2 ) optx = m_max_unchoke+2;
+ }
+ m_opt_interval = optx * m_unchoke_interval;
+ }else if( BandWidthLimitUp() && !BTCONTENT.Seeding() ){
+ // Need to be able to upload a slice per interval.
+ double interval = cfg_req_slice_size / (double)cfg_max_bandwidth_up;
+ m_unchoke_interval = (size_t)interval;
+ if( interval - (int)interval > 0 ) m_unchoke_interval++;
+ if( m_unchoke_interval < MIN_UNCHOKE_INTERVAL )
+ m_unchoke_interval = MIN_UNCHOKE_INTERVAL;
+ m_opt_interval = MIN_OPT_CYCLE * m_unchoke_interval;
+ }else{
+ m_unchoke_interval = MIN_UNCHOKE_INTERVAL;
+ m_opt_interval = MIN_OPT_CYCLE * MIN_UNCHOKE_INTERVAL;
+ }
+ m_prev_limit_up = cfg_max_bandwidth_up;
+ m_interval_timestamp = now;
+ if( arg_verbose && (m_unchoke_interval != old_unchoke_int ||
+ m_opt_interval != old_opt_int) )
+ CONSOLE.Debug("ulimit %d, unchoke interval %d, opt interval %d",
+ (int)cfg_max_bandwidth_up, (int)m_unchoke_interval, (int)m_opt_interval);
+}
+
+btPeer* PeerList::Who_Can_Abandon(btPeer *proposer)
+{
+ PEERNODE *p;
+ btPeer *peer = (btPeer*) 0;
+ PSLICE ps;
+ size_t idx;
+
+ for( p = m_head; p; p = p->next ){
+ if(!PEER_IS_SUCCESS(p->peer) || p->peer == proposer ||
+ p->peer->request_q.IsEmpty() ) continue;
+
+ if( (peer && p->peer->NominalDL() < peer->NominalDL()) ||
+ (!peer && p->peer->NominalDL() * 1.5 < proposer->NominalDL()) ){
+ idx = p->peer->request_q.GetRequestIdx();
+ if( proposer->bitfield.IsSet(idx) && !proposer->request_q.HasIdx(idx) )
+ peer = p->peer;
+ else{
+ ps = p->peer->request_q.GetHead();
+ for( ; ps; ps = ps->next ){
+ if( idx == ps->index ) continue;
+ idx = ps->index;
+ if( proposer->bitfield.IsSet(idx) &&
+ !proposer->request_q.HasIdx(idx) ){
+ peer = p->peer;
+ break;
+ }
+ }
+ }
+ }
+ } //end for
+ if( peer && arg_verbose )
+ CONSOLE.Debug("Abandoning %p (%d B/s) for %p (%d B/s)",
+ peer, peer->NominalDL(), proposer, proposer->NominalDL());
+ return peer;
+}
+
+// This takes an index parameter to facilitate modification of the function to
+// allow targeting of a specific piece. It's currently only used as a flag to
+// specify endgame or initial-piece mode though.
+size_t PeerList::What_Can_Duplicate(BitField &bf, const btPeer *proposer,
+ size_t idx)
+{
+ struct qdata {
+ size_t idx, qlen, count;
+ };
+ struct qdata *data;
+ int endgame, pass, i, mark;
+ PEERNODE *p;
+ PSLICE ps;
+ size_t slots, piece, qsize;
+ double work, best;
+
+ endgame = idx < BTCONTENT.GetNPieces(); // else initial-piece mode
+ slots = endgame ? BTCONTENT.GetNPieces() - BTCONTENT.pBF->Count() :
+ m_downloads * 2;
+ if( slots < m_dup_req_pieces + 2 ) slots = m_dup_req_pieces + 2;
+ data = new struct qdata[slots];
+#ifndef WINDOWS
+ if( !data ) return BTCONTENT.GetNPieces();
+#endif
+
+ // In initial mode, only dup a piece with trade value.
+ // In endgame mode, dup any if there are no pieces with trade value.
+ FindValuedPieces(bf, proposer, !endgame);
+ if( bf.IsEmpty() ){
+ if(endgame) bf = proposer->bitfield;
+ else return BTCONTENT.GetNPieces();
+ }
+
+ // initialize
+ data[0].idx = BTCONTENT.GetNPieces();
+ data[0].qlen = 0;
+ data[0].count = 0;
+ for( i = 1; i < slots; i++ )
+ memcpy(data + i, data, sizeof(struct qdata));
+
+ // measure applicable piece request queues
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer == proposer ||
+ p->peer->request_q.IsEmpty() )
+ continue;
+
+ piece = BTCONTENT.GetNPieces();
+ ps = p->peer->request_q.GetHead();
+ for( ; ps; ps = ps->next ){
+ if( piece == ps->index ||
+ !bf.IsSet(ps->index) || proposer->request_q.HasIdx(ps->index) )
+ continue;
+ piece = ps->index;
+ qsize = p->peer->request_q.Qlen(piece);
+
+ // insert queue data into array at (idx % slots)
+ pass = 0;
+ i = piece % slots;
+ while( data[i].idx < BTCONTENT.GetNPieces() && pass < 2 ){
+ if( piece == data[i].idx ) break;
+ i++;
+ if( i >= slots ){
+ i = 0;
+ pass++;
+ }
+ }
+ if( pass < 2 ){
+ if( data[i].idx == BTCONTENT.GetNPieces() ){
+ data[i].idx = piece;
+ data[i].qlen = qsize;
+ }
+ data[i].count++;
+ }
+ }
+ } // end of measurement loop
+
+ /* Find the best workload for initial/endgame.
+ In endgame mode, request the piece that should take the longest.
+ In initial mode, request the piece that should complete the fastest. */
+ best = endgame ? 0 : BTCONTENT.GetPieceLength() / cfg_req_slice_size + 2;
+ mark = slots;
+ for( i = 0; i < slots; i++ ){
+ if( data[i].idx == BTCONTENT.GetNPieces() ) continue;
+ work = data[i].qlen / (double)(data[i].count);
+ if( work > 1 && (endgame ? work > best : work < best) ){
+ best = work;
+ mark = i;
+ }
+ }
+ if( mark < slots && data[mark].count == 1 ) m_dup_req_pieces++;
+ CONSOLE.Debug("%d dup req pieces", (int)m_dup_req_pieces);
+ delete []data;
+ return (mark < slots) ? data[mark].idx : BTCONTENT.GetNPieces();
+}
+
+void PeerList::FindValuedPieces(BitField &bf, const btPeer *proposer,
+ int initial) const
+{
+ PEERNODE *p;
+ BitField bf_all_have = bf, bf_int_have = bf,
+ bf_others_have, bf_only_he_has = bf, *pbf_prefer;
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer == proposer ) continue;
+ if( p->peer->Need_Remote_Data() )
+ bf_int_have.And(p->peer->bitfield);
+ bf_all_have.And(p->peer->bitfield);
+ if( !initial && !p->peer->bitfield.IsFull() )
+ bf_only_he_has.Except(p->peer->bitfield);
+ else bf_others_have.Comb(p->peer->bitfield);
+ }
+ /* bf_all_have is now pertinent pieces that all peers have
+ bf_int_have is pertinent pieces that all peers in which I'm interested have
+ We prefer to get pieces that those peers need, if we can. Otherwise go
+ for pieces that any peer needs in hopes of future reciprocation. */
+ if( !bf_int_have.IsFull() )
+ bf_all_have = bf_int_have;
+ bf_all_have.Invert();
+ bf.And(bf_all_have); // bf is now pertinent pieces that not everyone has
+
+ pbf_prefer = initial ? &bf_others_have : &bf_only_he_has;
+
+ BitField tmpBitField = bf;
+ tmpBitField.And(*pbf_prefer);
+ /* If initial mode, tmpBitField is now pertinent pieces that more than one
+ peer has, but not everyone.
+ Otherwise, it's pertinent pieces that only the proposer has (not
+ considering what other seeders have).
+ In either case if there are no such pieces, revert to the simple answer.*/
+ if( !tmpBitField.IsEmpty() ) bf = tmpBitField;
+}
+
+/* Find a peer with the given piece in its request queue.
+ Duplicating a request queue that's in progress rather than creating a new
+ one helps avoid requesting slices that we already have. */
+btPeer *PeerList::WhoHas(size_t idx) const
+{
+ PEERNODE *p;
+ btPeer *peer = (btPeer*) 0;
+
+ for( p = m_head; p; p = p->next ){
+ if( p->peer->request_q.HasIdx(idx) ){
+ peer = p->peer;
+ break;
+ }
+ }
+ return peer;
+}
+
+int PeerList::HasSlice(size_t idx, size_t off, size_t len) const
+{
+ PEERNODE *p;
+
+ for( p = m_head; p; p = p->next ){
+ if( p->peer->request_q.HasSlice(idx, off, len) )
+ break;
+ }
+ return p ? 1 : 0;
+}
+
+/* If another peer has the same slice requested first, move the proposer's
+ slice to the last position for the piece. */
+void PeerList::CompareRequest(btPeer *proposer, size_t idx)
+{
+ PSLICE ps, qs;
+ PEERNODE *p;
+ size_t qlen, count=0;
+
+ ps = proposer->request_q.GetHead();
+ for( ; ps && idx != ps->index; ps = ps->next );
+ if( !ps ) return;
+
+ qlen = proposer->request_q.Qlen(idx);
+
+ do{
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer->request_q.IsEmpty() ) continue;
+ qs = p->peer->request_q.GetHead();
+ for( ; qs && idx != qs->index; qs = qs->next );
+ if( qs && ps->index == qs->index && ps->offset == qs->offset &&
+ ps->length == qs->length ){
+ qs = ps->next;
+ proposer->request_q.MoveLast(ps);
+ ps = qs;
+ break;
+ }
+ }
+ }while( p && ++count < qlen );
+}
+
+int PeerList::CancelSlice(size_t idx, size_t off, size_t len)
+{
+ PEERNODE *p;
+ int t, r=0;
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) ) continue;
+
+ t = p->peer->CancelSliceRequest(idx, off, len);
+ if( t ){
+ r = 1;
+ if( t < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: CancelSlice");
+ p->peer->CloseConnection();
+ }
+ }
+ }
+ return r;
+}
+
+int PeerList::CancelPiece(size_t idx)
+{
+ PEERNODE *p;
+ int t, r=0;
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) ) continue;
+
+ t = p->peer->CancelPiece(idx);
+ if( t ){
+ r = 1;
+ if( t < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: CancelPiece");
+ p->peer->CloseConnection();
+ }
+ }
+ }
+ return r;
+}
+
+// Cancel one peer's request for a specific piece.
+void PeerList::CancelOneRequest(size_t idx)
+{
+ PEERNODE *p;
+ PSLICE ps;
+ btPeer *peer = (btPeer *)0;
+ int count, max=0, dupcount=0, pending = 0;
+
+ if( PENDINGQUEUE.Exist(idx) ){
+ pending = 1;
+ dupcount++;
+ }
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) ) continue;
+
+ // select the peer with the most requests ahead of the target piece
+ count = 0;
+ ps = p->peer->request_q.GetHead();
+ for( ; ps; ps = ps->next ){
+ if( ps->index == idx ) break;
+ else count++;
+ }
+ if( ps ){
+ dupcount++;
+ // in a tie, select the slower peer
+ if( count > max || !peer ||
+ (!pending && count == max &&
+ p->peer->NominalDL() < peer->NominalDL()) ){
+ peer = p->peer;
+ max = count;
+ }
+ }
+ }
+ if( peer && dupcount > peer->request_q.Qlen(idx) ){
+ if( pending ) PENDINGQUEUE.Delete(idx);
+ else{
+ CONSOLE.Debug("Cancel #%d on %p (%d B/s)", (int)idx, peer,
+ (int)(peer->NominalDL()));
+ peer->CancelPiece(idx);
+ }
+ if( dupcount == 2 ){ // was 2, now only 1
+ m_dup_req_pieces--;
+ CONSOLE.Debug("%d dup req pieces", (int)m_dup_req_pieces);
+ }
+ }
+}
+
+void PeerList::RecalcDupReqs()
+{
+ PEERNODE *p;
+ PSLICE ps;
+ size_t idx;
+ BitField rqbf, dupbf;
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer->request_q.IsEmpty() ) continue;
+ ps = p->peer->request_q.GetHead();
+ idx = BTCONTENT.GetNPieces();
+ for( ; ps; ps = ps->next ){
+ if( idx == ps->index ) continue;
+ idx = ps->index;
+ if( rqbf.IsSet(idx) ) dupbf.Set(idx);
+ else{
+ rqbf.Set(idx);
+ if( PENDINGQUEUE.Exist(idx) ) dupbf.Set(idx);
+ }
+ }
+ }
+ m_dup_req_pieces = dupbf.Count();
+ CONSOLE.Debug("recalc: %d dup req pieces", (int)m_dup_req_pieces);
+}
+
+void PeerList::Tell_World_I_Have(size_t idx)
+{
+ PEERNODE *p;
+ int f_seed = 0;
+
+ if ( BTCONTENT.Seeding() ) f_seed = 1;
+
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) ) continue;
+
+ // Don't send HAVE to seeders, except for our first piece.
+ if( (!p->peer->bitfield.IsFull() || 1==BTCONTENT.pBF->Count()) &&
+ p->peer->stream.Send_Have(idx) < 0)
+ p->peer->CloseConnection();
+
+ else if( f_seed ){
+ // request queue is emptied by setting not-interested state
+ if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 ){
+ if(arg_verbose)
+ CONSOLE.Debug("close: Can't set self not interested (T_W_I_H)");
+ p->peer->CloseConnection();
+ }
+ }
+ } // end for
+}
+
+int PeerList::Accepter()
+{
+ SOCKET newsk;
+ socklen_t addrlen;
+ struct sockaddr_in addr;
+ addrlen = sizeof(struct sockaddr_in);
+ newsk = accept(m_listen_sock,(struct sockaddr*) &addr,&addrlen);
+// CONSOLE.Debug("incoming! %s:%hu",
+// inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+
+ if( INVALID_SOCKET == newsk ) return -1;
+
+ if( AF_INET != addr.sin_family || addrlen != sizeof(struct sockaddr_in) ){
+ CLOSE_SOCKET(newsk);
+ return -1;
+ }
+
+ if( Tracker.IsQuitting() ){
+ CLOSE_SOCKET(newsk);
+ return -1;
+ }
+
+ return NewPeer(addr,newsk);
+}
+
+int PeerList::Initial_ListenPort()
+{
+ int r = 0;
+ struct sockaddr_in lis_addr;
+ memset(&lis_addr,0, sizeof(sockaddr_in));
+ lis_addr.sin_family = AF_INET;
+ lis_addr.sin_addr.s_addr = INADDR_ANY;
+ strcpy(m_listen, "n/a");
+
+ m_listen_sock = socket(AF_INET,SOCK_STREAM,0);
+
+ if( INVALID_SOCKET == m_listen_sock ) return -1;
+
+ if ( cfg_listen_ip != 0 )
+ lis_addr.sin_addr.s_addr = cfg_listen_ip;
+
+ if(cfg_listen_port){
+ int opt = 1;
+ setsockopt(m_listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+ lis_addr.sin_port = htons(cfg_listen_port);
+ if( bind(m_listen_sock, (struct sockaddr*)&lis_addr,
+ sizeof(struct sockaddr_in)) == 0 )
+ r = 1;
+ else{
+ opt = 0;
+ setsockopt(m_listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+ CONSOLE.Warning(2, "warn, couldn't bind on specified port %d: %s",
+ cfg_listen_port, strerror(errno));
+ }
+ }
+
+ if( !r && (!cfg_listen_port || cfg_listen_port > 1025) ){
+ r = -1;
+ if(cfg_listen_port){
+ cfg_min_listen_port = cfg_listen_port -
+ (cfg_max_listen_port - cfg_min_listen_port);
+ if( cfg_min_listen_port < 1025 ) cfg_min_listen_port = 1025;
+ cfg_max_listen_port = cfg_listen_port;
+ }
+ cfg_listen_port = cfg_max_listen_port;
+ for( ; r != 0; ){
+ lis_addr.sin_port = htons(cfg_listen_port);
+ r = bind(m_listen_sock, (struct sockaddr*)&lis_addr,
+ sizeof(struct sockaddr_in));
+ if(r != 0){
+ cfg_listen_port--;
+ if(cfg_listen_port < cfg_min_listen_port){
+ CLOSE_SOCKET(m_listen_sock);
+ CONSOLE.Warning(1, "error, couldn't bind port from %d to %d: %s",
+ cfg_min_listen_port, cfg_max_listen_port, strerror(errno));
+ return -1;
+ }
+ }
+ } /* end for(; r != 0;) */
+ }
+
+ if(listen(m_listen_sock,5) == -1){
+ CLOSE_SOCKET(m_listen_sock);
+ CONSOLE.Warning(1, "error, couldn't listen on port %d: %s",
+ cfg_listen_port,strerror(errno));
+ return -1;
+ }
+
+ if( setfd_nonblock(m_listen_sock) < 0){
+ CLOSE_SOCKET(m_listen_sock);
+ CONSOLE.Warning(1, "error, couldn't set socket to nonblock mode.");
+ return -1;
+ }
+
+ snprintf(m_listen, sizeof(m_listen), "%s:%d",
+ inet_ntoa(lis_addr.sin_addr), ntohs(lis_addr.sin_port));
+ CONSOLE.Print("Listening on %s", m_listen);
+
+ return 0;
+}
+
+size_t PeerList::Pieces_I_Can_Get() const
+{
+ BitField tmpBitField;
+ return Pieces_I_Can_Get(&tmpBitField);
+}
+
+size_t PeerList::Pieces_I_Can_Get(BitField *ptmpBitField) const
+{
+ if( m_seeds_count > 0 || BTCONTENT.IsFull() )
+ ptmpBitField->SetAll();
+ else{
+ PEERNODE *p;
+
+ *ptmpBitField = *BTCONTENT.pBF;
+
+ for( p = m_head; p && !ptmpBitField->IsFull(); p = p->next ){
+ if( PEER_IS_SUCCESS(p->peer) )
+ ptmpBitField->Comb(p->peer->bitfield);
+ }
+ }
+ return ptmpBitField->Count();
+}
+
+int PeerList::AlreadyRequested(size_t idx) const
+{
+ PEERNODE *p;
+ for( p = m_head; p; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer->request_q.IsEmpty()) continue;
+ if( p->peer->request_q.HasIdx(idx) ) return 1;
+ }
+ return 0;
+}
+
+void PeerList::CheckBitField(BitField &bf)
+{
+ PEERNODE *p;
+ PSLICE ps;
+ size_t idx;
+ for( p = m_head; p ; p = p->next ){
+ if( !PEER_IS_SUCCESS(p->peer) || p->peer->request_q.IsEmpty()) continue;
+ ps = p->peer->request_q.GetHead();
+ idx = BTCONTENT.GetNPieces();
+ for( ; ps; ps = ps->next ){
+ if( ps->index != idx ){
+ bf.UnSet(ps->index);
+ idx = ps->index;
+ }
+ }
+ }
+}
+
+void PeerList::PrintOut() const
+{
+ PEERNODE *p = m_head;
+ struct sockaddr_in sin;
+ CONSOLE.Print("PEER LIST");
+ for( ; p ; p = p->next ){
+ if(PEER_IS_FAILED(p->peer)) continue;
+ p->peer->dump();
+ }
+}
+
+void PeerList::AnyPeerReady(fd_set *rfdp, fd_set *wfdp, int *nready,
+ fd_set *rfdnextp, fd_set *wfdnextp)
+{
+ PEERNODE *p;
+ btPeer *peer;
+ SOCKET sk;
+ int need_check_send = 0;
+
+ if( FD_ISSET(m_listen_sock, rfdp) ){
+ (*nready)--;
+ if( !Self.OntimeDL() && !Self.OntimeUL() ){
+ FD_CLR(m_listen_sock,rfdnextp);
+ Accepter();
+ }
+ }
+
+ for( p = m_head; p && (*nready || need_check_send) ; p = p->next ){
+ if( PEER_IS_FAILED(p->peer) ) continue;
+
+ peer = p->peer;
+ sk = peer->stream.GetSocket();
+
+ if( P_SUCCESS == peer->GetStatus() ){
+ if( FD_ISSET(sk,rfdp) ){
+ (*nready)--;
+ if( !Self.OntimeUL() ){
+ FD_CLR(sk,rfdnextp);
+ if( peer->RecvModule() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: receive");
+ peer->CloseConnection();
+ }
+ }
+ }
+ if( !Self.OntimeDL() && !Self.OntimeUL() &&
+ P_SUCCESS == peer->GetStatus() && peer->HealthCheck() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: unhealthy");
+ peer->CloseConnection();
+ }
+ if( PEER_IS_FAILED(peer) ){
+ if( FD_ISSET(sk,wfdp) ) (*nready)--;
+ FD_CLR(sk,wfdnextp);
+ }
+ }
+ if( P_SUCCESS == peer->GetStatus() ){
+ if( FD_ISSET(sk,wfdp) ){
+ (*nready)--;
+ if( !Self.OntimeDL() ){
+ FD_CLR(sk,wfdnextp);
+ if( peer->SendModule() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: send");
+ peer->CloseConnection();
+ FD_CLR(sk,rfdnextp);
+ }
+ need_check_send = 1;
+ }
+ }else if( !Self.OntimeDL() )
+ need_check_send = (peer->CheckSendStatus() && need_check_send);
+ }
+ else if( P_HANDSHAKE == peer->GetStatus() ){
+ if( FD_ISSET(sk,rfdp) ){
+ (*nready)--;
+ if( !Self.OntimeDL() && !Self.OntimeUL() ){
+ FD_CLR(sk,rfdnextp);
+ if( peer->HandShake() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: bad handshake");
+ peer->CloseConnection();
+ FD_CLR(sk,wfdnextp);
+ }
+ }
+ }
+ if( FD_ISSET(sk,wfdp) ){
+ (*nready)--;
+ if( !Self.OntimeDL() && !Self.OntimeUL() ){
+ FD_CLR(sk,wfdnextp);
+ if( peer->SendModule() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: send handshake");
+ peer->CloseConnection();
+ FD_CLR(sk,rfdnextp);
+ }
+ }
+ }
+ }
+ else if( P_CONNECTING == peer->GetStatus() ){
+ if( FD_ISSET(sk,wfdp) ){
+ (*nready)--;
+ if( !Self.OntimeDL() && !Self.OntimeUL() ){
+ FD_CLR(sk,wfdnextp);
+ if( peer->Send_ShakeInfo() < 0 ){
+ if(arg_verbose) CONSOLE.Debug("close: Sending handshake");
+ peer->CloseConnection();
+ FD_CLR(sk,rfdnextp);
+ }else peer->SetStatus(P_HANDSHAKE);
+ }
+ if( FD_ISSET(sk,rfdp) ) (*nready)--;
+ }else if( FD_ISSET(sk,rfdp) ){ // connect failed.
+ (*nready)--;
+ if( !Self.OntimeDL() && !Self.OntimeUL() ){
+ FD_CLR(sk,rfdnextp);
+ if(arg_verbose) CONSOLE.Debug("close: connect failed");
+ peer->CloseConnection();
+ FD_CLR(sk,wfdnextp);
+ }
+ }
+ }
+ }// end for
+
+ if( !m_ul_limited && !BandWidthLimitUp() ) m_missed_count++;
+}
+
+void PeerList::CloseAllConnectionToSeed()
+{
+ PEERNODE *p = m_head;
+ for( ; p; p = p->next ){
+ if( p->peer->bitfield.IsFull() ||
+ /* Drop peers who remain uninterested, but keep recent connections.
+ Peers who connected recently will resolve by bitfield exchange. */
+ (PEER_IS_SUCCESS(p->peer) && !p->peer->Is_Remote_Interested() &&
+ BTCONTENT.GetSeedTime() - now >= 300 &&
+ !p->peer->ConnectedWhileSeed()) ){
+ p->peer->DontWantAgain();
+ if(arg_verbose) CONSOLE.Debug("close: seed<->seed");
+ p->peer->CloseConnection();
+ }
+ else p->peer->stream.in_buffer.SetSize(BUF_DEF_SIZ);
+ }
+}
+
+int PeerList::UnChokeCheck(btPeer* peer, btPeer *peer_array[])
+{
+ int i = 0;
+ int cancel_idx = 0;
+ btPeer *loster = (btPeer*) 0;
+ int f_seed = BTCONTENT.Seeding();
+ int no_opt = 0;
+ unsigned long rndbits;
+ int r=0;
+ int retval = 0;
+
+ if(m_opt_timestamp) no_opt = 1;
+ if(f_seed) no_opt = 1 - no_opt;
+
+// Find my 3 or 4 fastest peers.
+// The m_max_unchoke+1 (4th) slot is for the optimistic unchoke when it happens.
+
+ // Find a slot for the candidate--the slowest peer, or an available slot.
+ for( cancel_idx = i = 0; i < m_max_unchoke + no_opt; i++ ){
+ if((btPeer*) 0 == peer_array[i] ||
+ PEER_IS_FAILED(peer_array[i]) ){ // 有空位
+ cancel_idx = i;
+ break;
+ }else{
+ if(cancel_idx == i) continue;
+
+ if(f_seed){
+ // compare time unchoked
+ if( (!peer_array[i]->Is_Local_UnChoked() &&
+ (peer_array[cancel_idx]->Is_Local_UnChoked() ||
+ peer_array[cancel_idx]->GetLastUnchokeTime() <
+ peer_array[i]->GetLastUnchokeTime())) ||
+ (peer_array[i]->Is_Local_UnChoked() &&
+ peer_array[cancel_idx]->Is_Local_UnChoked() &&
+ peer_array[i]->GetLastUnchokeTime() <
+ peer_array[cancel_idx]->GetLastUnchokeTime()) )
+ cancel_idx = i;
+ }else{
+ // compare download rate.
+ if( peer_array[cancel_idx]->RateDL() > peer_array[i]->RateDL()
+ //if equal, reciprocate to the peer we've sent less to, proportionally
+ ||(peer_array[cancel_idx]->RateDL() == peer_array[i]->RateDL()
+ && peer_array[cancel_idx]->TotalUL()
+ / (peer_array[cancel_idx]->TotalDL()+.001)
+ < peer_array[i]->TotalUL() / (peer_array[i]->TotalDL()+.001)) )
+ cancel_idx = i;
+ }
+ }
+ } // end for
+
+ if( (btPeer*) 0 != peer_array[cancel_idx] &&
+ PEER_IS_SUCCESS(peer_array[cancel_idx]) ){
+ if(f_seed){
+ if( (!peer_array[cancel_idx]->Is_Local_UnChoked() &&
+ (peer->Is_Local_UnChoked() ||
+ peer->GetLastUnchokeTime() <
+ peer_array[cancel_idx]->GetLastUnchokeTime())) ||
+ (peer_array[cancel_idx]->Is_Local_UnChoked() &&
+ peer->Is_Local_UnChoked() &&
+ peer_array[cancel_idx]->GetLastUnchokeTime() <
+ peer->GetLastUnchokeTime()) ){
+ loster = peer_array[cancel_idx];
+ peer_array[cancel_idx] = peer;
+ }else
+ loster = peer;
+ }else{
+ if( peer->RateDL() > peer_array[cancel_idx]->RateDL()
+ // If equal, reciprocate to the peer we've sent less to, proportionally
+ ||(peer_array[cancel_idx]->RateDL() == peer->RateDL()
+ && peer_array[cancel_idx]->TotalUL()
+ / (peer_array[cancel_idx]->TotalDL()+.001)
+ > peer->TotalUL() / (peer->TotalDL()+.001)) ){
+ loster = peer_array[cancel_idx];
+ peer_array[cancel_idx] = peer;
+ }else
+ loster = peer;
+ }
+
+ // opt unchoke
+ if( no_opt ){
+ if( loster->SetLocal(M_CHOKE) < 0 ){
+ loster->CloseConnection();
+ if( peer==loster ) retval = -1;
+ }
+ }
+ else
+ // The last slot is for the optimistic unchoke.
+ if( (btPeer*) 0 == peer_array[m_max_unchoke] ||
+ PEER_IS_FAILED(peer_array[m_max_unchoke]) )
+ peer_array[m_max_unchoke] = loster;
+ else {
+ if( !r-- ){
+ rndbits = random();
+ r = 15;
+ }
+ // if loser is empty and current is not, loser gets 75% chance.
+ if( loster->IsEmpty() && !peer_array[m_max_unchoke]->IsEmpty()
+ && (rndbits>>=2)&3 ){
+ btPeer* tmp = peer_array[m_max_unchoke];
+ peer_array[m_max_unchoke] = loster;
+ loster = tmp;
+ } else
+ // This mess chooses the loser:
+ // if loser is choked and current is not
+ // OR if both are choked and loser has waited longer
+ // OR if both are unchoked and loser has had less time unchoked.
+ if( (!loster->Is_Local_UnChoked() &&
+ ( peer_array[m_max_unchoke]->Is_Local_UnChoked() ||
+ loster->GetLastUnchokeTime() <
+ peer_array[m_max_unchoke]->GetLastUnchokeTime() )) ||
+ (loster->Is_Local_UnChoked() &&
+ peer_array[m_max_unchoke]->Is_Local_UnChoked() &&
+ peer_array[m_max_unchoke]->GetLastUnchokeTime() <
+ loster->GetLastUnchokeTime()) ){
+ // if current is empty and loser is not, loser gets 25% chance;
+ // else loser wins.
+ // transformed to: if loser is empty or current isn't, or 25% chance,
+ // then loser wins.
+ if( !peer_array[m_max_unchoke]->IsEmpty() || loster->IsEmpty()
+ || !((rndbits>>=2)&3) ){
+ btPeer* tmp = peer_array[m_max_unchoke];
+ peer_array[m_max_unchoke] = loster;
+ loster = tmp;
+ }
+ }
+ if(loster->SetLocal(M_CHOKE) < 0){
+ loster->CloseConnection();
+ if( peer==loster ) retval = -1;
+ }
+ }
+ }else //else if((btPeer*) 0 != peer_array[cancel_idx].....
+ peer_array[cancel_idx] = peer;
+
+ return retval;
+}
+
+// When we change what we're going after, we need to evaluate & set our
+// interest with each peer appropriately.
+void PeerList::CheckInterest()
+{
+ PEERNODE *p = m_head;
+ for( ; p; p = p->next ){
+ // Don't shortcut by checking Is_Local_Interested(), as we need to let
+ // SetLocal() reset the m_standby flag.
+ if( p->peer->Need_Remote_Data() ){
+ if( p->peer->SetLocal(M_INTERESTED) < 0 )
+ p->peer->CloseConnection();
+ }else{
+ if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 )
+ p->peer->CloseConnection();
+ }
+ }
+}
+
+btPeer* PeerList::GetNextPeer(btPeer *peer) const
+{
+ static PEERNODE *p = m_head;
+
+ if( !peer ) p = m_head;
+ else if( p && p->peer == peer ){
+ p = p->next;
+ }else{
+ for( p=m_head; p && (p->peer != peer); p = p->next );
+ if(p) p = p->next;
+ else p = m_head;
+ }
+ for( ; p; p = p->next )
+ if( p->peer && PEER_IS_SUCCESS(p->peer) ) break;
+
+ if(p) return p->peer;
+ else return (btPeer*) 0;
+}
+
+int PeerList::Endgame()
+{
+ BitField tmpBitfield;
+ int endgame = 0;
+
+ tmpBitfield = *BTCONTENT.pBF;
+ tmpBitfield.Invert(); // what I don't have...
+ tmpBitfield.Except(BTCONTENT.GetFilter()); // ...that I want
+ if( tmpBitfield.Count() > 0 &&
+ tmpBitfield.Count() < m_peers_count - m_conn_count )
+ endgame = 1;
+ else{
+ Pieces_I_Can_Get(&tmpBitfield); // what's available...
+ tmpBitfield.Except(BTCONTENT.GetFilter()); // ...that I want...
+ tmpBitfield.Except(*BTCONTENT.pBF); // ...that I don't have
+ if( tmpBitfield.Count() > 0 &&
+ tmpBitfield.Count() < m_peers_count - m_conn_count)
+ endgame = 1;
+ }
+
+ if( endgame && !m_endgame ){
+ if(arg_verbose) CONSOLE.Debug("Endgame (dup request) mode");
+ UnStandby();
+ }else if( !endgame && m_endgame ){
+ if(arg_verbose) CONSOLE.Debug("Normal (non dup request) mode");
+ RecalcDupReqs(); // failsafe
+ }
+
+ m_endgame = endgame;
+ return endgame;
+}
+
+void PeerList::UnStandby()
+{
+ PEERNODE *p = m_head;
+ for( ; p; p = p->next ){
+ if( PEER_IS_SUCCESS(p->peer) ) p->peer->UnStandby();
+ }
+}
+
+void PeerList::Pause()
+{
+ PEERNODE *p = m_head;
+
+ m_f_pause = 1;
+ StopDownload();
+ for( ; p; p = p->next ){
+ if( p->peer->Is_Local_UnChoked() && p->peer->SetLocal(M_CHOKE) < 0 )
+ p->peer->CloseConnection();
+ }
+}
+
+void PeerList::Resume()
+{
+ m_f_pause = 0;
+ CheckInterest();
+}
+
+void PeerList::StopDownload()
+{
+ PEERNODE *p = m_head;
+
+ for( ; p; p = p->next ){
+ if( p->peer->SetLocal(M_NOT_INTERESTED) < 0 ){
+ p->peer->CloseConnection();
+ }else p->peer->PutPending();
+ }
+}
+
+size_t PeerList::GetUnchoked() const
+{
+ PEERNODE *p;
+ size_t count = 0;
+
+ for( p = m_head; p; p = p->next ){
+ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() ){
+ count++;
+ if( count > m_max_unchoke ) break;
+ }
+ }
+ return count;
+}
+
+// This function returns 0 if it could not find an upload faster than the
+// minimum and all peer upload rates are known (not zero).
+size_t PeerList::GetSlowestUp(size_t minimum) const
+{
+ PEERNODE *p;
+ size_t slowest = 0, zero = 0, unchoked = 0, rate;
+
+ for( p = m_head; p; p = p->next ){
+ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() ){
+ unchoked++;
+ rate = p->peer->RateUL();
+ if( 0==rate ) zero = 1;
+ else if( rate >= minimum && (rate < slowest || 0==slowest) )
+ slowest = rate;
+ }
+ }
+ if( slowest > (rate = Self.RateUL()) ) slowest = rate;
+
+ // We're looking for slow, so guess low when we must guess a rate.
+ if( slowest ){
+ if( zero ) return minimum ? minimum : ((slowest+1)/2);
+ else return slowest;
+ }else{
+ if( 0==unchoked ) unchoked = 1; // safeguard
+ if( zero ) return minimum ? minimum :
+ ((rate = Self.RateUL()) ? rate / unchoked : 1);
+ else return 0;
+ }
+}
+
+int PeerList::BandWidthLimitUp(double when)
+{
+ return BandWidthLimitUp(when, cfg_max_bandwidth_up);
+}
+
+int PeerList::BandWidthLimitUp(double when, int limit)
+{
+ int limited = 0;
+ double nexttime;
+
+ if( limit <= 0 ) return 0;
+
+ nexttime = Self.LastSendTime() +
+ (double)(Self.LastSizeSent()) / limit;
+ if( nexttime >= now + 1 + when ) limited = 1;
+ else if( nexttime < now + when ) limited = 0;
+ else{
+ struct timespec nowspec;
+ double rightnow;
+
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+ rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000;
+
+ if( nexttime <= rightnow + when ) limited = 0;
+ else limited = 1;
+ }
+ if( limited ) m_f_ulate = 1;
+ return limited;
+}
+
+int PeerList::BandWidthLimitDown(double when)
+{
+ return BandWidthLimitDown(when, cfg_max_bandwidth_down);
+}
+
+int PeerList::BandWidthLimitDown(double when, int limit)
+{
+ int limited = 0;
+ double nexttime;
+
+ // Don't check SeedOnly() here--need to let the input stream drain.
+ if( limit <= 0 ) return 0;
+
+ nexttime = Self.LastRecvTime() +
+ (double)(Self.LastSizeRecv()) / limit;
+ if( nexttime >= now + 1 + when ) limited = 1;
+ else if( nexttime < now + when ) limited = 0;
+ else{
+ struct timespec nowspec;
+ double rightnow;
+
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+ rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000;
+
+ if( nexttime <= rightnow + when ) limited = 0;
+ else limited = 1;
+ }
+ if( limited ) m_f_dlate = 1;
+ return limited;
+}
+
+int PeerList::IsIdle()
+{
+ int idle = 0, dlate = 0, ulate = 0, slow = 0;
+
+ if(
+ ( (cfg_max_bandwidth_down > 0 &&
+ (dlate = (now > (time_t)(Self.LastRecvTime() + Self.LateDL() +
+ Self.LastSizeRecv() / (double)cfg_max_bandwidth_down)))) ||
+ 0==Self.RateDL() ||
+ ((0==cfg_max_bandwidth_down ||
+ (slow = (Self.RateDL() < cfg_max_bandwidth_down / 2))) &&
+ BandWidthLimitDown(Self.LateDL(), (int)Self.RateDL() * 2)) ||
+ (!slow && BandWidthLimitDown(Self.LateDL())) )
+
+ && !(dlate && m_f_dlate) &&
+
+ ( (cfg_max_bandwidth_up > 0 &&
+ (ulate = (now > (time_t)(Self.LastSendTime() + Self.LateUL() +
+ Self.LastSizeSent() / (double)cfg_max_bandwidth_up)))) ||
+ 0==Self.RateUL() ||
+ (slow = 0) || // re-initialization
+ ((0==cfg_max_bandwidth_up ||
+ (slow = (Self.RateUL() < cfg_max_bandwidth_up / 2))) &&
+ BandWidthLimitUp(Self.LateUL(), (int)Self.RateUL() * 2)) ||
+ (!slow && BandWidthLimitUp(Self.LateUL())) )
+ ){
+ idle = 1;
+ }
+
+ if( !dlate ) m_f_dlate = 1;
+ else if( m_f_dlate ) idle = 0;
+ if( !ulate ) m_f_ulate = 1;
+ else if( m_f_ulate ) idle = 0;
+ return idle;
+}
+
+// How long must we wait for bandwidth to become available in either direction?
+double PeerList::WaitBW() const
+{
+ struct timespec nowspec;
+ double rightnow, late;
+ double maxwait = 0, nextwake = 0;
+ double nextup = 0, nextdn = 0;
+ int use_up = 0, use_dn = 0;
+
+ if( cfg_max_bandwidth_up ){
+ nextup = Self.LastSendTime() +
+ (double)(Self.LastSizeSent()) / cfg_max_bandwidth_up;
+ }
+ if( cfg_max_bandwidth_down ){
+ nextdn = Self.LastRecvTime() +
+ (double)(Self.LastSizeRecv()) / cfg_max_bandwidth_down;
+ }
+
+ // could optimize away the clock call when maxwait will be > MAX_SLEEP
+ if( now <= (time_t)nextup || now <= (time_t)nextdn ){
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+ rightnow = nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000;
+ }else rightnow = (double)now;
+
+ if( nextup >= rightnow ){
+ if( nextdn < rightnow ) use_up = 1;
+ else if( nextdn < nextup ) use_dn = 1;
+ else use_up = 1;
+ }else if( nextdn >= rightnow ) use_dn = 1;
+
+ if( use_up ){
+ nextwake = nextup;
+ late = Self.LateUL();
+ }else if( use_dn ){
+ nextwake = nextdn;
+ late = Self.LateDL();
+ }else{
+ nextwake = late = 0;
+ }
+
+ if( (m_f_limitd && nextdn <= rightnow + Self.LateDL()) ||
+ (m_f_limitu && nextup <= rightnow + Self.LateUL()) ){
+ // socket setup is outdated; send a problem indicator value back
+ Self.OntimeUL(0);
+ Self.OntimeDL(0);
+ maxwait = -100;
+ }else if( nextwake > rightnow ){
+ maxwait = nextwake - rightnow - late;
+ if( maxwait < 0 ){
+ use_up = use_dn = 0;
+ }
+ Self.OntimeUL(use_up);
+ Self.OntimeDL(use_dn);
+// CONSOLE.Debug("waitbw %f at %f", maxwait, rightnow);
+ }else{
+ Self.OntimeUL(0);
+ Self.OntimeDL(0);
+// CONSOLE.Debug("nextwake %f at %f", nextwake, rightnow);
+ }
+ return maxwait;
+}
+
+void PeerList::UnchokeIfFree(btPeer *peer)
+{
+ PEERNODE *p;
+ size_t count = 0;
+
+ if( m_f_pause ) return;
+ for( p = m_head; p; p = p->next ){
+ if( PEER_IS_SUCCESS(p->peer) && p->peer->Is_Local_UnChoked() &&
+ p->peer->Is_Remote_Interested() ){
+ count++;
+ if( m_max_unchoke < count ) return;
+ }
+ }
+ if( peer->SetLocal(M_UNCHOKE) < 0 ) peer->CloseConnection();
+}
+
+void PeerList::AdjustPeersCount()
+{
+ Tracker.AdjustPeersCount();
+}
+
diff --git a/peerlist.h b/peerlist.h
new file mode 100644
index 0000000..ee59a38
--- a/dev/null
+++ b/peerlist.h
@@ -0,0 +1,127 @@
+#ifndef PEERLIST_H
+#define PEERLIST_H
+
+#include "./def.h"
+#include <sys/types.h>
+#include <time.h>
+
+#include "./peer.h"
+#include "./rate.h"
+
+typedef struct _peernode{
+ btPeer *peer;
+ struct _peernode *next;
+}PEERNODE;
+
+class PeerList
+{
+ private:
+ SOCKET m_listen_sock;
+ PEERNODE *m_head, *m_dead;
+ size_t m_peers_count, m_seeds_count, m_conn_count, m_downloads;
+ size_t m_max_unchoke;
+ time_t m_unchoke_check_timestamp, m_keepalive_check_timestamp,
+ m_last_progress_timestamp, m_opt_timestamp, m_interval_timestamp;
+ time_t m_unchoke_interval, m_opt_interval;
+ size_t m_defer_count, m_missed_count, m_upload_count, m_up_opt_count;
+ size_t m_dup_req_pieces;
+ int m_prev_limit_up;
+ char m_listen[22];
+
+ unsigned char m_ul_limited:1;
+ unsigned char m_f_pause:1;
+ unsigned char m_f_limitd:1;
+ unsigned char m_f_limitu:1;
+ unsigned char m_f_dlate:1;
+ unsigned char m_f_ulate:1;
+ unsigned char m_endgame:1;
+ unsigned char m_reserved:1;
+
+ int Accepter();
+ int UnChokeCheck(btPeer* peer,btPeer *peer_array[]);
+ int FillFDSet(fd_set *rfd, fd_set *wfd, int f_keepalive_check,
+ int f_unchoke_check, btPeer **UNCHOKER);
+
+ public:
+ PeerList();
+ ~PeerList();
+
+ // TotalPeers() is now GetPeersCount() for consistency
+ int Initial_ListenPort();
+ const char *GetListen() const { return m_listen; }
+
+ int IsEmpty() const { return m_peers_count ? 0 : 1; }
+
+
+ void PrintOut() const;
+
+ int NewPeer(struct sockaddr_in addr, SOCKET sk);
+
+ void CloseAllConnectionToSeed();
+ void CloseAll();
+
+ int IntervalCheck(fd_set *rfd, fd_set *wfd);
+
+ void SetUnchokeIntervals();
+ void AnyPeerReady(fd_set *rfdp, fd_set *wfdp, int *nready,
+ fd_set *rfdnextp, fd_set *wfdnextp);
+
+ int BandWidthLimitUp() { return BandWidthLimitUp(0); }
+ int BandWidthLimitUp(double when);
+ int BandWidthLimitUp(double when, int limit);
+ int BandWidthLimitDown() { return BandWidthLimitDown(0); }
+ int BandWidthLimitDown(double when);
+ int BandWidthLimitDown(double when, int limit);
+ double WaitBW() const;
+ void DontWaitBW() { Self.OntimeUL(0); Self.OntimeDL(0); }
+
+ void Tell_World_I_Have(size_t idx);
+ btPeer* Who_Can_Abandon(btPeer *proposer);
+ size_t What_Can_Duplicate(BitField &bf, const btPeer *proposer, size_t idx);
+ void FindValuedPieces(BitField &bf, const btPeer *proposer, int initial)
+ const;
+ btPeer *WhoHas(size_t idx) const;
+ int HasSlice(size_t idx, size_t off, size_t len) const;
+ void CompareRequest(btPeer *proposer, size_t idx);
+ int CancelSlice(size_t idx, size_t off, size_t len);
+ int CancelPiece(size_t idx);
+ void CancelOneRequest(size_t idx);
+
+ void CheckBitField(BitField &bf);
+ int AlreadyRequested(size_t idx) const;
+ size_t Pieces_I_Can_Get() const;
+ size_t Pieces_I_Can_Get(BitField *ptmpBitField) const;
+ void CheckInterest();
+ btPeer* GetNextPeer(btPeer *peer) const;
+ int Endgame();
+ void UnStandby();
+
+ size_t GetDupReqs() const { return m_dup_req_pieces; }
+ void RecalcDupReqs();
+
+ size_t GetSeedsCount() const { return m_seeds_count; }
+ size_t GetPeersCount() const { return m_peers_count; }
+ size_t GetConnCount() const { return m_conn_count; }
+ void AdjustPeersCount(); // passthrough to tracker function
+
+ size_t GetUnchoked() const;
+ size_t GetSlowestUp(size_t minimum) const;
+ size_t GetDownloads() const { return m_downloads; }
+ size_t GetUnchokeInterval() const { return m_unchoke_interval; }
+
+ void Defer() { m_defer_count++; }
+ void Upload() { m_upload_count++; }
+
+ int IsIdle();
+ void UnLate() { m_f_dlate = m_f_ulate = 0; }
+ void Pause();
+ void Resume();
+ int IsPaused() const { return m_f_pause ? 1 : 0; }
+ void StopDownload();
+
+ void UnchokeIfFree(btPeer *peer);
+};
+
+extern PeerList WORLD;
+
+#endif
diff --git a/rate.cpp b/rate.cpp
new file mode 100644
index 0000000..ae3662d
--- a/dev/null
+++ b/rate.cpp
@@ -0,0 +1,334 @@
+#include "rate.h" // def.h
+
+#include <sys/time.h>
+
+#include "btconfig.h"
+#include "bufio.h" // for BUF_DEF_SIZ
+#include "bttime.h"
+#include "console.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+#include "compat.h"
+#endif
+
+#define RATE_INTERVAL 20
+#define SHORT_INTERVAL 5
+
+Rate::Rate()
+{
+ m_last_timestamp = m_total_timeused = m_nom_time = (time_t)0;
+ m_count_bytes = 0;
+ m_history = m_history_last = (BWSAMPLE *)0;
+ m_last_realtime = m_recent_realtime = m_prev_realtime = 0;
+ m_last_size = m_recent_size = m_prev_size = 0;
+ m_selfrate = (Rate *)0;
+ m_late = 0;
+ m_ontime = m_update_nominal = 0;
+ m_lastrate.lasttime = (time_t)0;
+ m_nominal = DEFAULT_SLICE_SIZE / 8; // minimum "acceptable" rate
+}
+
+void Rate::Reset()
+{
+ m_last_timestamp = m_total_timeused = (time_t)0;
+ ClearHistory();
+ m_last_realtime = 0;
+ m_last_size = 0;
+}
+
+void Rate::StartTimer()
+{
+ if( !m_last_timestamp ) m_last_timestamp = now;
+}
+
+void Rate::StopTimer()
+{
+ if( m_last_timestamp ){
+ m_total_timeused += (now - m_last_timestamp);
+ if( m_history ){
+ if( m_history == m_history_last )
+ m_nominal = (size_t)(m_history->bytes /
+ (m_history->timestamp - m_last_timestamp));
+ else (void)RateMeasure(); // updates nominal
+ }
+ m_last_timestamp = 0;
+ ClearHistory();
+ }
+ m_update_nominal = 0;
+}
+
+BWSAMPLE *Rate::NewSample()
+{
+ BWSAMPLE *sample = new BWSAMPLE;
+ if( sample ){
+ sample->timestamp = 0;
+ sample->bytes = 0;
+ sample->next = (BWSAMPLE *)0;
+ }else
+ CONSOLE.Warning(2, "warn, failed to allocate memory for bandwidth sample.");
+
+ return sample;
+}
+
+void Rate::ClearHistory()
+{
+ if( m_history ){
+ BWSAMPLE *pnext;
+ for( BWSAMPLE *p=m_history; p; p=pnext ){
+ pnext = p->next;
+ delete p;
+ }
+ m_history = m_history_last = (BWSAMPLE *)0;
+ }
+}
+
+void Rate::Cleanup()
+{
+ BWSAMPLE *p = m_history;
+
+ while( p && RATE_INTERVAL <= now - (time_t)(p->timestamp) ){
+ int nzero = 0;
+ if( !p->next ){
+ if( BWSAMPLE *q = NewSample() ){
+ q->timestamp = (double)now - 1;
+ p->next = q;
+ m_history_last = q;
+ nzero++;
+ }else{
+ p->bytes = p->bytes * RATE_INTERVAL / (now - (time_t)(p->timestamp));
+ p->timestamp = (double)(now - RATE_INTERVAL + 1);
+ }
+ }
+ if( p->next ){
+ if( RATE_INTERVAL > now - (time_t)(p->next->timestamp) ){
+ time_t reftime = nzero ? now : (time_t)(p->next->timestamp);
+ while( (time_t)(p->next->timestamp) > (time_t)(p->timestamp) + 1 ){
+ // fill holes
+ if( BWSAMPLE *q = NewSample() ){
+ q->timestamp = (double)((time_t)(p->next->timestamp) - 1);
+ q->next = p->next;
+ p->next = q;
+ nzero++;
+ }else break;
+ }
+ if( nzero ){
+ size_t bytes = (size_t)( p->bytes / (reftime - p->timestamp) );
+ BWSAMPLE *q = p->next;
+ for( ; nzero; nzero-- ){
+ q->bytes += bytes; // distribute over the following empty samples
+ q = q->next;
+ }
+ }
+ }
+ m_history = p->next;
+ delete p;
+ p = m_history;
+ }
+ }
+}
+
+void Rate::CountAdd(size_t nbytes)
+{
+ m_count_bytes += nbytes;
+ if( m_selfrate ) m_selfrate->CountAdd(nbytes);
+}
+
+void Rate::UnCount(size_t nbytes)
+{
+ m_count_bytes -= nbytes;
+ if( m_selfrate ) m_selfrate->UnCount(nbytes);
+}
+
+void Rate::RateAdd(size_t nbytes, size_t bwlimit)
+{
+ struct timespec nowspec;
+
+ clock_gettime(CLOCK_REALTIME, &nowspec);
+
+ RateAdd(nbytes, bwlimit,
+ nowspec.tv_sec + (double)(nowspec.tv_nsec)/1000000000);
+}
+
+void Rate::RateAdd(size_t nbytes, size_t bwlimit, double timestamp)
+{
+ int update_nominal = 0;
+
+ if( m_history_last && timestamp < m_history_last->timestamp ){
+ // time went backward
+ ClearHistory();
+ }else Cleanup();
+ if( timestamp <= m_last_realtime ){ // time went backward
+ m_ontime = 0;
+ m_last_size = 0;
+ m_last_realtime = 0;
+ }
+
+ if( m_history_last &&
+ (time_t)timestamp == (time_t)(m_history_last->timestamp) )
+ m_history_last->bytes += nbytes;
+ else{
+ if( BWSAMPLE *p = NewSample() ){
+ p->timestamp = timestamp;
+ p->bytes = nbytes;
+ if( m_history_last ){
+ m_history_last->next = p;
+ update_nominal = 1;
+ }
+ else m_history = p;
+ m_history_last = p;
+ }
+ }
+
+ if( !m_selfrate && m_ontime ){
+ double late=timestamp - (m_last_realtime + (double)m_last_size / bwlimit);
+// double tmplate = late;
+ // keep the change under control in case the system gets weird on us
+ if( late < 0 ) late /= 2;
+ else if( m_late && late > m_late ) late = m_late / 2;
+ m_late += late;
+// CONSOLE.Debug("%p late %f->%f: %f", this, tmplate, late, m_late);
+ m_ontime = 0;
+ }
+
+ if( m_selfrate && bwlimit && m_last_realtime && m_selfrate->LastSize() /
+ (timestamp - m_selfrate->LastRealtime()) > bwlimit )
+ m_last_size += nbytes;
+ else if( !m_selfrate && bwlimit && m_last_realtime &&
+ m_last_size / (timestamp - m_last_realtime) > bwlimit )
+ m_last_size += nbytes;
+ else{
+ m_last_realtime = timestamp;
+ m_last_size = nbytes;
+ }
+
+ if( nbytes > BUF_DEF_SIZ ){
+ m_prev_realtime = m_recent_realtime;
+ m_prev_size = m_recent_size;
+ m_recent_realtime = timestamp;
+ m_recent_size = nbytes;
+ }else m_recent_size += nbytes;
+
+ if( m_selfrate ){
+ if( update_nominal ){
+ m_update_nominal = 1;
+ (void)RateMeasure(); // updates nominal
+ }
+ m_selfrate->RateAdd(nbytes, bwlimit, timestamp);
+ }
+
+//if(!m_selfrate) CONSOLE.Debug("%p RateAdd %u @ %f next=%f", this,
+// nbytes, timestamp, m_last_realtime + (double)m_last_size / bwlimit);
+}
+
+void Rate::operator=(const Rate &ra)
+{
+ m_last_timestamp = now;
+ m_count_bytes = ra.m_count_bytes;
+}
+
+size_t Rate::CurrentRate()
+{
+ // We can't make up for past slowness by overloading the line now/future.
+ // Look at only the most recent data sent/received.
+ if( !m_last_timestamp || !m_history ) return 0; // no current rate
+
+ struct timespec timestamp;
+ clock_gettime(CLOCK_REALTIME, &timestamp);
+
+ double timeused = timestamp.tv_sec + (double)(timestamp.tv_nsec)/1000000000 -
+ m_last_realtime;
+ if( timeused <= 0 ) return 0;
+
+ return (size_t)( m_last_size / timeused );
+}
+
+size_t Rate::NominalRate()
+{
+ if( !m_history && m_last_timestamp && TimeUsed() > 10 ){
+ // sent a request over 10 sec ago but have received nothing
+ if( !m_nom_time || now >= m_nom_time + 10 ){
+ m_nominal /= 10;
+ m_nom_time = now;
+ }
+ }
+ return m_nominal;
+}
+
+size_t Rate::RateMeasure()
+{
+ // calculate rate based on bandwidth history data
+ time_t timestamp = now;
+ unsigned long countbytes = 0;
+ double timeused = 0;
+ BWSAMPLE *p;
+
+ if( m_history && now == m_lastrate.lasttime &&
+ m_recent_realtime == m_lastrate.recent ){
+ if( m_update_nominal ) m_nominal = m_lastrate.value;
+ return m_lastrate.value;
+ }
+
+ m_lastrate.lasttime = now;
+ if( !m_last_timestamp || !m_history ){
+ m_lastrate.value = 0;
+ return 0; // no current rate
+ }
+
+ Cleanup();
+ for( p=m_history; p; p=p->next ){
+ countbytes += p->bytes;
+ }
+ timeused = (double)(now - (time_t)(m_history->timestamp));
+ if( timeused == 0 ) timeused = 1;
+ else if( timeused < 0 ) ClearHistory(); // time went backward
+ else m_update_nominal = 1;
+ if( now < (time_t)m_recent_realtime ){
+ if( m_history ){
+ m_recent_realtime = (double)now;
+ m_prev_realtime = (double)(now - 1);
+ m_recent_size = m_prev_size = 0;
+ }else{
+ m_recent_realtime = m_prev_realtime = 0;
+ m_recent_size = m_prev_size = 0;
+ }
+ }
+ if( !m_history ){
+ m_lastrate.value = 0;
+ return 0;
+ }
+
+ // Don't let the most recent addition inflate the rate measurement.
+ if( now == (time_t)m_recent_realtime ){
+ // don't count the most recent addition
+ countbytes -= m_recent_size;
+ timeused = m_recent_realtime - m_history->timestamp;
+ }else if( m_recent_realtime &&
+ RATE_INTERVAL > now - (time_t)m_recent_realtime &&
+ m_recent_size / (now - (time_t)m_recent_realtime) >
+ m_prev_size / (m_recent_realtime - m_prev_realtime) ){
+ // "tone down" the most recent to match the previous addition's rate
+ countbytes -= m_recent_size;
+ countbytes += (unsigned long)(
+ m_prev_size / (m_recent_realtime - m_prev_realtime) *
+ (now - (time_t)m_recent_realtime) );
+ }
+
+ m_lastrate.value = (size_t)(countbytes / timeused);
+ m_lastrate.recent = m_recent_realtime;
+ if( m_update_nominal ) m_nominal = m_lastrate.value;
+ return m_lastrate.value;
+}
+
+size_t Rate::RateMeasure(const Rate &ra_to)
+{
+ time_t timeused = TimeUsed();
+ int tmp = ra_to.m_count_bytes - m_count_bytes;
+ return (size_t)( (tmp>0) ? (tmp/(timeused ? timeused : 1)) : 0 );
+}
+
+time_t Rate::TimeUsed()
+{
+ if( now < m_last_timestamp ) m_last_timestamp = now;
+ return now - m_last_timestamp;
+}
+
diff --git a/rate.h b/rate.h
new file mode 100644
index 0000000..c935937
--- a/dev/null
+++ b/rate.h
@@ -0,0 +1,71 @@
+#ifndef RATE_H
+#define RATE_H
+
+#include "def.h"
+#include <inttypes.h>
+#include <sys/types.h>
+#include <time.h>
+
+typedef struct _bwsample{
+ double timestamp;
+ unsigned long bytes;
+ struct _bwsample *next;
+}BWSAMPLE;
+
+class Rate{
+ private:
+ time_t m_last_timestamp;
+ time_t m_total_timeused;
+ uint64_t m_count_bytes;
+ // m_last: tracks recent xfer(s) for timing & limit comparison
+ // m_recent: the most recent measurable xfer
+ // m_prev: the prior m_recent
+ double m_last_realtime, m_recent_realtime, m_prev_realtime;
+ size_t m_last_size, m_recent_size, m_prev_size;
+ double m_late;
+ size_t m_nominal;
+ time_t m_nom_time;
+ struct{
+ size_t value;
+ time_t lasttime;
+ double recent;
+ } m_lastrate;
+
+ unsigned char m_ontime:1;
+ unsigned char m_update_nominal:1;
+ unsigned char m_reserved:6;
+
+ BWSAMPLE *m_history, *m_history_last; // bandwidth history data
+
+ Rate *m_selfrate;
+
+ static BWSAMPLE *NewSample();
+
+ public:
+ Rate();
+
+ void Reset();
+ void StartTimer();
+ void StopTimer();
+ void ClearHistory();
+ void Cleanup();
+ void CountAdd(size_t nbytes);
+ void UnCount(size_t nbytes);
+ void RateAdd(size_t nbytes, size_t bwlimit);
+ void RateAdd(size_t nbytes, size_t bwlimit, double timestamp);
+ void operator=(const Rate &ra);
+ uint64_t Count() const { return m_count_bytes; }
+ size_t CurrentRate();
+ size_t NominalRate();
+ size_t RateMeasure();
+ size_t RateMeasure(const Rate &ra);
+ time_t TimeUsed();
+ double LastRealtime() const { return m_last_realtime; }
+ size_t LastSize() const { return m_last_size; }
+ void SetSelf(Rate *rate) { m_selfrate = rate; }
+ double Late() const { return m_late; }
+ int Ontime() const { return m_ontime ? 1 : 0; }
+ void Ontime(int yn) { m_ontime = yn ? 1 : 0; }
+};
+
+#endif
diff --git a/setnonblock.cpp b/setnonblock.cpp
new file mode 100644
index 0000000..d6c6a83
--- a/dev/null
+++ b/setnonblock.cpp
@@ -0,0 +1,25 @@
+#include "./setnonblock.h"
+
+#ifdef WINDOWS
+
+int setfd_nonblock(SOCKET socket)
+{
+ unsigned long val = 1;
+ return ioctl(socket,FIONBIO,&val);
+}
+
+#else
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int setfd_nonblock(SOCKET socket)
+{
+ int f_old;
+ f_old = fcntl(socket,F_GETFL,0);
+ if( f_old < 0 ) return -1;
+ f_old |= O_NONBLOCK;
+ return (fcntl(socket,F_SETFL,f_old));
+}
+
+#endif
diff --git a/setnonblock.h b/setnonblock.h
new file mode 100644
index 0000000..7a4864d
--- a/dev/null
+++ b/setnonblock.h
@@ -0,0 +1,17 @@
+#ifndef SETNONBLOCK_H
+#define SETNONBLOCK_H
+
+#include "./def.h"
+#include <sys/types.h>
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+#else
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/socket.h>
+#endif
+
+int setfd_nonblock(SOCKET socket);
+
+#endif
diff --git a/sha1.c b/sha1.c
new file mode 100644
index 0000000..280be24
--- a/dev/null
+++ b/sha1.c
@@ -0,0 +1,251 @@
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+Modified 7/98
+By James H. Brown <jbrown@burgoyne.com>
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it. This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include <process.h> for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid <sreid@sea-to-sky.net>
+Still 100% public domain
+
+1- Removed #include <process.h> and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz <Saul.Kravitz@celera.com>
+Still 100% PD
+Modified to run on Compaq Alpha hardware.
+
+
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#include "config.h"
+
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+#define SHA1HANDSOFF
+
+#ifdef VERBOSE
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#include "sha1.h"
+
+/* Use result of AC_C_BIGENDIAN autoconf test. */
+#ifndef WORDS_BIGENDIAN
+#define SHA1_LITTLE_ENDIAN 1
+#endif
+
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef SHA1_LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+#ifdef VERBOSE /* SAK */
+void SHAPrintContext(SHA1_CTX *context, char *msg){
+ printf("%s (%d,%d) %x %x %x %x %x\n",
+ msg,
+ context->count[0], context->count[1],
+ context->state[0],
+ context->state[1],
+ context->state[2],
+ context->state[3],
+ context->state[4]);
+}
+#endif
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
+{
+uint32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ uint32_t l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /*
+JHB */
+{
+uint32_t i, j; /* JHB */
+
+#ifdef VERBOSE
+ SHAPrintContext(context, "before");
+#endif
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+#ifdef VERBOSE
+ SHAPrintContext(context, "after ");
+#endif
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+uint32_t i; /* JHB */
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = 0; /* JHB */
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(finalcount, 0, 8); /* SWR */
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+
diff --git a/sha1.h b/sha1.h
new file mode 100644
index 0000000..86babdb
--- a/dev/null
+++ b/sha1.h
@@ -0,0 +1,37 @@
+#ifndef SHA1_H
+#define SHA1_H
+
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+23 Apr 2001 version from http://sea-to-sky.net/~sreid/
+Modified slightly to take advantage of autoconf.
+See sha1.c for full history comments.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+typedef struct {
+ uint32_t state[5];
+ uint32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /* JHB */
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sigint.cpp b/sigint.cpp
new file mode 100644
index 0000000..4e49a99
--- a/dev/null
+++ b/sigint.cpp
@@ -0,0 +1,68 @@
+#ifndef WINDOWS
+#include "sigint.h" // def.h
+
+#include <sys/types.h>
+#include <signal.h>
+
+#include "btcontent.h"
+#include "tracker.h"
+#include "peerlist.h"
+#include "btconfig.h"
+#include "console.h"
+
+extern "C" {
+
+RETSIGTYPE sig_catch(int sig_no)
+{
+ if(SIGINT == sig_no || SIGTERM == sig_no){
+ Tracker.ClearRestart();
+ Tracker.SetStoped();
+ signal(sig_no,sig_catch2);
+ }
+}
+
+static RETSIGTYPE sig_catch2(int sig_no)
+{
+ if(SIGINT == sig_no || SIGTERM == sig_no){
+ if( cfg_cache_size ) BTCONTENT.FlushCache();
+ BTCONTENT.SaveBitfield();
+ WORLD.CloseAll();
+ signal(sig_no,SIG_DFL);
+ raise(sig_no);
+ }
+}
+
+
+// Handler for other signals
+RETSIGTYPE signals(int sig_no)
+{
+ return CONSOLE.Signal(sig_no);
+}
+
+} // extern "C"
+
+#endif
+
+
+void sig_setup()
+{
+#ifndef WINDOWS
+ signal(SIGPIPE,SIG_IGN);
+ signal(SIGINT,sig_catch);
+ signal(SIGTERM,sig_catch);
+
+ // Don't let printf restart a write after SIGTTOU, we will hard-loop!
+ struct sigaction handler;
+ handler.sa_handler = signals;
+ sigemptyset(&(handler.sa_mask));
+ handler.sa_flags = 0; // SA_RESTART is not set
+ sigaction(SIGTTOU, &handler, (struct sigaction *)0);
+
+ // Likewise with input after SIGTTIN
+ sigaction(SIGTTIN, &handler, (struct sigaction *)0);
+
+ signal(SIGCONT,signals);
+ signal(SIGTSTP,signals);
+#endif
+}
+
diff --git a/sigint.h b/sigint.h
new file mode 100644
index 0000000..b3d287e
--- a/dev/null
+++ b/sigint.h
@@ -0,0 +1,18 @@
+#ifndef SIGINT_H
+#define SIGINT_H
+
+#include "def.h"
+
+#ifndef WINDOWS
+extern "C" {
+
+RETSIGTYPE sig_catch(int sig_no);
+static RETSIGTYPE sig_catch2(int sig_no);
+RETSIGTYPE signals(int sig_no);
+
+} // extern "C"
+#endif
+
+void sig_setup();
+
+#endif
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- a/dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/stamp-h1 b/stamp-h1
new file mode 100644
index 0000000..4547fe1
--- a/dev/null
+++ b/stamp-h1
@@ -0,0 +1 @@
+timestamp for config.h
diff --git a/tracker.cpp b/tracker.cpp
new file mode 100644
index 0000000..35bc085
--- a/dev/null
+++ b/tracker.cpp
@@ -0,0 +1,669 @@
+#include "tracker.h"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "peerlist.h"
+#include "peer.h"
+#include "httpencode.h"
+#include "bencode.h"
+#include "setnonblock.h"
+#include "connect_nonb.h"
+#include "btcontent.h"
+#include "iplist.h"
+
+#include "btconfig.h"
+#include "ctcs.h"
+#include "console.h"
+#include "bttime.h"
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_RANDOM)
+#include "compat.h"
+#endif
+
+btTracker Tracker;
+
+btTracker::btTracker()
+{
+ memset(m_host,0,MAXHOSTNAMELEN);
+ memset(m_path,0,MAXPATHLEN);
+ memset(m_trackerid,0,PEER_ID_LEN+1);
+
+ m_sock = INVALID_SOCKET;
+ m_port = 80;
+ m_status = T_FREE;
+ m_f_started = m_f_stoped = m_f_completed = m_f_restart = 0;
+
+ m_interval = 15;
+ m_peers_count = m_seeds_count = 0;
+
+ m_connect_refuse_click = 0;
+ m_last_timestamp = (time_t) 0;
+ m_prevpeers = 0;
+
+ m_report_time = (time_t) 0;
+ m_report_dl = m_report_ul = m_totaldl = m_totalul = 0;
+}
+
+btTracker::~btTracker()
+{
+ if( m_sock != INVALID_SOCKET) CLOSE_SOCKET(m_sock);
+}
+
+void btTracker::Reset(time_t new_interval)
+{
+ if(new_interval) m_interval = new_interval;
+
+ if( INVALID_SOCKET != m_sock ){
+ if(arg_verbose && T_READY==m_status)
+ CONSOLE.Debug("Disconnected from tracker");
+ CLOSE_SOCKET(m_sock);
+ m_sock = INVALID_SOCKET;
+ }
+
+ m_request_buffer.Reset();
+ m_reponse_buffer.Reset();
+ if( now < m_last_timestamp ) m_last_timestamp = now; // time reversed
+
+ if( m_f_stoped ){
+ m_status = T_FINISHED;
+ if( m_f_restart ) Restart();
+ }
+ else m_status = T_FREE;
+}
+
+int btTracker:: _IPsin(char *h, int p, struct sockaddr_in *psin)
+{
+ psin->sin_family = AF_INET;
+ psin->sin_port = htons(p);
+ psin->sin_addr.s_addr = inet_addr(h);
+ return ( psin->sin_addr.s_addr == INADDR_NONE ) ? -1 : 0;
+}
+
+int btTracker:: _s2sin(char *h,int p,struct sockaddr_in *psin)
+{
+ psin->sin_family = AF_INET;
+ psin->sin_port = htons(p);
+ if( h ){
+ psin->sin_addr.s_addr = inet_addr(h);
+ if(psin->sin_addr.s_addr == INADDR_NONE){
+ struct hostent *ph = gethostbyname(h);
+ if( !ph || ph->h_addrtype != AF_INET){
+ memset(psin,0,sizeof(struct sockaddr_in));
+ return -1;
+ }
+ memcpy(&psin->sin_addr,ph->h_addr_list[0],sizeof(struct in_addr));
+ }
+ }else
+ psin->sin_addr.s_addr = htonl(INADDR_ANY);
+ return 0;
+}
+
+int btTracker::_UpdatePeerList(char *buf,size_t bufsiz)
+{
+ char tmphost[MAXHOSTNAMELEN];
+ const char *ps;
+ size_t i,pos,tmpport;
+ size_t cnt = 0;
+
+ struct sockaddr_in addr;
+
+ if( decode_query(buf,bufsiz,"failure reason",&ps,&i,(int64_t*)0,QUERY_STR) ){
+ char failreason[1024];
+ if( i < 1024 ){
+ memcpy(failreason, ps, i);
+ failreason[i] = '\0';
+ }else{
+ memcpy(failreason, ps, 1000);
+ failreason[1000] = '\0';
+ strcat(failreason,"...");
+ }
+ CONSOLE.Warning(1, "TRACKER FAILURE REASON: %s", failreason);
+ return -1;
+ }
+ if( decode_query(buf,bufsiz,"warning message",&ps,&i,(int64_t*)0,QUERY_STR) ){
+ char warnmsg[1024];
+ if( i < 1024 ){
+ memcpy(warnmsg, ps, i);
+ warnmsg[i] = '\0';
+ }else{
+ memcpy(warnmsg, ps, 1000);
+ warnmsg[1000] = '\0';
+ strcat(warnmsg,"...");
+ }
+ CONSOLE.Warning(2, "TRACKER WARNING: %s", warnmsg);
+ }
+
+ m_peers_count = m_seeds_count = 0;
+
+ if( decode_query(buf,bufsiz,"tracker id",&ps,&i,(int64_t*)0,QUERY_STR) ){
+ if( i <= PEER_ID_LEN ){
+ memcpy(m_trackerid, ps, i);
+ m_trackerid[i] = '\0';
+ }else{
+ memcpy(m_trackerid, ps, PEER_ID_LEN);
+ m_trackerid[PEER_ID_LEN] = '\0';
+ }
+ }
+
+ if( !decode_query(buf, bufsiz, "interval", (const char**)0, &i,
+ (int64_t*)0, QUERY_INT) )
+ return -1;
+
+ if(m_interval != (time_t)i) m_interval = (time_t)i;
+ if(m_default_interval != (time_t)i) m_default_interval = (time_t)i;
+
+ if( decode_query(buf, bufsiz, "complete", (const char**)0, &i,
+ (int64_t*)0, QUERY_INT) )
+ m_seeds_count = i;
+ if( decode_query(buf, bufsiz, "incomplete", (const char**)0, &i,
+ (int64_t*)0, QUERY_INT) )
+ m_peers_count = m_seeds_count + i;
+ else{
+ if(arg_verbose && 0==m_seeds_count)
+ CONSOLE.Debug("Tracker did not supply peers count.");
+ m_peers_count = m_seeds_count;
+ }
+
+ pos = decode_query(buf, bufsiz, "peers", (const char**)0, (size_t *)0,
+ (int64_t*)0, QUERY_POS);
+
+ if( !pos ){
+ return -1;
+ }
+
+ if(4 > bufsiz - pos){ return -1; } // peers list 太小
+
+ buf += (pos + 1); bufsiz -= (pos + 1);
+
+ ps = buf-1;
+ if( *ps != 'l' ){ // binary peers section if not 'l'
+ addr.sin_family = AF_INET;
+ i = 0;
+ while( *ps != ':' ) i = i * 10 + (*ps++ - '0');
+ i /= 6;
+ ps++;
+ while( i-- > 0 ){
+ memcpy(&addr.sin_addr,ps,sizeof(struct in_addr));
+ memcpy(&addr.sin_port,ps+sizeof(struct in_addr),sizeof(unsigned short));
+ if( !Self.IpEquiv(addr) ){
+ cnt++;
+ IPQUEUE.Add(&addr);
+ }
+ ps += 6;
+ }
+ }
+ else
+ for( ; bufsiz && *buf!='e'; buf += pos, bufsiz -= pos ){
+ pos = decode_dict(buf,bufsiz,(char*)0);
+ if(!pos) break;
+ if( !decode_query(buf,pos,"ip",&ps,&i,(int64_t*)0,QUERY_STR) ||
+ MAXHOSTNAMELEN < i ) continue;
+ memcpy(tmphost,ps,i); tmphost[i] = '\0';
+
+ if( !decode_query(buf,pos,"port",(const char**)0,&tmpport,(int64_t*)0,
+ QUERY_INT) ) continue;
+
+ if( !decode_query(buf,pos,"peer id",&ps,&i,(int64_t*)0,QUERY_STR) &&
+ i != 20 ) continue;
+
+ if(_IPsin(tmphost,tmpport,&addr) < 0){
+ CONSOLE.Warning(3, "warn, detected invalid ip address %s.",tmphost);
+ continue;
+ }
+
+ if( !Self.IpEquiv(addr) ){
+ cnt++;
+ IPQUEUE.Add(&addr);
+ }
+ }
+
+ if( 0==m_peers_count ){
+ m_peers_count = cnt + 1; // include myself
+ m_f_boguspeercnt = 1;
+ }else m_f_boguspeercnt = 0;
+ if(arg_verbose) CONSOLE.Debug("new peers=%d; next check in %d sec",
+ (int)cnt, (int)m_interval);
+ return 0;
+}
+
+int btTracker::CheckReponse()
+{
+ char *pdata, *format;
+ ssize_t r;
+ size_t q, hlen, dlen;
+
+ r = m_reponse_buffer.FeedIn(m_sock);
+ time(&m_last_timestamp);
+
+ if( r > 0 ) return 0; // connection is still open; may have more data coming
+
+ q = m_reponse_buffer.Count();
+
+ if( !q ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ if( getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0 )
+ error = errno;
+ if( error != 0 ) CONSOLE.Warning(2,
+ "warn, received nothing from tracker: %s", strerror(error));
+ else CONSOLE.Warning(2, "warn, received nothing from tracker!");
+ Reset(15); // try again
+ return -1;
+ }
+
+ Reset( (-1 == r) ? 15 : 0 ); // can't reset socket before error check
+
+ hlen = Http_split(m_reponse_buffer.BasePointer(), q, &pdata,&dlen);
+
+ if( !hlen ){
+ CONSOLE.Warning(2, "warn, tracker reponse invalid. No html header found.");
+ return -1;
+ }
+
+ r = Http_reponse_code(m_reponse_buffer.BasePointer(),hlen);
+ if ( r != 200 ){
+ if( r == 301 || r == 302 ){
+ char redirect[MAXPATHLEN], ih_buf[20 * 3 + 1], pi_buf[20 * 3 + 1],
+ tmppath[MAXPATHLEN];
+
+ if( Http_get_header(m_reponse_buffer.BasePointer(), hlen, "Location",
+ redirect) < 0 )
+ return -1;
+
+ if( Http_url_analyse(redirect,m_host,&m_port,m_path) < 0 ){
+ CONSOLE.Warning(1,
+ "warn, tracker redirected to an invalid url %s", redirect);
+ return -1;
+ }else{
+ char *c = strstr(m_path, "?info_hash=");
+ if( !c ) c = strstr(m_path, "&info_hash=");
+ if( c ) *c = '\0';
+ if(arg_verbose) CONSOLE.Debug("tracker redirect to %s", redirect);
+ if( BuildBaseRequest() < 0 ) return -1;
+ }
+
+ if( Connect() < 0 ){
+ Reset(15);
+ return -1;
+ }else return 0;
+ }else if( r >= 400 ){
+ CONSOLE.Warning(2, "Tracker reponse code >= 400 !!!");
+ CONSOLE.Warning(2,
+ "The file is not registered on this tracker or may have been removed.");
+ CONSOLE.Warning(2,
+ "IF YOU CONTINUE TO GET THIS MESSAGE AND DOWNLOAD DOES NOT BEGIN, PLEASE STOP CTORRENT!");
+ if( pdata && dlen ){ // write(STDERR_FILENO, pdata, dlen);
+ CONSOLE.Warning(0, "Tracker reponse data DUMP:");
+ CONSOLE.Warning(0, "%s", pdata);
+ CONSOLE.Warning(0, "== DUMP OVER==");
+ }
+ return -1;
+ }else
+ return 0;
+ }
+
+ if( !m_f_started ) m_f_started = 1;
+ m_connect_refuse_click = 0;
+ m_ok_click++;
+
+ if ( !pdata ){
+ CONSOLE.Warning(2, "warn, peers list received from tracker is empty.");
+ return 0;
+ }
+ return _UpdatePeerList(pdata,dlen);
+}
+
+int btTracker::Initial()
+{
+ if(Http_url_analyse(BTCONTENT.GetAnnounce(),m_host,&m_port,m_path) < 0){
+ CONSOLE.Warning(1, "error, invalid tracker url format!");
+ return -1;
+ }
+
+ char chars[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ for(int i=0; i<8; i++)
+ m_key[i] = chars[random()%36];
+ m_key[8] = 0;
+
+ /* get local ip address */
+ struct sockaddr_in addr;
+ if( cfg_public_ip ){ // Get specified public address.
+ if( (addr.sin_addr.s_addr = inet_addr(cfg_public_ip)) == INADDR_NONE ){
+ struct hostent *h;
+ h = gethostbyname(cfg_public_ip);
+ memcpy(&addr.sin_addr, h->h_addr, sizeof(struct in_addr));
+ }
+ Self.SetIp(addr);
+ goto next_step;
+ }
+ if( cfg_listen_ip ){ // Get specified listen address.
+ addr.sin_addr.s_addr = cfg_listen_ip;
+ Self.SetIp(addr);
+ if( !IsPrivateAddress(cfg_listen_ip) ) goto next_step;
+ }
+ { // Try to get address corresponding to the hostname.
+ struct hostent *h;
+ char hostname[MAXHOSTNAMELEN];
+
+ if( gethostname(hostname, MAXHOSTNAMELEN) >= 0 ){
+// CONSOLE.Debug("hostname: %s", hostname);
+ if( h = gethostbyname(hostname) ){
+// CONSOLE.Debug("Host name: %s", h->h_name);
+// CONSOLE.Debug("Address: %s", inet_ntoa(*((struct in_addr *)h->h_addr)));
+ if( !IsPrivateAddress(((struct in_addr *)(h->h_addr))->s_addr) ||
+ !cfg_listen_ip ){
+ memcpy(&addr.sin_addr, h->h_addr, sizeof(struct in_addr));
+ Self.SetIp(addr);
+ }
+ }
+ }
+ }
+
+ next_step:
+ if( BuildBaseRequest() < 0 ) return -1;
+
+ return 0;
+}
+
+int btTracker::IsPrivateAddress(uint32_t addr)
+{
+ return (addr & htonl(0xff000000)) == htonl(0x0a000000) || // 10.x.x.x/8
+ (addr & htonl(0xfff00000)) == htonl(0xac100000) || // 172.16.x.x/12
+ (addr & htonl(0xffff0000)) == htonl(0xc0a80000) || // 192.168.x.x/16
+ (addr & htonl(0xff000000)) == htonl(0x7f000000); // 127.x.x.x/8
+}
+
+int btTracker::BuildBaseRequest()
+{
+ char ih_buf[20 * 3 + 1], pi_buf[20 * 3 + 1], tmppath[MAXPATHLEN];
+ const char *format;
+
+ strcpy(tmppath,m_path);
+ if(strchr(m_path, '?'))
+ format=REQ_URL_P1A_FMT;
+ else format=REQ_URL_P1_FMT;
+
+ char *opt = (char *)0;
+ if( cfg_public_ip ){
+ opt = new char[5+strlen(cfg_public_ip)];
+ strcpy(opt, "&ip=");
+ strcat(opt, cfg_public_ip);
+ }else{
+ struct sockaddr_in addr;
+ Self.GetAddress(&addr);
+ if( !IsPrivateAddress(addr.sin_addr.s_addr) ){
+ opt = new char[20];
+ strcpy(opt, "&ip=");
+ strcat(opt, inet_ntoa(addr.sin_addr));
+ }
+ }
+
+ if(MAXPATHLEN < snprintf((char*)m_path,MAXPATHLEN,format,
+ tmppath,
+ Http_url_encode(ih_buf,(char*)BTCONTENT.GetInfoHash(),20),
+ Http_url_encode(pi_buf,(char*)BTCONTENT.GetPeerId(),20),
+ opt ? opt : "",
+ cfg_listen_port,
+ m_key)){
+ return -1;
+ }
+
+ return 0;
+}
+
+int btTracker::Connect()
+{
+ ssize_t r;
+ time(&m_last_timestamp);
+
+ if(_s2sin(m_host,m_port,&m_sin) < 0) {
+ CONSOLE.Warning(2, "warn, get tracker's ip address failed.");
+ return -1;
+ }
+
+ m_sock = socket(AF_INET,SOCK_STREAM,0);
+ if(INVALID_SOCKET == m_sock) return -1;
+
+ // we only need to bind if we have specified an ip
+ // we need it to bind here before the connect!!!!
+ if ( cfg_listen_ip != 0 ) {
+ struct sockaddr_in addr;
+ // clear the struct as requested in the manpages
+ memset(&addr,0, sizeof(sockaddr_in));
+ // set the type
+ addr.sin_family = AF_INET;
+ // we want the system to choose port
+ addr.sin_port = 0;
+ // set the defined ip from the commandline
+ addr.sin_addr.s_addr = cfg_listen_ip;
+ // bind it or return...
+ if(bind(m_sock,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) != 0){
+ CONSOLE.Warning(1, "warn, can't set up tracker connection: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+
+ if(setfd_nonblock(m_sock) < 0){ CLOSE_SOCKET(m_sock); return -1; }
+
+ r = connect_nonb(m_sock,(struct sockaddr*)&m_sin);
+
+ if( r == -1 ){ CLOSE_SOCKET(m_sock); return -1; }
+ else if( r == -2 ) m_status = T_CONNECTING;
+ else{
+ if(arg_verbose) CONSOLE.Debug("Connected to tracker");
+ if( 0 == SendRequest() ) m_status = T_READY;
+ else{ CLOSE_SOCKET(m_sock); return -1; }
+ }
+ return 0;
+}
+
+int btTracker::SendRequest()
+{
+ char *event,*str_event[] = {"started","stopped","completed" };
+ char REQ_BUFFER[2*MAXPATHLEN];
+ struct sockaddr_in addr;
+
+ if( m_f_stoped )
+ event = str_event[1]; /* stopped */
+ else if( !m_f_started ){
+ if( BTCONTENT.IsFull() ) m_f_completed = 1;
+ event = str_event[0]; /* started */
+ }else if( BTCONTENT.IsFull() && !m_f_completed ){
+ if( Self.TotalDL() > 0 ) event = str_event[2]; /* download complete */
+ else event = (char*) 0; /* interval */
+ m_f_completed = 1; /* only send download complete once */
+ }else
+ event = (char*) 0; /* interval */
+
+ char opt1[20] = "&event=";
+ char opt2[12+PEER_ID_LEN] = "&trackerid=";
+
+ if( BTCONTENT.IsFull() ) m_totaldl = Self.TotalDL();
+ if(MAXPATHLEN < snprintf(REQ_BUFFER,MAXPATHLEN,REQ_URL_P2_FMT,
+ m_path,
+ event ? strncat(opt1,event,12) : "",
+ *m_trackerid ? strncat(opt2,m_trackerid,PEER_ID_LEN) : "",
+ (unsigned long long)(m_totalul = Self.TotalUL()),
+ (unsigned long long)m_totaldl,
+ (unsigned long long)(BTCONTENT.GetLeftBytes()),
+ (int)cfg_max_peers)){
+ return -1;
+ }
+
+ // if we have a tracker hostname (not just an IP), send a Host: header
+ if(_IPsin(m_host, m_port, &addr) < 0){
+ char REQ_HOST[MAXHOSTNAMELEN];
+ if(MAXHOSTNAMELEN < snprintf(REQ_HOST,MAXHOSTNAMELEN,"\r\nHost: %s",m_host))
+ return -1;
+ strcat(REQ_BUFFER, REQ_HOST);
+ }
+
+ strcat(REQ_BUFFER, "\r\nUser-Agent: ");
+ strcat(REQ_BUFFER, cfg_user_agent);
+
+ strcat(REQ_BUFFER,"\r\n\r\n");
+ // hc
+ //CONSOLE.Warning(0, "SendRequest: %s", REQ_BUFFER);
+
+ if( 0 !=
+ m_request_buffer.PutFlush(m_sock,REQ_BUFFER,strlen((char*)REQ_BUFFER)) ){
+ CONSOLE.Warning(2,
+ "warn, send request to tracker failed: %s", strerror(errno));
+ if( event == str_event[2] )
+ m_f_completed = 0; // failed sending completion event
+ return -1;
+ }else{
+ m_report_time = now;
+ m_report_dl = m_totaldl;
+ m_report_ul = m_totalul;
+ if(arg_verbose)
+ CONSOLE.Debug("Reported to tracker: %llu uploaded, %llu downloaded",
+ (unsigned long long)m_report_ul, (unsigned long long)m_report_dl);
+ }
+
+ return 0;
+}
+
+int btTracker::IntervalCheck(fd_set *rfdp, fd_set *wfdp)
+{
+ /* tracker communication */
+ if( T_FREE == m_status ){
+ if( INVALID_SOCKET != m_sock ){
+ FD_CLR(m_sock, rfdp);
+ FD_CLR(m_sock, wfdp);
+ }
+ if( now - m_last_timestamp >= m_interval ||
+ // Connect to tracker early if we run low on peers.
+ (WORLD.GetPeersCount() < cfg_min_peers &&
+ m_prevpeers >= cfg_min_peers && now - m_last_timestamp >= 15) ){
+ m_prevpeers = WORLD.GetPeersCount();
+
+ if(Connect() < 0){ Reset(15); return -1; }
+
+ FD_SET(m_sock, rfdp);
+ if( m_status == T_CONNECTING ) FD_SET(m_sock, wfdp);
+ }else if( now < m_last_timestamp ) m_last_timestamp = now; // time reversed
+ }else if( T_CONNECTING == m_status ){
+ FD_SET(m_sock, rfdp);
+ FD_SET(m_sock, wfdp);
+ }else if( INVALID_SOCKET != m_sock ){
+ FD_SET(m_sock, rfdp);
+ if( m_request_buffer.Count() ) FD_SET(m_sock, wfdp);
+ }
+ return m_sock;
+}
+
+int btTracker::SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds,
+ fd_set *rfdnextp, fd_set *wfdnextp)
+{
+ if( T_FREE == m_status ) return 0;
+
+ if( T_CONNECTING == m_status && FD_ISSET(m_sock,wfdp) ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ (*nfds)--;
+ FD_CLR(m_sock, wfdnextp);
+ if( FD_ISSET(m_sock, rfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock, rfdnextp);
+ }
+ if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0)
+ error = errno;
+ if( error ){
+ if( ECONNREFUSED == error ){
+ if(arg_verbose) CONSOLE.Debug("tracker connection refused");
+ m_connect_refuse_click++;
+ }else CONSOLE.Warning(2,
+ "warn, connect to tracker failed: %s", strerror(error));
+ Reset(15);
+ return -1;
+ }else{
+ if(arg_verbose) CONSOLE.Debug("Connected to tracker");
+ if( SendRequest() == 0 ) m_status = T_READY;
+ else { Reset(15); return -1; }
+ }
+ }else if( T_CONNECTING == m_status && FD_ISSET(m_sock,rfdp) ){
+ int error = 0;
+ socklen_t n = sizeof(error);
+ (*nfds)--;
+ FD_CLR(m_sock, rfdnextp);
+ if(getsockopt(m_sock, SOL_SOCKET,SO_ERROR,&error,&n) < 0)
+ error = errno;
+ CONSOLE.Warning(2, "warn, connect to tracker failed: %s", strerror(error));
+ Reset(15);
+ return -1;
+ }else if( INVALID_SOCKET != m_sock ){
+ if( FD_ISSET(m_sock, rfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock,rfdnextp);
+ SOCKET tmp_sock = m_sock;
+ int r = CheckReponse();
+ if( INVALID_SOCKET == m_sock ){
+ if( FD_ISSET(tmp_sock, wfdp) ){
+ (*nfds)--;
+ FD_CLR(tmp_sock,wfdnextp);
+ }
+ return r;
+ }
+ }
+ if( FD_ISSET(m_sock, wfdp) ){
+ (*nfds)--;
+ FD_CLR(m_sock,wfdnextp);
+ if( m_request_buffer.Count() && m_request_buffer.FlushOut(m_sock) < 0 ){
+ Reset(15);
+ return -1;
+ }
+ }
+ }else{ // failsafe
+ Reset(15);
+ return -1;
+ }
+ return 0;
+}
+
+void btTracker::Restart()
+{
+ m_f_stoped = m_f_restart = 0;
+
+ if( T_FINISHED == m_status ){
+ m_status = T_FREE;
+ m_f_started = 0;
+ m_interval = 15;
+ }
+}
+
+void btTracker::SetStoped()
+{
+ if( !m_f_started ){
+ m_f_stoped = 1;
+ m_status = T_FINISHED;
+ }else{
+ Reset(15);
+ m_f_stoped = 1;
+ }
+}
+
+void btTracker::RestartTracker()
+{
+ SetStoped(); // finish the tracker
+ // Now we need to wait until the tracker updates (T_FINISHED == m_status),
+ // then Tracker.Restart().
+ SetRestart();
+}
+
+size_t btTracker::GetPeersCount() const
+{
+ // includes seeds, so must always be >= 1 (myself!)
+ return (m_peers_count > m_seeds_count) ? m_peers_count :
+ (GetSeedsCount() + (BTCONTENT.IsFull() ? 0 : 1));
+}
+
+size_t btTracker::GetSeedsCount() const
+{
+ return m_seeds_count ? m_seeds_count : (BTCONTENT.IsFull() ? 1 : 0);
+}
+
diff --git a/tracker.h b/tracker.h
new file mode 100644
index 0000000..c901b52
--- a/dev/null
+++ b/tracker.h
@@ -0,0 +1,118 @@
+#ifndef TRACKER_H
+#define TRACKER_H
+
+#include "./def.h"
+#include <sys/types.h>
+
+#include "./bufio.h"
+
+#ifdef WINDOWS
+#include <Winsock2.h>
+
+#else
+#include <unistd.h>
+#include <netdb.h> // Solaris defines MAXHOSTNAMELEN here.
+#include <stdio.h> // autoconf manual: Darwin + others prereq for stdlib.h
+#include <stdlib.h> // autoconf manual: Darwin prereq for sys/socket.h
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/param.h>
+#endif
+
+#include <time.h>
+
+#include "btconfig.h"
+
+#define T_FREE 0
+#define T_CONNECTING 1
+#define T_READY 2
+#define T_FINISHED 3
+
+class btTracker
+{
+ private:
+ char m_host[MAXHOSTNAMELEN];
+ char m_path[MAXPATHLEN];
+ int m_port;
+ char m_key[9];
+ char m_trackerid[PEER_ID_LEN+1];
+
+ struct sockaddr_in m_sin;
+
+ unsigned char m_status:2;
+ unsigned char m_f_started:1;
+ unsigned char m_f_stoped:1;
+ unsigned char m_f_completed:1;
+ unsigned char m_f_restart:1;
+ unsigned char m_f_boguspeercnt:1;
+ unsigned char m_reserved:1;
+
+ time_t m_interval; // 与Tracker通信的时间间隔
+ time_t m_default_interval; // interval that the tracker tells us to wait
+ time_t m_last_timestamp; // 最后一次成功与Tracker通信的时间
+ size_t m_connect_refuse_click;
+
+ size_t m_ok_click; // tracker ok response counter
+ size_t m_peers_count; // total number of peers
+ size_t m_seeds_count; // total number of seeds
+ size_t m_prevpeers; // number of peers previously seen
+ time_t m_report_time;
+ uint64_t m_totaldl, m_totalul, m_report_dl, m_report_ul;
+
+ SOCKET m_sock;
+ BufIo m_request_buffer, m_reponse_buffer;
+
+ int _IPsin(char *h, int p, struct sockaddr_in *psin);
+ int _s2sin(char *h,int p,struct sockaddr_in *psin);
+ int _UpdatePeerList(char *buf,size_t bufsiz);
+ int IsPrivateAddress(uint32_t addr);
+
+ int BuildBaseRequest();
+ int Connect();
+ int SendRequest();
+ int CheckReponse();
+ void Restart();
+
+ public:
+ btTracker();
+ ~btTracker();
+
+ int Initial();
+
+ void Reset(time_t new_interval);
+
+ unsigned char GetStatus() { return m_status; }
+ void SetStatus(unsigned char s) { m_status = s; }
+
+ SOCKET GetSocket() { return m_sock; }
+
+ void RestartTracker();
+ void SetRestart() { m_f_restart = 1; }
+ void ClearRestart() { m_f_restart = 0; }
+ int IsRestarting() const { return m_f_restart; }
+ int IsQuitting() const { return m_f_stoped; }
+ void SetStoped();
+
+ int IntervalCheck(fd_set* rfdp, fd_set *wfdp);
+ int SocketReady(fd_set *rfdp, fd_set *wfdp, int *nfds,
+ fd_set *rfdnextp, fd_set *wfdnextp);
+
+ size_t GetRefuseClick() const { return m_connect_refuse_click; }
+ size_t GetOkClick() const { return m_ok_click; }
+ size_t GetPeersCount() const;
+ size_t GetSeedsCount() const;
+ void AdjustPeersCount() {
+ if(m_f_boguspeercnt && m_peers_count) m_peers_count--; }
+ time_t GetInterval() const { return m_default_interval; }
+
+ time_t GetReportTime() const { return m_report_time; }
+ uint64_t GetReportDL() const { return m_report_dl; }
+ uint64_t GetReportUL() const { return m_report_ul; }
+ void CountDL(size_t nbytes) { m_totaldl += nbytes; }
+ void CountUL(size_t nbytes) { m_totalul += nbytes; }
+};
+
+extern btTracker Tracker;
+
+#endif
diff --git a/version.m4 b/version.m4
new file mode 100644
index 0000000..738561e
--- a/dev/null
+++ b/version.m4
@@ -0,0 +1,5 @@
+m4_define([m4_PACKAGE_NAME], [CheaTorrent])
+m4_define([m4_PACKAGE_TARNAME], [cheatorrent])
+m4_define([m4_PACKAGE_VERSION], [v1.0])
+m4_define([m4_PACKAGE_BUGREPORT], [lol])
+