[svn] Initial revision

This commit is contained in:
kwget 1999-12-01 23:42:23 -08:00
parent c5f1f6a779
commit 31d6616c48
108 changed files with 50333 additions and 0 deletions

16
AUTHORS Normal file
View File

@ -0,0 +1,16 @@
Authors of GNU Wget.
[ Note that this file does not attempt to list all the contributors to
Wget; look at the ChangeLog for that. This is a list of people who
contributed sizeable amounts of code and assigned the copyright to the
FSF. ]
Hrvoje Niksic. Designed and implemented Wget.
Gordon Matzigkeit. Wrote netrc.c and netrc.h.
Darko Budor. Added Windows support, wrote wsstartup.c, wsstartup.h
and windecl.h.
Junio Hamano. Added support for FTP Opie and HTTP digest
authentication.

339
COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
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) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<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.

211
ChangeLog Normal file
View File

@ -0,0 +1,211 @@
1998-06-23 Dave Love <d.love@dl.ac.uk>
* configure.in (exext): Define.
1998-06-06 Hrvoje Niksic <hniksic@srce.hr>
* configure.in: Check for access().
1998-05-20 Hrvoje Niksic <hniksic@srce.hr>
* po/hr.po: Some fixes, as per suggestions by Francois Pinard.
1998-05-19 Dominique Delamarre <dominique.delamarre@hol.fr>
* po/fr.po: New file.
1998-05-19 Toomas Soome <tsoome@ut.ee>
* po/et.po: Updated.
1998-05-11 Simos KSenitellis <simos@teiath.gr>
* po/el.po: New file.
1998-05-09 Hrvoje Niksic <hniksic@srce.hr>
* aclocal.m4 (WGET_WITH_NLS): Print available catalogs.
1998-05-09 Toomas Soome <tsoome@ut.ee>
* po/et.po: New file.
1998-05-06 Douglas E. Wegscheid <wegscd@whirlpool.com>
* configure.bat: set up for either Borland or Visual C
* windows/wget.dep: new file
* windows/Makefile.*: use wget.dep
* rename windows/Makefile.bor to Makefile.src.bor
1998-05-06 Douglas E. Wegscheid <wegscd@whirlpool.com>
* windows/makefile.bor: Updated.
* windows/Makefile.src: Ditto.
1998-04-30 Douglas E. Wegscheid <wegscd@whirlpool.com>
* windows/config.h.bor: New file.
* windows/makefile.bor: New file.
1998-04-27 John Burden <john@futuresguide.com>
* windows/Makefile.*: Cleanup.
1998-04-27 Gregor Hoffleit <flight@mathi.uni-heidelberg.de>
* configure.in: Check for PID_T.
1998-04-19 Giovanni Bortolozzo <borto@dei.unipd.it>
* po/it.po: Updated.
1998-04-19 Jan Prikryl <prikryl@cg.tuwien.ac.at>
* po/cs.po: Updated.
1998-04-19 Wanderlei Cavassin <cavassin@conectiva.com.br>
* po/pt_BR.po: Updated.
1998-04-08 Stefan Hornburg <racke@gundel.han.de>
* Makefile (dist): New target.
1998-04-08 Wanderlei Cavassin <cavassin@conectiva.com.br>
* po/pt_BR.po: Updated.
1998-04-04 Hrvoje Niksic <hniksic@srce.hr>
* aclocal.m4 (WGET_WITH_NLS): Renamed USE_NLS to HAVE_NLS.
* ABOUT-NLS: Removed.
* Makefile.in (stamp-h): Clean up stamp-h-related dependencies.
Don't attempt to write to stamp-h.in.
* aclocal.m4 (WGET_PROCESS_PO): Reset srcdir to ac_given_srcdir.
1998-04-03 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (distclean-top): Remove stamp-h.
1998-04-02 Robert Schmidt <rsc@vingmed.no>
* po/no.po: New file.
1998-04-01 Hrvoje Niksic <hniksic@srce.hr>
* configure.in: New option `--disable-debug'.
1998-03-31 Hrvoje Niksic <hniksic@srce.hr>
* configure.in: Check for endianness.
1998-03-29 Hrvoje Niksic <hniksic@srce.hr>
* aclocal.m4 (WGET_PROCESS_PO): Use echo instead of AC_MSG_RESULT.
1998-03-28 Hrvoje Niksic <hniksic@srce.hr>
* aclocal.m4 (WGET_WITH_NLS): Disable USE_NLS if gettext is
unavailable.
* aclocal.m4: Renamed AM_STRUCT_UTIMBUF to WGET_STRUCT_UTIMBUF;
renamed AM_WITH_NLS to WGET_WITH_NLS.
* aclocal.m4: Eliminate POSUBS.
1998-03-17 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in: config.h* -> src/config.h*
* configure.in: Check for vsnprintf().
* po/POTFILES.in: Updated.
1998-03-16 Hrvoje Niksic <hniksic@srce.hr>
* po/POTFILES.in: Removed extraneous newline at end of line, which
caused an error in `Makefile' which Sun make choked on.
1998-03-16 Jan Prikryl <prikryl@cg.tuwien.ac.at>
* po/cs.po: New file.
1998-03-12 Wanderlei Cavassin <cavassin@conectiva.com.br>
* po/pt_BR.po: New file.
1998-03-07 Hrvoje Niksic <hniksic@srce.hr>
* PROBLEMS: New file.
1998-02-22 Karl Eichwalder <ke@suse.de>
* po/Makefile.in.in (install-data-yes): Fix creation of
directories for LC_MESSAGE files.
1998-02-22 Hrvoje Niksic <hniksic@srce.hr>
* configure.in: Removed `-Wno-switch' for gcc.
* po/Makefile.in.in (install-data-yes): Use mkinstalldirs to
create the directory first.
1998-02-21 Karl Eichwalder <karl@suse.de>
* po/de.po: Updated.
1998-02-19 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (check): New empty target.
1998-02-11 Hrvoje Niksic <hniksic@srce.hr>
* po/it.po: New file, by Antonio Rosella.
1998-02-08 Hrvoje Niksic <hniksic@srce.hr>
* aclocal.m4: Cleaned up.
* po/hr.po: Updated.
* configure.in: Removed check for POSIXized ISC.
1998-02-08 Karl Eichwalder <karl@suse.de>
* po/de.po: Updated.
1998-02-07 Karl Eichwalder <ke@suse.de>
* Makefile.in (install.info uninstall.info install.man
uninstall.man install.wgetrc): Use it.
* Makefile.in (install.mo): New target.
1998-02-03 Karl Eichwalder <ke@suse.de>
* po/POTFILES.in: Touch it (needed for NLS); add src/ftp.c,
src/getopt.c, src/host.c, src/html.c, src/http.c, src/init.c,
src/main.c, src/mswindows.c, src/netrc.c, src/recur.c, src/retr.c,
src/url.c, and src/utils.c.
* intl/po2tbl.sed.in: Add from gettext-0.10.32 (needed for NLS).
* po/Makefile.in.in: Add from gettext-0.10.32.
* Makefile.in (SUBDIRS): Add po/.
* configure.in (ALL_LINGUAS): New variable. Add "de" and "hr".
(AM_GNU_GETTEXT): Add.
(AC_OUTPUT): Add po/Makefile.in; run the sed command.
* aclocal.m4 (AM_WITH_NLS, AM_GNU_GETTEXT, AM_LC_MESSAGES,
AM_PATH_PROG_WITH_TEST): from gettext-0.10.32.

75
INSTALL Normal file
View File

@ -0,0 +1,75 @@
-*- text -*-
Installation Procedure
0) Preparation
To build and install GNU Wget, you need to unpack the archive (which
you have presumably done, since you are reading this), and read on.
Like most GNU utilities, Wget uses the GNU Autoconf mechanism for
build and installation; those of you familiar with compiling GNU
software will feel at home.
1) Configuration
To configure Wget, run the configure script provided with the
distribution. You may use all the standard arguments configure
scripts take. The most important ones are:
--help print help message
--prefix=PREFIX install architecture-independent files in PREFIX
(/usr/local by default)
--bindir=DIR user executables in DIR (PREFIX/bin)
--infodir=DIR info documentation in DIR [PREFIX/info]
--mandir=DIR man documentation in DIR [PREFIX/man]
--build=BUILD configure for building on BUILD [BUILD=HOST]
--host=HOST configure for HOST [guessed]
--target=TARGET configure for TARGET [TARGET=HOST]
--enable and --with options recognized (mostly Wget-specific):
--with-socks use the socks library
--disable-opie disable support for opie or s/key FTP login
--disable-digest disable support for HTTP digest authorization
--disable-debug disable support for debugging output
--disable-nls do not use Native Language Support
So, if you want to configure Wget for installation in your home
directory, you can type:
./configure --prefix=$HOME
You can customize many default settings by editing Makefile and
config.h. The program will work very well without your touching these
files, but it is useful to have a look at things you can change there.
If you use socks, it is useful to add -L/usr/local/lib (or wherever
the socks library is installed) to LDFLAGS in Makefile.
To configure Wget on Windows, run configure.bat and follow the
instructions in the windows/ directory. If this doesn't work for any
reason, talk to the Windows developers listed in `windows/README'; I
do not maintain the port.
2) Compilation
To compile the program, type make and cross your fingers. If you do
not have an ANSI compiler, Wget will try to KNR-ize its sources "on
the fly". This should make GNU Wget compilable virtually anywhere.
After the compilation a ready to use `wget' executable should reside
in the src directory. I do not have any kind of test-suite as of this
moment, but it should be easy enough to test whether the basic stuff
works.
3) Installation
Use `make install' to install GNU Wget to directories specified to
configure (/usr/local/* by default).
The standard installation process will copy the wget binary to
/usr/local/bin, install the info pages (wget.info*) to
/usr/local/info. You can customize the directories either through the
configuration process or making the necessary changes in the Makefile.
To delete the files created by Wget installation, you can use make
uninstall.

28
MACHINES Normal file
View File

@ -0,0 +1,28 @@
This files lists the architectures on which this version of GNU Wget
was tried on. If you compile Wget on a new architecture, please drop
me a note, or send a patch to this file.
Sun SunOS, Solaris (sparc-sun-solaris*, sparc-sun-sunos*)
GNU/Linux (i[3456]86-*-linux*)
DEC Ultrix, Digital Unix (mips-dec-ultrix*, alpha-dec-osf*)
HP BSD (m68k-hp-bsd)
HP HPUX (hppa1.0-hp-hpux7.00, hppa1.1-hp-hpux9.01 and others)
IBM AIX (powerpc-ibm-aix4.1.4.0)
Amiga NetBSD (m68k-cbm-netbsd1.2)
SGI IRIX (mips-sgi-irix4.0.5, mips-sgi-irix5.3)
SCO Unix (i586-pc-sco3.2v5.0.4)
NeXTStep 3.3 Intel (i386-next-nextstep3)
FreeBSD (i386-unknown-freebsd2.2.6)
Windows 95/NT (i[3456]86)

16
MAILING-LIST Normal file
View File

@ -0,0 +1,16 @@
-*- text -*-
Mailing List Info
Thanks to Karsten Thygesen, Wget has its own mailing list for
discussion and announcements. The list address is hosted at Sunsite
Denmark, <wget@sunsite.auc.dk>. To subscribe, send mail to
<wget-subscribe@sunsite.auc.dk>.
The list is fairly low-volume -- one or two messages per day and with
sporadic periods of intensive activity. If you are interested in
using or hacking Wget, or wish to read the important announcements,
you are very welcome to subscribe.
The list is archived at <URL:http://fly.cc.fer.hr/archive/wget>.

170
Makefile.in Normal file
View File

@ -0,0 +1,170 @@
# Makefile for `Wget' utility
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: @VERSION@
#
SHELL = /bin/sh
@SET_MAKE@
srcdir = @srcdir@
VPATH = @srcdir@
#
# User configuration section
#
#
# Install variables
#
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
infodir = @infodir@
sysconfdir = @sysconfdir@
mandir = @mandir@
manext = 1
localedir = $(prefix)/share/locale
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
DEFS = @DEFS@ -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@
#
# End of user configuration section. There should be no need to change
# anything below this line.
#
DISTNAME = wget-@VERSION@
RM = rm -f
# These are used for maintenance only, so they are safe without
# special autoconf cruft.
FIND = find
GZIP = gzip
TAR = tar
# flags passed to recursive makes in subdirectories
MAKEDEFS = CC='$(CC)' CPPFLAGS='$(CPPFLAGS)' DEFS='$(DEFS)' \
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' LIBS='$(LIBS)' \
prefix='$(prefix)' exec_prefix='$(exec_prefix)' bindir='$(bindir)' \
infodir='$(infodir)' mandir='$(mandir)' manext='$(manext)'
# subdirectories in the distribution
SUBDIRS = src doc po util
# default target
all: src/config.h Makefile $(SUBDIRS)
check: all
$(SUBDIRS): FORCE
cd $@ && $(MAKE) $(MAKEDEFS)
# install everything
install: install.bin install.info install.wgetrc install.mo # install.man
# install/uninstall the binary
install.bin uninstall.bin:
cd src && $(MAKE) $(MAKEDEFS) $@
# install/uninstall the info/man pages
install.info uninstall.info install.man uninstall.man install.wgetrc:
cd doc && $(MAKE) $(MAKEDEFS) $@
# Install `.mo' files
install.mo:
cd po && $(MAKE) $(MAKEDEFS) $@
# create tag files for Emacs
TAGS:
cd src && $(MAKE) $@
dist: $(srcdir)/configure DISTFILES
mkdir $(DISTNAME)
for d in `$(FIND) . -type d ! -name RCS -print`; do \
if [ "$$d" != "." -a "$$d" != "./$(DISTNAME)" ]; then \
mkdir $(DISTNAME)/$$d; \
fi; \
done
for f in `cat DISTFILES`; do \
ln $(srcdir)/$$f $(DISTNAME)/$$f || \
{ echo copying $$f; cp -p $(srcdir)/$$f $(DISTNAME)/$$f ; } \
done
(cd $(DISTNAME); $(MAKE) distclean)
$(TAR) chvf - $(DISTNAME) | $(GZIP) -c --best >$(DISTNAME).tar.gz
$(RM) -r $(DISTNAME)
$(RM) DISTFILES
DISTFILES: FORCE
rm -rf $(DISTNAME)
(cd $(srcdir); find . ! -type d -print) \
| sed '/\/RCS\//d; \
/$@/d; \
/\.tar.*/d; \
s/^.\///; /^\.$$/d;' \
| sort | uniq > $@
#
# Cleanup dependencies
#
clean: clean-recursive clean-top
distclean: distclean-recursive distclean-top
realclean: realclean-recursive realclean-top
clean-top:
$(RM) *~ *.bak $(DISTNAME).tar.gz
distclean-top: clean-top
$(RM) Makefile config.status config.log config.cache stamp-h
realclean-top: distclean-top
clean-recursive distclean-recursive realclean-recursive:
for subdir in $(SUBDIRS); do \
target=`echo $@ | sed s/-recursive//`; \
(cd $$subdir && $(MAKE) $(MAKEDEFS) $$target) || exit 1; \
done
#
# Dependencies for maintenance
#
Makefile: Makefile.in config.status
CONFIG_HEADERS= ./config.status
config.status: configure
./config.status --recheck
configure: configure.in aclocal.m4
cd $(srcdir) && autoconf
src/config.h: stamp-h
stamp-h: src/config.h.in config.status
CONFIG_FILES= CONFIG_HEADERS=src/config.h ./config.status
src/config.h.in: stamp-h.in
stamp-h.in: configure.in aclocal.m4
echo timestamp > $@
FORCE:

238
NEWS Normal file
View File

@ -0,0 +1,238 @@
GNU Wget NEWS -- history of user-visible changes.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
See the end for copying conditions.
Please send GNU Wget bug reports to <bug-wget@gnu.org>.
* Wget 1.5.3 is a bugfix release with no user-visible changes.
* Wget 1.5.2 is a bugfix release with no user-visible changes.
* Wget 1.5.1 is a bugfix release with no user-visible changes.
* Changes in Wget 1.5.0
** Wget speaks many languages!
On systems with gettext(), Wget will output messages in the language
set by the current locale, if available. At this time we support
Czech, German, Croatian, Italian, Norwegian and Portuguese.
** Opie (Skey) is now supported with FTP.
** HTTP Digest Access Authentication (RFC2069) is now supported.
** The new `-b' option makes Wget go to background automatically.
** The `-I' and `-X' options now accept wildcard arguments.
** The `-w' option now accepts suffixes `s' for seconds, `m' for
minutes, `h' for hours, `d' for days and `w' for weeks.
** Upon getting SIGHUP, the whole previous log is now copied to
`wget-log'.
** Wget now understands proxy settings with explicit usernames and
passwords, e.g. `http://user:password@proxy.foo.com/'.
** You can use the new `--cut-dirs' option to make Wget create less
directories.
** The `;type=a' appendix to FTP URLs is now recognized. For
instance, the following command will retrieve the welcoming message in
ASCII type transfer:
wget "ftp://ftp.somewhere.com/welcome.msg;type=a"
** `--help' and `--version' options have been redone to to conform to
standards set by other GNU utilities.
** Wget should now be compilable under MS Windows environment. MS
Visual C++ and Watcom C have been used successfully.
** If the file length is known, percentages are displayed during
download.
** The manual page, now hopelessly out of date, is no longer
distributed with Wget.
* Wget 1.4.5 is a bugfix release with no user-visible changes.
* Wget 1.4.4 is a bugfix release with no user-visible changes.
* Changes in Wget 1.4.3
** Wget is now a GNU utility.
** Can do passive FTP.
** Reads .netrc.
** Info documentation expanded.
** Compiles on pre-ANSI compilers.
** Global wgetrc now goes to /usr/local/etc (i.e. $sysconfdir).
** Lots of bugfixes.
* Changes in Wget 1.4.2
** New mirror site at ftp://sunsite.auc.dk/pub/infosystems/wget/,
thanks to Karsten Thygesen.
** Mailing list! Mail to wget-request@sunsite.auc.dk to subscribe.
** New option --delete-after for proxy prefetching.
** New option --retr-symlinks to retrieve symbolic links like plain
files.
** rmold.pl -- script to remove files deleted on the remote server
** --convert-links should work now.
** Minor bugfixes.
* Changes in Wget 1.4.1
** Minor bugfixes.
** Added -I (the opposite of -X).
** Dot tracing is now customizable; try wget --dot-style=binary
* Changes in Wget 1.4.0
** Wget 1.4.0 [formerly known as Geturl] is an extensive rewrite of
Geturl. Although many things look suspiciously similar, most of the
stuff was rewritten, like recursive retrieval, HTTP, FTP and mostly
everything else. Wget should be now easier to debug, maintain and,
most importantly, use.
** Recursive HTTP should now work without glitches, even with Location
changes, server-generated directory listings and other naughty stuff.
** HTTP regetting is supported on servers that support Range
specification. WWW authorization is supported -- try
wget http://user:password@hostname/
** FTP support was rewritten and widely enhanced. Globbing should now
work flawlessly. Symbolic links are created locally. All the
information the Unix-style ls listing can give is now recognized.
** Recursive FTP is supported, e.g.
wget -r ftp://gnjilux.cc.fer.hr/pub/unix/util/
** You can specify "rejected" directories, to which you do not want to
enter, e.g. with wget -X /pub
** Time-stamping is supported, with both HTTP and FTP. Try wget -N URL.
** A new texinfo reference manual is provided. It can be read with
Emacs, standalone info, or converted to HTML, dvi or postscript.
** Fixed a long-standing bug, so that Wget now works over SLIP
connections.
** You can have a system-wide wgetrc (/usr/local/lib/wgetrc by
default). Settings in $HOME/.wgetrc override the global ones, of
course :-)
** You can set up quota in .wgetrc to prevent sucking too much
data. Try `quota = 5M' in .wgetrc (or quota = 100K if you want your
sysadmin to like you).
** Download rate is printed after retrieval.
** Wget now sends the `Referer' header when retrieving
recursively.
** With the new --no-parent option Wget can retrieve FTP recursively
through a proxy server.
** HTML parser, as well as the whole of Wget was rewritten to be much
faster and less memory-consuming (yes, both).
** Absolute links can be converted to relative links locally. Check
wget -k.
** Wget catches hangup, filtering the output to a log file and
resuming work. Try kill -HUP %?wget.
** User-defined headers can be sent. Try
wget http://fly.cc.her.hr/ --header='Accept-Charset: iso-8859-2'
** Acceptance/Rejection lists may contain wildcards.
** Wget can display HTTP headers and/or FTP server response with the
new `-S' option. It can save the original HTTP headers with `-s'.
** socks library is now supported (thanks to Antonio Rosella
<Antonio.Rosella@agip.it>). Configure with --with-socks.
** There is a nicer display of REST-ed output.
** Many new options (like -x to force directory hierarchy, or -m to
turn on mirroring options).
** Wget is now distributed under GNU General Public License (GPL).
** Lots of small features I can't remember. :-)
** A host of bugfixes.
* Changes in Geturl 1.3
** Added FTP globbing support (ftp://fly.cc.fer.hr/*)
** Added support for no_proxy
** Added support for ftp://user:password@host/
** Added support for %xx in URL syntax
** More natural command-line options
** Added -e switch to execute .geturlrc commands from the command-line
** Added support for robots.txt
** Fixed some minor bugs
* Geturl 1.2 is a bugfix release with no user-visible changes.
* Changes in Geturl 1.1
** REST supported in FTP
** Proxy servers supported
** GNU getopt used, which enables command-line arguments to be ordered
as you wish, e.g. geturl http://fly.cc.fer.hr/ -vo log is the same as
geturl -vo log http://fly.cc.fer.hr/
** Netscape-compatible URL syntax for HTTP supported: host[:port]/dir/file
** NcFTP-compatible colon URL syntax for FTP supported: host:/dir/file
** <base href="xxx"> supported
** autoconf supported
----------------------------------------------------------------------
Copyright information:
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim
copies of this document as received, in any medium, provided that
the copyright notice and this permission notice are preserved, thus
giving the recipient permission to redistribute in turn.
Permission is granted to distribute modified versions of this
document, or of portions of it, under the above conditions,
provided also that they carry prominent notices stating who last
changed them.

80
README Normal file
View File

@ -0,0 +1,80 @@
-*- text -*-
GNU Wget README
GNU Wget is a free network utility to retrieve files from the World
Wide Web using HTTP and FTP, the two most widely used Internet
protocols. It works non-interactively, thus enabling work in the
background, after having logged off.
The recursive retrieval of HTML pages, as well as FTP sites is
supported -- you can use Wget to make mirrors of archives and home
pages, or traverse the web like a WWW robot (Wget understands
/robots.txt).
Wget works exceedingly well on slow or unstable connections, keeping
getting the document until it is fully retrieved. Re-getting files
from where it left off works on servers (both HTTP and FTP) that
support it. Matching of wildcards and recursive mirroring of
directories are available when retrieving via FTP. Both HTTP and FTP
retrievals can be time-stamped, thus Wget can see if the remote file
has changed since last retrieval and automatically retrieve the new
version if it has.
Wget supports proxy servers, which can lighten the network load, speed
up retrieval and provide access behind firewalls. If you are behind a
firewall that requires the use of a socks style gateway, you can get
the socks library and compile wget with support for socks.
Most of the features are configurable, either through command-line
options, or via initialization file .wgetrc. Wget allows you to
install a global startup file (/usr/local/etc/wgetrc by default) for
site settings.
Wget works under almost all modern Unix variants and, unlike many
other similar utilities, is written entirely in C, thus requiring no
additional software (like perl). As Wget uses the GNU Autoconf, it is
easily built on and ported to other Unix's. Installation procedure is
described in the INSTALL file.
Like all GNU utilities, the latest version of Wget can be found at the
master GNU archive site prep.ai.mit.edu, and its mirrors. For
example, Wget 1.5.2 is at:
<URL:ftp://prep.ai.mit.edu/pub/gnu/wget-1.5.2.tar.gz>.
The latest version is also available via FTP from the maintainer's
machine, at:
<URL:ftp://gnjilux.cc.fer.hr/pub/unix/util/wget/wget.tar.gz>.
This location is mirrored at:
<URL:ftp://sunsite.auc.dk/pub/infosystems/wget/> and
<URL:http://sunsite.auc.dk/ftp/pub/infosystems/wget/>.
Please report bugs in Wget to <bug-wget@prep.ai.mit.edu>.
Wget has a own mailing list at <wget@sunsite.auc.dk>. To subscribe,
mail to <wget-subscribe@sunsite.auc.dk>.
Wget is free in all senses -- it is freely redistributable, and no
payment is required. If you still wish to donate money to the author,
or wish to sponsor implementation of specific features, please email
me at <hniksic@srce.hr>.
AUTHOR: Hrvoje Niksic <URL:mailto:hniksic@srce.hr>
Copyright (C) 1995, 1996, 1997, 1998 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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

78
TODO Normal file
View File

@ -0,0 +1,78 @@
Hey Emacs, this is -*- outline -*- mode
This is the todo list for Wget. I don't have any time-table of when I
plan to implement these features; this is just a list of things I'd
like to see in Wget. I'll work on some of them myself, and I will
accept patches in their direction. The items are not listed in any
particular order. Not all of them are user-visible changes.
* Make `-k' convert <base href=...> too.
* Add option to clobber existing file names (no `.N' suffixes).
* Introduce a concept of "boolean" options. For instance, every
boolean option `--foo' would have a `--no-foo' equivalent for
turning it off. Get rid of `--foo=no' stuff. Short options would
be handled as `-x' vs. `-nx'.
* Implement "thermometer" display (not all that hard; use an
alternative show_progress() if the output goes to a terminal.)
* Add option to only list wildcard matches without doing the download.
* Add case-insensitivity as an option.
* Add option to download all files needed to display a web page
(images, etc.)
* Handle MIME types correctly. There should be an option to (not)
retrieve files based on MIME types, e.g. `--accept-types=image/*'.
* Implement "persistent" retrieving. In "persistent" mode Wget should
treat most of the errors as transient.
* Allow time-stamping by arbitrary date.
* Fix Unix directory parser to allow for spaces in file names.
* Allow size limit to files.
* -k should convert convert relative references to absolute if not
downloaded.
* Recognize HTML comments correctly. Add more options for handling
bogus HTML found all over the 'net.
* Implement breadth-first retrieval.
* Download to .in* when mirroring.
* Add an option to delete or move no-longer-existent files when
mirroring.
* Implement a switch to avoid downloading multiple files (e.g. x and
x.gz).
* Implement uploading (--upload URL?) in FTP and HTTP.
* Rewrite FTP code to allow for easy addition of new commands. It
should probably be coded as a simple DFA engine.
* Recognize more FTP servers (VMS).
* Make HTTP timestamping use If-Modified-Since facility.
* Implement better spider options.
* Add more protocols (e.g. gopher and news), implementing them in a
modular fashion.
* Implement a concept of "packages" a la mirror.
* Implement correct RFC1808 URL parsing.
* Implement HTTP cookies.
* Implement more HTTP/1.1 bells and whistles (ETag, Content-MD5 etc.)
* Support SSL encryption through SSLeay.

251
aclocal.m4 vendored Normal file
View File

@ -0,0 +1,251 @@
AC_DEFUN(AM_C_PROTOTYPES,
[AC_REQUIRE([AM_PROG_CC_STDC])
AC_BEFORE([$0], [AC_C_INLINE])
AC_MSG_CHECKING([for function prototypes])
if test "$am_cv_prog_cc_stdc" != no; then
AC_MSG_RESULT(yes)
AC_DEFINE(PROTOTYPES)
U= ANSI2KNR=
else
AC_MSG_RESULT(no)
U=_ ANSI2KNR=./ansi2knr
# Ensure some checks needed by ansi2knr itself.
AC_HEADER_STDC
AC_CHECK_HEADERS(string.h)
fi
AC_SUBST(U)dnl
AC_SUBST(ANSI2KNR)dnl
])
# serial 1
# @defmac AC_PROG_CC_STDC
# @maindex PROG_CC_STDC
# @ovindex CC
# If the C compiler in not in ANSI C mode by default, try to add an option
# to output variable @code{CC} to make it so. This macro tries various
# options that select ANSI C on some system or another. It considers the
# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
# handles function prototypes correctly.
#
# If you use this macro, you should check after calling it whether the C
# compiler has been set to accept ANSI C; if not, the shell variable
# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
# code in ANSI C, you can make an un-ANSIfied copy of it by using the
# program @code{ansi2knr}, which comes with Ghostscript.
# @end defmac
AC_DEFUN(AM_PROG_CC_STDC,
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
AC_CACHE_VAL(am_cv_prog_cc_stdc,
[am_cv_prog_cc_stdc=no
ac_save_CC="$CC"
# Don't try gcc -ansi; that turns off useful extensions and
# breaks some systems' header files.
# AIX -qlanglvl=ansi
# Ultrix and OSF/1 -std1
# HP-UX -Aa -D_HPUX_SOURCE
# SVR4 -Xc -D__EXTENSIONS__
for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
AC_TRY_COMPILE(
[#if !defined(__STDC__) || __STDC__ != 1
choke me
#endif
/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/stat.h>
#endif
], [
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};],
[am_cv_prog_cc_stdc="$ac_arg"; break])
done
CC="$ac_save_CC"
])
AC_MSG_RESULT($am_cv_prog_cc_stdc)
case "x$am_cv_prog_cc_stdc" in
x|xno) ;;
*) CC="$CC $am_cv_prog_cc_stdc" ;;
esac
])
AC_DEFUN(WGET_STRUCT_UTIMBUF,
[AC_MSG_CHECKING(for struct utimbuf)
if test x"$ac_cv_header_utime_h" = xyes; then
AC_EGREP_CPP([struct[ ]+utimbuf],
[#include <utime.h>],
[AC_DEFINE(HAVE_STRUCT_UTIMBUF)
AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))
else
AC_MSG_RESULT(no)
fi])
# This code originates from Ulrich Drepper's AM_WITH_NLS.
AC_DEFUN(WGET_WITH_NLS,
[AC_MSG_CHECKING([whether NLS is requested])
dnl Default is enabled NLS
AC_ARG_ENABLE(nls,
[ --disable-nls do not use Native Language Support],
HAVE_NLS=$enableval, HAVE_NLS=yes)
AC_MSG_RESULT($HAVE_NLS)
dnl If something goes wrong, we may still decide not to use NLS.
dnl For this reason, defer AC_SUBST'ing HAVE_NLS until the very
dnl last moment.
if test x"$HAVE_NLS" = xyes; then
AC_MSG_RESULT("language catalogs: $ALL_LINGUAS")
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
AC_SUBST(MSGFMT)
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
CATOBJEXT=.gmo
INSTOBJEXT=.mo
DATADIRNAME=share
dnl Test whether we really found GNU xgettext.
if test "$XGETTEXT" != ":"; then
dnl If it is no GNU xgettext we define it as : so that the
dnl Makefiles still can work.
if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
: ;
else
AC_MSG_RESULT(
[found xgettext programs is not GNU xgettext; ignore it])
XGETTEXT=":"
fi
fi
AC_CHECK_HEADERS(locale.h libintl.h)
AC_CHECK_FUNCS(gettext, [], [
AC_CHECK_LIB(intl, gettext, [
dnl gettext is in libintl; announce the fact manually.
LIBS="-lintl $LIBS"
AC_DEFINE(HAVE_GETTEXT)
], [
AC_MSG_RESULT(
[gettext not found; disabling NLS])
HAVE_NLS=no
])
])
dnl These rules are solely for the distribution goal. While doing this
dnl we only have to keep exactly one list of the available catalogs
dnl in configure.in.
for lang in $ALL_LINGUAS; do
GMOFILES="$GMOFILES $lang.gmo"
POFILES="$POFILES $lang.po"
done
dnl Construct list of names of catalog files to be constructed.
for lang in $ALL_LINGUAS; do
CATALOGS="$CATALOGS ${lang}${CATOBJEXT}"
done
dnl Make all variables we use known to autoconf.
AC_SUBST(CATALOGS)
AC_SUBST(CATOBJEXT)
AC_SUBST(DATADIRNAME)
AC_SUBST(GMOFILES)
AC_SUBST(INSTOBJEXT)
AC_SUBST(INTLLIBS)
AC_SUBST(POFILES)
fi
AC_SUBST(HAVE_NLS)
dnl Some independently maintained files, such as po/Makefile.in,
dnl use `USE_NLS', so support it.
USE_NLS=$HAVE_NLS
AC_SUBST(USE_NLS)
if test "x$HAVE_NLS" = xyes; then
AC_DEFINE(HAVE_NLS)
fi
])
dnl Generate list of files to be processed by xgettext which will
dnl be included in po/Makefile.
dnl
dnl This is not strictly an Autoconf macro, because it is run from
dnl within `config.status' rather than from within configure. This
dnl is why special rules must be applied for it.
AC_DEFUN(WGET_PROCESS_PO,
[srcdir=$ac_given_srcdir # Advanced autoconf hackery
dnl I wonder what the following several lines do...
if test "x$srcdir" != "x."; then
if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
posrcprefix="$srcdir/"
else
posrcprefix="../$srcdir/"
fi
else
posrcprefix="../"
fi
rm -f po/POTFILES
dnl Use `echo' rather than AC_MSG_RESULT, because this is run from
dnl `config.status'.
echo "generating po/POTFILES from $srcdir/po/POTFILES.in"
sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," \
-e "\$s/\(.*\) \\\\/\1/" \
< $srcdir/po/POTFILES.in > po/POTFILES
echo "creating po/Makefile"
sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
])
# Search path for a program which passes the given test.
# Ulrich Drepper <drepper@cygnus.com>, 1996.
#
# This file may be copied and used freely without restrictions. It
# can be used in projects which are not available under the GNU Public
# License but which still want to provide support for the GNU gettext
# functionality. Please note that the actual code is *not* freely
# available.
# serial 1
dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
AC_DEFUN(AM_PATH_PROG_WITH_TEST,
[# Extract the first word of "$2", so it can be a program name with args.
set dummy $2; ac_word=[$]2
AC_MSG_CHECKING([for $ac_word])
AC_CACHE_VAL(ac_cv_path_$1,
[case "[$]$1" in
/*)
ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
;;
*)
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
for ac_dir in ifelse([$5], , $PATH, [$5]); do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if [$3]; then
ac_cv_path_$1="$ac_dir/$ac_word"
break
fi
fi
done
IFS="$ac_save_ifs"
dnl If no 4th arg is given, leave the cache variable unset,
dnl so AC_PATH_PROGS will keep looking.
ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
])dnl
;;
esac])dnl
$1="$ac_cv_path_$1"
if test -n "[$]$1"; then
AC_MSG_RESULT([$]$1)
else
AC_MSG_RESULT(no)
fi
AC_SUBST($1)dnl
])

693
config.guess vendored Executable file
View File

@ -0,0 +1,693 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
#
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
#
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
alpha:OSF1:*:*)
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-cbm-sysv4
exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-cbm-openbsd${UNAME_RELEASE}
exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
NILE:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
echo m68k-atari-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
echo m68k-sun-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-apple-openbsd${UNAME_RELEASE}
exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit 0 ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
sed 's/^ //' << EOF >dummy.c
int main (argc, argv) int argc; char **argv; {
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
${CC-cc} dummy.c -o dummy \
&& ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
&& rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else echo i586-dg-dgux${UNAME_RELEASE}
fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i?86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
sed 's/^ //' << EOF >dummy.c
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit 0 ;;
*:AIX:*:4)
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
9000/[3478]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
sed 's/^ //' << EOF >dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
i?86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
F300:UNIX_System_V:*:*)
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit 0 ;;
F301:UNIX_System_V:*:*)
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
hp3[0-9][05]:OpenBSD:*:*)
echo m68k-hp-openbsd${UNAME_RELEASE}
exit 0 ;;
i?86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
i*:CYGWIN*:*)
echo i386-pc-cygwin32
exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin32
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
echo "powerpc-unknown-linux-gnu" ; exit 0
elif test "${UNAME_MACHINE}" = "alpha" ; then
echo alpha-unknown-linux-gnu ; exit 0
elif test "${UNAME_MACHINE}" = "sparc" ; then
echo sparc-unknown-linux-gnu ; exit 0
else
# Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
# useful --help. Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
test ! -d /usr/lib/ldscripts/. \
&& echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
# Determine whether the default compiler is a.out or elf
cat >dummy.c <<EOF
main(argc, argv)
int argc;
char *argv[];
{
#ifdef __ELF__
printf ("%s-pc-linux-gnu\n", argv[1]);
#else
printf ("%s-pc-linux-gnuaout\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i?86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4.3${OS_REL} && exit 0
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
m68*:LynxOS:2.*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
i?86:LynxOS:2.*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit 0 ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit 0 ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
printf ("vax-dec-bsd\n"); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
c34*)
echo c34-convex-bsd
exit 0 ;;
c38*)
echo c38-convex-bsd
exit 0 ;;
c4*)
echo c4-convex-bsd
exit 0 ;;
esac
fi
#echo '(Unable to guess system type)' 1>&2
exit 1

927
config.sub vendored Executable file
View File

@ -0,0 +1,927 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
if [ x$1 = x ]
then
echo Configuration name missing. 1>&2
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
echo "or $0 ALIAS" 1>&2
echo where ALIAS is a recognized configuration type. 1>&2
exit 1
fi
# First pass through any local machine types.
case $1 in
*local*)
echo $1
exit 0
;;
*)
;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
linux-gnu*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple)
os=
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco5)
os=sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
| arme[lb] | pyramid \
| tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
| alpha | we32k | ns16k | clipper | i370 | sh \
| powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
| pdp11 | mips64el | mips64orion | mips64orionel \
| sparc | sparclet | sparclite | sparc64)
basic_machine=$basic_machine-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i[3456]86)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
| sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
| none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
| hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
| pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
| pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
| mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-cbm
;;
amigados)
basic_machine=m68k-cbm
os=-amigados
;;
amigaunix | amix)
basic_machine=m68k-cbm
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | ymp)
basic_machine=ymp-cray
os=-unicos
;;
cray2)
basic_machine=cray2-cray
os=-unicos
;;
[ctj]90-cray)
basic_machine=c90-cray
os=-unicos
;;
crds | unos)
basic_machine=m68k-crds
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i[3456]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i[3456]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i[3456]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i[3456]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
miniframe)
basic_machine=m68000-convergent
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
np1)
basic_machine=np1-gould
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pentium | p5)
basic_machine=i586-intel
;;
pentiumpro | p6)
basic_machine=i686-intel
;;
pentium-* | p5-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
k5)
# We don't have specific support for AMD's K5 yet, so just call it a Pentium
basic_machine=i586-amd
;;
nexen)
# We don't have specific support for Nexgen yet, so just call it a Pentium
basic_machine=i586-nexgen
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=rs6000-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
xmp)
basic_machine=xmp-cray
os=-unicos
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
mips)
basic_machine=mips-mips
;;
romp)
basic_machine=romp-ibm
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sparc)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-unixware* | svr4*)
os=-sysv4
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -linux-gnu* | -uxpv*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-ctix* | -uts*)
os=-sysv
;;
-ns2 )
os=-nextstep2
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-xenix)
os=-xenix
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
*-acorn)
os=-riscix1.2
;;
arm*-semi)
os=-aout
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-ibm)
os=-aix
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigados
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f301-fujitsu)
os=-uxpv
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-aix*)
vendor=ibm
;;
-hpux*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-vxsim* | -vxworks*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os

3093
configure vendored Executable file

File diff suppressed because it is too large Load Diff

47
configure.bat Normal file
View File

@ -0,0 +1,47 @@
@echo off
rem Configure batch file for `Wget' utility
rem Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
rem This program is free software; you can redistribute it and/or modify
rem it under the terms of the GNU General Public License as published by
rem the Free Software Foundation; either version 2 of the License, or
rem (at your option) any later version.
rem This program is distributed in the hope that it will be useful,
rem but WITHOUT ANY WARRANTY; without even the implied warranty of
rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
rem GNU General Public License for more details.
rem You should have received a copy of the GNU General Public License
rem along with this program; if not, write to the Free Software
rem Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
cls
if .%1 == .--borland goto :borland
if .%1 == .--msvc goto :msvc
if not .%BORPATH% == . goto :borland
if not .%1 == . goto :usage
:msvc
copy windows\config.h.ms src\config.h > nul
copy windows\Makefile.top Makefile > nul
copy windows\Makefile.src src\Makefile > nul
copy windows\Makefile.doc doc\Makefile > nul
echo Type NMAKE to start compiling.
echo If it doesn't work, try executing MSDEV\BIN\VCVARS32.BAT first,
echo and then NMAKE.
goto :end
:borland
copy windows\config.h.bor src\config.h > nul
copy windows\Makefile.top.bor Makefile > nul
copy windows\Makefile.src.bor src\Makefile > nul
copy windows\Makefile.doc doc\Makefile > nul
echo Type MAKE to start compiling.
goto :end
:usage
echo Usage: Configure [--borland | --msvc]
:end

209
configure.in Normal file
View File

@ -0,0 +1,209 @@
dnl Template file for GNU Autoconf
dnl Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
AC_INIT(src/version.c)
AC_PREREQ(2.12)
AC_CONFIG_HEADER(src/config.h)
dnl
dnl What version of Wget are we building?
dnl
VERSION=`sed -e 's/^.*"\(.*\)";$/\1/' ${srcdir}/src/version.c`
echo "configuring for GNU Wget $VERSION"
AC_SUBST(VERSION)
PACKAGE=wget
AC_SUBST(PACKAGE)
dnl
dnl Get cannonical host
dnl
AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED(OS_TYPE, "$host_os")
dnl
dnl Process features.
dnl
AC_ARG_WITH(socks,
[ --with-socks use the socks library],
[AC_DEFINE(HAVE_SOCKS)])
AC_ARG_ENABLE(opie,
[ --disable-opie disable support for opie or s/key FTP login],
USE_OPIE=$enableval, USE_OPIE=yes)
test x"${USE_OPIE}" = xyes && AC_DEFINE(USE_OPIE)
AC_ARG_ENABLE(digest,
[ --disable-digest disable support for HTTP digest authorization],
USE_DIGEST=$enableval, USE_DIGEST=yes)
test x"${USE_DIGEST}" = xyes && AC_DEFINE(USE_DIGEST)
AC_ARG_ENABLE(debug,
[ --disable-debug disable support for debugging output],
DEBUG=$enableval, DEBUG=yes)
test x"${DEBUG}" = xyes && AC_DEFINE(DEBUG)
case "${USE_OPIE}${USE_DIGEST}" in
*yes*)
MD5_OBJ='md5$o'
esac
if test x"$USE_OPIE" = xyes; then
OPIE_OBJ='ftp-opie$o'
fi
AC_SUBST(MD5_OBJ)
AC_SUBST(OPIE_OBJ)
dnl
dnl Whether make sets $(MAKE)...
dnl
AC_PROG_MAKE_SET
dnl
dnl Find a good install
dnl
AC_PROG_INSTALL
dnl
dnl Find the compiler
dnl
dnl We want these before the checks, so the checks can modify their values.
test -z "$CFLAGS" && CFLAGS= auto_cflags=1
test -z "$CC" && cc_specified=yes
AC_PROG_CC
dnl
dnl if the user hasn't specified CFLAGS, then
dnl if compiler is gcc, then use -O2 and some warning flags
dnl else use os-specific flags or -O
dnl
if test -n "$auto_cflags"; then
if test -n "$GCC"; then
CFLAGS="$CFLAGS -O2 -Wall -Wno-implicit"
else
case "$host_os" in
*hpux*) CFLAGS="$CFLAGS +O3" ;;
*ultrix* | *osf*) CFLAGS="$CFLAGS -O -Olimit 2000" ;;
*) CFLAGS="$CFLAGS -O" ;;
esac
fi
fi
dnl
dnl Handle AIX
dnl
AC_AIX
dnl
dnl In case of {cyg,gnu}win32. Should be a _target_ test.
dnl Might also be erelevant for DJGPP.
dnl
case "$host_os" in
*win32) exeext='.exe';;
*) exeext='';;
esac
AC_SUBST(exeext)
dnl
dnl Check if we can handle prototypes.
dnl
AM_C_PROTOTYPES
dnl
dnl Checks for typedefs, structures, and compiler characteristics.
dnl
AC_C_CONST
AC_TYPE_SIZE_T
AC_TYPE_PID_T
dnl #### This generates a warning. What do I do to shut it up?
AC_C_BIGENDIAN
dnl
dnl Checks for headers
dnl
AC_CHECK_HEADERS(string.h stdarg.h unistd.h sys/time.h utime.h sys/utime.h)
AC_CHECK_HEADERS(sys/select.h sys/utsname.h pwd.h signal.h)
AC_HEADER_TIME
dnl
dnl Return type of signal-handlers
dnl
AC_TYPE_SIGNAL
dnl
dnl Check for struct utimbuf
WGET_STRUCT_UTIMBUF
dnl
dnl Checks for library functions.
dnl
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(strdup strstr strcasecmp strncasecmp)
AC_CHECK_FUNCS(gettimeofday mktime strptime)
AC_CHECK_FUNCS(strerror vsnprintf select signal symlink access isatty)
AC_CHECK_FUNCS(uname gethostname)
AC_CHECK_FUNCS(gethostbyname, [], [
AC_CHECK_LIB(nsl, gethostbyname)
])
dnl
dnl Checks for libraries.
dnl
AC_CHECK_LIB(socket, socket)
dnl #### This appears to be deficient with later versions of SOCKS.
if test "x${with_socks}" = xyes
then
AC_CHECK_LIB(resolv, main)
AC_CHECK_LIB(socks, Rconnect)
fi
dnl Set of available languages.
dnl
dnl #### This kind of sucks. Shouldn't the configure process
dnl determine this automagically by scanning `.po' files in `po/'
dnl subdirectory?
ALL_LINGUAS="cs de hr no it pt_BR"
dnl internationalization macros
WGET_WITH_NLS
dnl
dnl Find makeinfo. If makeinfo is not found, look for Emacs. If
dnl Emacs cannot be found, look for XEmacs.
dnl
AC_CHECK_PROGS(MAKEINFO, makeinfo emacs xemacs)
case "${MAKEINFO}" in
*makeinfo) MAKEINFO="${MAKEINFO} \$(srcdir)/wget.texi" ;;
*emacs | *xemacs) MAKEINFO="${MAKEINFO} -batch -q -no-site-file -eval '(find-file \"\$(srcdir)/wget.texi\")' -l texinfmt -f texinfo-format-buffer -f save-buffer" ;;
*) MAKEINFO="makeinfo \$(srcdir)/wget.texi" ;;
esac
dnl
dnl Create output
dnl
AC_OUTPUT([Makefile src/Makefile doc/Makefile util/Makefile po/Makefile.in],
[WGET_PROCESS_PO
test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h])

245
doc/ChangeLog Normal file
View File

@ -0,0 +1,245 @@
1998-09-10 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (HTTP Options): Warn against masquerading as Mozilla.
1998-05-24 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (clean): Remove HTML files.
1998-05-13 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Various updates.
(Proxies): New node.
1998-05-09 Hrvoje Niksic <hniksic@srce.hr>
* texinfo.tex: New file.
1998-05-08 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (dvi): New target.
1998-05-02 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Recursive Retrieval): Fix typo. Suggested by
Francois Pinard.
1998-04-18 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Fixed @dircategory, courtesy Karl Eichwalder.
1998-03-31 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in: Don't attempt to (un)install the man-page.
1998-03-30 Hrvoje Niksic <hniksic@srce.hr>
* wget.1: Removed it.
1998-03-29 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Invoking): Split into more sections, analogous to
output of `wget --help'.
(HTTP Options): Document --user-agent.
1998-03-16 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Contributors): Updated with oodles of new names.
1998-02-22 Karl Eichwalder <ke@suse.de>
* Makefile.in (install.info): only info files (no *info.orig,
etc.).
1998-01-31 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (install.wgetrc): Don't use `!'.
1998-01-28 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Expanded.
1998-01-25 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document `--cache'.
(Contributors): Added Brian.
1997-07-26 Francois Pinard <pinard@iro.umontreal.ca>
* Makefile.in (install.wgetrc): Print the sample.wgetrc warning
only if the files actually differ.
1998-01-23 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in: Use `test ...' rather than `[ ... ]'.
* wget.texi (Advanced Options): Explained suffices.
1998-01-23 Karl Heuer <kwzh@gnu.org>
* wget.texi (Advanced Options): Updated.
1997-12-18 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Mailing List): Update.
1997-04-23 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document `--follow-ftp'.
1997-02-17 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document --proxy-user and
--proxy-passwd.
1997-02-14 Karl Eichwalder <ke@ke.Central.DE>
* Makefile.in (install.wgetrc): Never ever nuke an existing rc file.
1997-02-02 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Updated and revised.
* wget.texi (Contributors): Update.
(Advanced Options): Removed bogus **/* example.
* wget.texi: Use ``...'' instead of "...".
1997-02-01 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Domain Acceptance): Document --exclude-domains.
1997-01-21 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document --ignore-length.
1997-01-20 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Time-Stamping): New node.
1997-01-12 Hrvoje Niksic <hniksic@srce.hr>
* Makefile.in (distclean): Don't remove wget.info*.
1997-01-08 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Mailing List): Update archive.
(Portability): Update the Windows port by Budor.
1996-12-21 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Security Considerations): New node.
1996-12-19 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document --passive.
1996-12-12 Dieter Baron <dillo@danbala.tuwien.ac.at>
* wget.texi (Advanced Usage): Would reference prep instead of
wuarchive.
1996-11-25 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Documented --retr-symlinks.
1996-11-23 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document --delete-after.
1996-11-22 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Portability): Add IRIX and FreeBSD as the "regular"
platforms.
1996-11-20 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Usage): Document dot-style.
1996-11-18 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Usage): Dot customization example.
(Sample Wgetrc): Likewise.
1996-11-16 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Wgetrc Syntax): Explained emptying lists.
1996-11-13 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document includes/excludes.
(Wgetrc Commands): Likewise.
1996-11-10 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Options): Document headers.
1996-11-07 Hrvoje Niksic <hniksic@srce.hr>
* sample.wgetrc: Added header examples.
1996-11-06 Hrvoje Niksic <hniksic@srce.hr>
* sample.wgetrc: Rewritten.
* Makefile.in (install.wgetrc): Install sample.wgetrc.
(uninstall.info): Use $(RM).
1996-11-06 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Docfixes.
1996-11-03 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Proofread; *many* docfixes.
1996-11-02 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Introduction): Updated robots mailing list address.
1996-11-01 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi: Minor docfixes.
1996-10-26 Hrvoje Niksic <hniksic@srce.hr>
* wget.texi (Advanced Usage): Document passwords better.
* Makefile.in (distclean): Remove wget.1 on make distclean.
* wget.texi (Option Syntax): Explain --.
1996-10-21 Hrvoje Niksic <hniksic@srce.hr>
* fetch.texi (No Parent): update.
1996-10-18 Hrvoje Niksic <hniksic@srce.hr>
* fetch.texi (Advanced Options): Docfix.
1996-10-17 Tage Stabell-Kulo <tage@acm.org>
* geturl.texi (Advanced Options): Sort alphabetically.
1996-10-16 Hrvoje Niksic <hniksic@srce.hr>
* geturl.texi (Advanced Options): Describe -nr.
(Advanced Usage): Moved -O pipelines to Guru Usage.
(Simple Usage): Update.
(Advanced Options): Docfix.
* Makefile.in (RM): RM = rm -f.
1996-10-15 Hrvoje Niksic <hniksic@srce.hr>
* geturl.texi (Guru Usage): Add proxy-filling example.
1996-10-12 Hrvoje Niksic <hniksic@srce.hr>
* geturl.texi (Advanced Options): Added --spider.
1996-10-08 Hrvoje Niksic <hniksic@srce.hr>
* geturl.texi (Advanced Options): Added -X.
* Makefile.in: Added $(srcdir) where appropriate (I hope).

145
doc/Makefile.in Normal file
View File

@ -0,0 +1,145 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: @VERSION@
#
SHELL = /bin/sh
# Program to format Texinfo source into Info files.
MAKEINFO = @MAKEINFO@
# Program to format Texinfo source into DVI files.
TEXI2DVI = texi2dvi
# Program to convert DVI files to PostScript
DVIPS = dvips -D 300
# Program to convert texinfo files to html
TEXI2HTML = texi2html -expandinfo -split_chapter
top_srcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
prefix = @prefix@
infodir = @infodir@
mandir = @mandir@
manext = 1
sysconfdir = @sysconfdir@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
RM = rm -f
MAN = wget.$(manext)
WGETRC = $(sysconfdir)/wgetrc
#
# Dependencies for building
#
all: wget.info # wget.cat
everything: all wget_us.ps wget_a4.ps wget_toc.html
wget.info: wget.texi
-$(MAKEINFO)
#wget.cat: $(MAN)
# nroff -man $(srcdir)/$(MAN) > wget.cat
dvi: wget.dvi
wget.dvi: wget.texi
$(TEXI2DVI) $(srcdir)/wget.texi
wget_us.ps: wget.dvi
$(DVIPS) -t letter -o $@ wget.dvi
wget_a4.ps: wget.dvi
$(DVIPS) -t a4 -o $@ wget.dvi
wget_toc.html: wget.texi
$(TEXI2HTML) $(srcdir)/wget.texi
#
# Dependencies for installing
#
# install all the documentation
install: install.info install.wgetrc # install.man
# uninstall all the documentation
uninstall: uninstall.info # uninstall.man
# install info pages, creating install directory if necessary
install.info: wget.info
$(top_srcdir)/mkinstalldirs $(infodir)
-for file in $(srcdir)/wget.info $(srcdir)/wget.info-*[0-9]; do \
test -f "$$file" && $(INSTALL_DATA) $$file $(infodir) ; \
done
# install man page, creating install directory if necessary
#install.man:
# $(top_srcdir)/mkinstalldirs $(mandir)/man$(manext)
# $(INSTALL_DATA) $(srcdir)/$(MAN) $(mandir)/man$(manext)/$(MAN)
# install sample.wgetrc
install.wgetrc:
$(top_srcdir)/mkinstalldirs $(sysconfdir)
@if test -f $(WGETRC); then \
if cmp -s $(srcdir)/sample.wgetrc $(WGETRC); then echo ""; \
else \
echo ' $(INSTALL_DATA) $(srcdir)/sample.wgetrc $(WGETRC).new'; \
$(INSTALL_DATA) $(srcdir)/sample.wgetrc $(WGETRC).new; \
echo "WARNING: File \`$(WGETRC)' already exists and is spared."; \
echo " You might want to consider \`$(WGETRC).new',"; \
echo " and merge both into \`$(WGETRC)', for the best."; \
fi; \
else \
$(INSTALL_DATA) $(srcdir)/sample.wgetrc $(WGETRC); \
fi
# uninstall info pages
uninstall.info:
$(RM) $(infodir)/wget.info*
# uninstall man page
#uninstall.man:
# $(RM) $(mandir)/man$(manext)/$(MAN)
#
# Dependencies for cleanup
#
clean:
$(RM) *~ *.bak *.cat *.html
$(RM) *.dvi *.aux *.cp *.cps *.fn *.toc *.tp *.vr *.ps *.ky *.pg *.log
distclean: clean
$(RM) Makefile
realclean: distclean
$(RM) wget.info*
#
# Dependencies for maintenance
#
subdir = doc
Makefile: Makefile.in ../config.status
cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status

19
doc/ansi2knr.1 Normal file
View File

@ -0,0 +1,19 @@
.TH ANSI2KNR 1 "31 December 1990"
.SH NAME
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
.SH SYNOPSIS
.I ansi2knr
input_file output_file
.SH DESCRIPTION
If no output_file is supplied, output goes to stdout.
.br
There are no error messages.
.sp
.I ansi2knr
recognizes functions by seeing a non-keyword identifier at the left margin, followed by a left parenthesis, with a right parenthesis as the last character on the line. It will recognize a multi-line header if the last character on each line but the last is a left parenthesis or comma. These algorithms ignore whitespace and comments, except that the function name must be the first thing on the line.
.sp
The following constructs will confuse it:
.br
- Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call).
.br
- Macros that tinker with the syntax of the function header.

95
doc/sample.wgetrc Normal file
View File

@ -0,0 +1,95 @@
###
### Sample Wget initialization file .wgetrc
###
## You can use this file to change the default behaviour of wget or to
## avoid having to type many many command-line options. This file does
## not contain a comprehensive list of commands -- look at the manual
## to find out what you can put into this file.
##
## Wget initialization file can reside in /usr/local/etc/wgetrc
## (global, for all users) or $HOME/.wgetrc (for a single user).
##
## To use any of the settings in this file, you will have to uncomment
## them (and probably change them).
##
## Global settings (useful for setting up in /usr/local/etc/wgetrc).
## Think well before you change them, since they may reduce wget's
## functionality, and make it behave contrary to the documentation:
##
# You can set retrieve quota for beginners by specifying a value
# optionally followed by 'K' (kilobytes) or 'M' (megabytes). The
# default quota is unlimited.
#quota = inf
# You can lower (or raise) the default number of retries when
# downloading a file (default is 20).
#tries = 20
# Lowering the maximum depth of the recursive retrieval is handy to
# prevent newbies from going too "deep" when they unwittingly start
# the recursive retrieval. The default is 5.
#reclevel = 5
# Many sites are behind firewalls that do not allow initiation of
# connections from the outside. On these sites you have to use the
# `passive' feature of FTP. If you are behind such a firewall, you
# can turn this on to make Wget use passive FTP by default.
#passive_ftp = off
##
## Local settings (for a user to set in his $HOME/.wgetrc). It is
## *highly* undesirable to put these settings in the global file, since
## they are potentially dangerous to "normal" users.
##
## Even when setting up your own ~/.wgetrc, you should know what you
## are doing before doing so.
##
# Set this to on to use timestamping by default:
#timestamping = off
# It is a good idea to make Wget send your email address in a `From:'
# header with your request (so that server administrators can contact
# you in case of errors). Wget does *not* send `From:' by default.
#header = From: Your Name <username@site.domain>
# You can set up other headers, like Accept-Language. Accept-Language
# is *not* sent by default.
#header = Accept-Language: en
# You can set the default proxy for Wget to use. It will override the
# value in the environment.
#http_proxy = http://proxy.yoyodyne.com:18023/
# If you do not want to use proxy at all, set this to off.
#use_proxy = on
# You can customize the retrieval outlook. Valid options are default,
# binary, mega and micro.
#dot_style = default
# Setting this to off makes Wget not download /robots.txt. Be sure to
# know *exactly* what /robots.txt is and how it is used before changing
# the default!
#robots = on
# It can be useful to make Wget wait between connections. Set this to
# the number of seconds you want Wget to wait.
#wait = 0
# You can force creating directory structure, even if a single is being
# retrieved, by setting this to on.
#dirstruct = off
# You can turn on recursive retrieving by default (don't do this if
# you are not sure you know what it means) by setting this to on.
#recursive = off
# To have Wget follow FTP links from HTML files by default, set this
# to on:
#follow_ftp = off

5039
doc/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

88
doc/wget.info Normal file
View File

@ -0,0 +1,88 @@
This is Info file wget.info, produced by Makeinfo version 1.67 from the
input file ./wget.texi.
INFO-DIR-SECTION Net Utilities
INFO-DIR-SECTION World Wide Web
START-INFO-DIR-ENTRY
* Wget: (wget). The non-interactive network downloader.
END-INFO-DIR-ENTRY
This file documents the the GNU Wget utility for downloading network
data.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the sections entitled "Copying" and "GNU General Public License"
are included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

Indirect:
wget.info-1: 955
wget.info-2: 50818
wget.info-3: 88475

Tag Table:
(Indirect)
Node: Top955
Node: Overview1832
Node: Invoking5006
Node: URL Format5815
Node: Option Syntax8147
Node: Basic Startup Options9571
Node: Logging and Input File Options10271
Node: Download Options12665
Node: Directory Options18450
Node: HTTP Options20928
Node: FTP Options24524
Node: Recursive Retrieval Options25717
Node: Recursive Accept/Reject Options27493
Node: Recursive Retrieval29575
Node: Following Links31871
Node: Relative Links32903
Node: Host Checking33417
Node: Domain Acceptance35450
Node: All Hosts37120
Node: Types of Files37547
Node: Directory-Based Limits39997
Node: FTP Links42637
Node: Time-Stamping43507
Node: Time-Stamping Usage45144
Node: HTTP Time-Stamping Internals46713
Node: FTP Time-Stamping Internals47922
Node: Startup File49130
Node: Wgetrc Location50003
Node: Wgetrc Syntax50818
Node: Wgetrc Commands51533
Node: Sample Wgetrc58229
Node: Examples62521
Node: Simple Usage63128
Node: Advanced Usage65522
Node: Guru Usage68273
Node: Various69935
Node: Proxies70459
Node: Distribution73224
Node: Mailing List73566
Node: Reporting Bugs74265
Node: Portability76050
Node: Signals77425
Node: Appendices78079
Node: Robots78494
Node: Introduction to RES79641
Node: RES Format81534
Node: User-Agent Field82638
Node: Disallow Field83402
Node: Norobots Examples84013
Node: Security Considerations84967
Node: Contributors85963
Node: Copying88475
Node: Concept Index107638

End Tag Table

1283
doc/wget.info-1 Normal file

File diff suppressed because it is too large Load Diff

1079
doc/wget.info-2 Normal file

File diff suppressed because it is too large Load Diff

534
doc/wget.info-3 Normal file
View File

@ -0,0 +1,534 @@
This is Info file wget.info, produced by Makeinfo version 1.67 from the
input file ./wget.texi.
INFO-DIR-SECTION Net Utilities
INFO-DIR-SECTION World Wide Web
START-INFO-DIR-ENTRY
* Wget: (wget). The non-interactive network downloader.
END-INFO-DIR-ENTRY
This file documents the the GNU Wget utility for downloading network
data.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the sections entitled "Copying" and "GNU General Public License"
are included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

File: wget.info, Node: Copying, Next: Concept Index, Prev: Appendices, Up: Top
GNU GENERAL PUBLIC LICENSE
**************************
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
========
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it in
new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software,
and (2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1. 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.
2. 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.
3. 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.
4. 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.
5. 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.
6. 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.
7. 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.
8. 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.
9. 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.
10. 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.
11. 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
12. 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.
13. 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 AN IDEA OF WHAT IT DOES.
Copyright (C) 19YY 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., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper
mail.
If the program is interactive, make it output a short notice like
this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the program,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
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.

File: wget.info, Node: Concept Index, Prev: Copying, Up: Top
Concept Index
*************
* Menu:
* .netrc: Startup File.
* .wgetrc: Startup File.
* accept directories: Directory-Based Limits.
* accept suffixes: Types of Files.
* accept wildcards: Types of Files.
* all hosts: All Hosts.
* append to log: Logging and Input File Options.
* arguments: Invoking.
* authentication: HTTP Options.
* bug reports: Reporting Bugs.
* bugs: Reporting Bugs.
* cache: HTTP Options.
* command line: Invoking.
* Content-Length, ignore: HTTP Options.
* continue retrieval: Download Options.
* contributors: Contributors.
* conversion of links: Recursive Retrieval Options.
* copying: Copying.
* cut directories: Directory Options.
* debug: Logging and Input File Options.
* delete after retrieval: Recursive Retrieval Options.
* directories: Directory-Based Limits.
* directories, exclude: Directory-Based Limits.
* directories, include: Directory-Based Limits.
* directory limits: Directory-Based Limits.
* directory prefix: Directory Options.
* DNS lookup: Host Checking.
* dot style: Download Options.
* examples: Examples.
* exclude directories: Directory-Based Limits.
* execute wgetrc command: Basic Startup Options.
* features: Overview.
* filling proxy cache: Recursive Retrieval Options.
* follow FTP links: Recursive Accept/Reject Options.
* following ftp links: FTP Links.
* following links: Following Links.
* force html: Logging and Input File Options.
* ftp time-stamping: FTP Time-Stamping Internals.
* globbing, toggle: FTP Options.
* GPL: Copying.
* hangup: Signals.
* header, add: HTTP Options.
* host checking: Host Checking.
* host lookup: Host Checking.
* http password: HTTP Options.
* http time-stamping: HTTP Time-Stamping Internals.
* http user: HTTP Options.
* ignore length: HTTP Options.
* include directories: Directory-Based Limits.
* incremental updating: Time-Stamping.
* input-file: Logging and Input File Options.
* invoking: Invoking.
* latest version: Distribution.
* links: Following Links.
* links conversion: Recursive Retrieval Options.
* list: Mailing List.
* location of wgetrc: Wgetrc Location.
* log file: Logging and Input File Options.
* mailing list: Mailing List.
* mirroring: Guru Usage.
* no parent: Directory-Based Limits.
* no warranty: Copying.
* no-clobber: Download Options.
* nohup: Invoking.
* norobots disallow: Disallow Field.
* norobots examples: Norobots Examples.
* norobots format: RES Format.
* norobots introduction: Introduction to RES.
* norobots user-agent: User-Agent Field.
* number of retries: Download Options.
* operating systems: Portability.
* option syntax: Option Syntax.
* output file: Logging and Input File Options.
* overview: Overview.
* passive ftp: FTP Options.
* pause: Download Options.
* portability: Portability.
* proxies: Proxies.
* proxy <1>: Download Options.
* proxy: HTTP Options.
* proxy authentication: HTTP Options.
* proxy filling: Recursive Retrieval Options.
* proxy password: HTTP Options.
* proxy user: HTTP Options.
* quiet: Logging and Input File Options.
* quota: Download Options.
* recursion: Recursive Retrieval.
* recursive retrieval: Recursive Retrieval.
* redirecting output: Guru Usage.
* reject directories: Directory-Based Limits.
* reject suffixes: Types of Files.
* reject wildcards: Types of Files.
* relative links: Relative Links.
* reporting bugs: Reporting Bugs.
* retries: Download Options.
* retrieval tracing style: Download Options.
* retrieve symbolic links: FTP Options.
* retrieving: Recursive Retrieval.
* robots: Robots.
* robots.txt: Robots.
* sample wgetrc: Sample Wgetrc.
* security: Security Considerations.
* server maintenance: Robots.
* server response, print: Download Options.
* server response, save: HTTP Options.
* signal handling: Signals.
* span hosts: All Hosts.
* spider: Download Options.
* startup: Startup File.
* startup file: Startup File.
* suffixes, accept: Types of Files.
* suffixes, reject: Types of Files.
* syntax of options: Option Syntax.
* syntax of wgetrc: Wgetrc Syntax.
* time-stamping: Time-Stamping.
* time-stamping usage: Time-Stamping Usage.
* timeout: Download Options.
* timestamping: Time-Stamping.
* tries: Download Options.
* types of files: Types of Files.
* updating the archives: Time-Stamping.
* URL: URL Format.
* URL syntax: URL Format.
* usage, time-stamping: Time-Stamping Usage.
* user-agent: HTTP Options.
* various: Various.
* verbose: Logging and Input File Options.
* wait: Download Options.
* Wget as spider: Download Options.
* wgetrc: Startup File.
* wgetrc commands: Wgetrc Commands.
* wgetrc location: Wgetrc Location.
* wgetrc syntax: Wgetrc Syntax.
* wildcards, accept: Types of Files.
* wildcards, reject: Types of Files.

3118
doc/wget.texi Normal file

File diff suppressed because it is too large Load Diff

250
install-sh Executable file
View File

@ -0,0 +1,250 @@
#! /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=:
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

40
mkinstalldirs Executable file
View File

@ -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 2 1999-12-02 07:42:23Z kwget $
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" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

212
po/Makefile.in.in Normal file
View File

@ -0,0 +1,212 @@
# Makefile for program source directory in GNU NLS utilities package.
# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
#
# This file file be copied and used freely without restrictions. It can
# be used in projects which are not available under the GNU Public License
# but which still want to provide support for the GNU gettext functionality.
# Please note that the actual code is *not* freely available.
PACKAGE = @PACKAGE@
VERSION = @VERSION@
SHELL = /bin/sh
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
datadir = $(prefix)/@DATADIRNAME@
localedir = $(datadir)/locale
gnulocaledir = $(prefix)/share/locale
gettextsrcdir = $(prefix)/share/gettext/po
subdir = po
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
CC = @CC@
GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
MSGFMT = @MSGFMT@
XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
MSGMERGE = PATH=../src:$$PATH msgmerge
DEFS = @DEFS@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
INCLUDES = -I.. -I$(top_srcdir)/intl
COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
POFILES = @POFILES@
GMOFILES = @GMOFILES@
DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
$(POFILES) $(GMOFILES) $(SOURCES)
POTFILES = \
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
INSTOBJEXT = @INSTOBJEXT@
.SUFFIXES:
.SUFFIXES: .c .o .po .pox .gmo .mo .msg
.c.o:
$(COMPILE) $<
.po.pox:
$(MAKE) $(PACKAGE).pot
$(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
.po.mo:
$(MSGFMT) -o $@ $<
.po.gmo:
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
&& rm -f $$file && $(GMSGFMT) -o $$file $<
all: all-@USE_NLS@
all-yes: $(CATALOGS)
all-no:
$(srcdir)/$(PACKAGE).pot: $(POTFILES)
$(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
--add-comments --keyword=_ --keyword=N_ \
--files-from=$(srcdir)/POTFILES.in
rm -f $(srcdir)/$(PACKAGE).pot
mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot
install.mo: install
install: install-exec install-data
install-exec:
install-data: install-data-@USE_NLS@
install-data-no: all
install-data-yes: all
@catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
case "$$cat" in \
*.gmo) destdir=$(gnulocaledir);; \
*) destdir=$(localedir);; \
esac; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
dir=$$destdir/$$lang/LC_MESSAGES; \
$(top_srcdir)/mkinstalldirs $$dir; \
if test -r $$cat; then \
$(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
else \
$(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
fi; \
if test -r $$cat.m; then \
$(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
else \
if test -r $(srcdir)/$$cat.m ; then \
$(INSTALL_DATA) $(srcdir)/$$cat.m \
$$dir/$(PACKAGE)$(INSTOBJEXT).m; \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
else \
true; \
fi; \
fi; \
done
if test "$(PACKAGE)" = "gettext"; then \
$(INSTALL_DATA) $(srcdir)/Makefile.in.in \
$(gettextsrcdir)/Makefile.in.in; \
else \
: ; \
fi
# Define this as empty until I found a useful application.
installcheck:
uninstall:
catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
done
rm -f $(gettextsrcdir)/po-Makefile.in.in
check: all
cat-id-tbl.o: ../intl/libgettext.h
dvi info tags TAGS ID:
mostlyclean:
rm -f core core.* *.pox $(PACKAGE).po *.old.po
rm -fr *.o
clean: mostlyclean
distclean: clean
rm -f Makefile Makefile.in POTFILES *.mo *.msg
maintainer-clean: distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f $(GMOFILES)
distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
dist distdir: update-po $(DISTFILES)
dists="$(DISTFILES)"; \
for file in $$dists; do \
ln $(srcdir)/$$file $(distdir) 2> /dev/null \
|| cp -p $(srcdir)/$$file $(distdir); \
done
update-po: Makefile
$(MAKE) $(PACKAGE).pot
PATH=`pwd`/../src:$$PATH; \
cd $(srcdir); \
catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
mv $$lang.po $$lang.old.po; \
echo "$$lang:"; \
if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
rm -f $$lang.old.po; \
else \
echo "msgmerge for $$cat failed!"; \
rm -f $$lang.po; \
mv $$lang.old.po $$lang.po; \
fi; \
done
POTFILES: POTFILES.in
( if test 'x$(srcdir)' != 'x.'; then \
posrcprefix='$(top_srcdir)/'; \
else \
posrcprefix="../"; \
fi; \
rm -f $@-t $@ \
&& (sed -e '/^#/d' -e '/^[ ]*$$/d' \
-e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
| sed -e '$$s/\\$$//') > $@-t \
&& chmod a-w $@-t \
&& mv $@-t $@ )
Makefile: Makefile.in.in ../config.status POTFILES
cd .. \
&& CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
$(SHELL) ./config.status
# Tell versions [3.59,3.63) of GNU make not to export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

26
po/POTFILES.in Normal file
View File

@ -0,0 +1,26 @@
# List of files which containing translatable strings.
# Copyright (C) 1998 Free Software Foundation, Inc.
# Package source files
src/cmpt.c
src/connect.c
src/fnmatch.c
src/ftp-basic.c
src/ftp-ls.c
src/ftp-opie.c
src/ftp.c
src/getopt.c
src/headers.c
src/host.c
src/html.c
src/http.c
src/init.c
src/log.c
src/main.c
src/mswindows.c
src/netrc.c
src/rbuf.c
src/recur.c
src/retr.c
src/url.c
src/utils.c

BIN
po/cs.gmo Normal file

Binary file not shown.

1155
po/cs.po Normal file

File diff suppressed because it is too large Load Diff

BIN
po/de.gmo Normal file

Binary file not shown.

1090
po/de.po Normal file

File diff suppressed because it is too large Load Diff

BIN
po/hr.gmo Normal file

Binary file not shown.

1040
po/hr.po Normal file

File diff suppressed because it is too large Load Diff

BIN
po/it.gmo Normal file

Binary file not shown.

1059
po/it.po Normal file

File diff suppressed because it is too large Load Diff

BIN
po/no.gmo Normal file

Binary file not shown.

1045
po/no.po Normal file

File diff suppressed because it is too large Load Diff

BIN
po/pt_BR.gmo Normal file

Binary file not shown.

1168
po/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

921
po/wget.pot Normal file
View File

@ -0,0 +1,921 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Free Software Foundation, Inc.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 1998-09-21 19:08+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
#. Login to the server:
#. First: Establish the control connection.
#: src/ftp.c:147 src/http.c:346
#, c-format
msgid "Connecting to %s:%hu... "
msgstr ""
#: src/ftp.c:169 src/ftp.c:411 src/http.c:363
#, c-format
msgid "Connection to %s:%hu refused.\n"
msgstr ""
#. Second: Login with proper USER/PASS sequence.
#: src/ftp.c:190 src/http.c:374
msgid "connected!\n"
msgstr ""
#: src/ftp.c:191
#, c-format
msgid "Logging in as %s ... "
msgstr ""
#: src/ftp.c:200 src/ftp.c:253 src/ftp.c:301 src/ftp.c:353 src/ftp.c:447
#: src/ftp.c:520 src/ftp.c:568 src/ftp.c:616
msgid "Error in server response, closing control connection.\n"
msgstr ""
#: src/ftp.c:208
msgid "Error in server greeting.\n"
msgstr ""
#: src/ftp.c:216 src/ftp.c:262 src/ftp.c:310 src/ftp.c:362 src/ftp.c:457
#: src/ftp.c:530 src/ftp.c:578 src/ftp.c:626
msgid "Write failed, closing control connection.\n"
msgstr ""
#: src/ftp.c:223
msgid "The server refuses login.\n"
msgstr ""
#: src/ftp.c:230
msgid "Login incorrect.\n"
msgstr ""
#: src/ftp.c:237
msgid "Logged in!\n"
msgstr ""
#: src/ftp.c:270
#, c-format
msgid "Unknown type `%c', closing control connection.\n"
msgstr ""
#: src/ftp.c:283
msgid "done. "
msgstr ""
#: src/ftp.c:289
msgid "==> CWD not needed.\n"
msgstr ""
#: src/ftp.c:317
#, c-format
msgid ""
"No such directory `%s'.\n"
"\n"
msgstr ""
#: src/ftp.c:331 src/ftp.c:599 src/ftp.c:647 src/url.c:1431
msgid "done.\n"
msgstr ""
#. do not CWD
#: src/ftp.c:335
msgid "==> CWD not required.\n"
msgstr ""
#: src/ftp.c:369
msgid "Cannot initiate PASV transfer.\n"
msgstr ""
#: src/ftp.c:373
msgid "Cannot parse PASV response.\n"
msgstr ""
#: src/ftp.c:387
#, c-format
msgid "Will try connecting to %s:%hu.\n"
msgstr ""
#: src/ftp.c:432 src/ftp.c:504 src/ftp.c:548
msgid "done. "
msgstr ""
#: src/ftp.c:474
#, c-format
msgid "Bind error (%s).\n"
msgstr ""
#: src/ftp.c:490
msgid "Invalid PORT.\n"
msgstr ""
#: src/ftp.c:537
msgid ""
"\n"
"REST failed, starting from scratch.\n"
msgstr ""
#: src/ftp.c:586
#, c-format
msgid ""
"No such file `%s'.\n"
"\n"
msgstr ""
#: src/ftp.c:634
#, c-format
msgid ""
"No such file or directory `%s'.\n"
"\n"
msgstr ""
#: src/ftp.c:692 src/ftp.c:699
#, c-format
msgid "Length: %s"
msgstr ""
#: src/ftp.c:694 src/ftp.c:701
#, c-format
msgid " [%s to go]"
msgstr ""
#: src/ftp.c:703
msgid " (unauthoritative)\n"
msgstr ""
#: src/ftp.c:721
#, c-format
msgid "%s: %s, closing control connection.\n"
msgstr ""
#: src/ftp.c:729
#, c-format
msgid "%s (%s) - Data connection: %s; "
msgstr ""
#: src/ftp.c:746
msgid "Control connection closed.\n"
msgstr ""
#: src/ftp.c:764
msgid "Data transfer aborted.\n"
msgstr ""
#: src/ftp.c:830
#, c-format
msgid "File `%s' already there, not retrieving.\n"
msgstr ""
#: src/ftp.c:896 src/http.c:922
#, c-format
msgid "(try:%2d)"
msgstr ""
#: src/ftp.c:955 src/http.c:1116
#, c-format
msgid ""
"%s (%s) - `%s' saved [%ld]\n"
"\n"
msgstr ""
#: src/ftp.c:1001
#, c-format
msgid "Using `%s' as listing tmp file.\n"
msgstr ""
#: src/ftp.c:1013
#, c-format
msgid "Removed `%s'.\n"
msgstr ""
#: src/ftp.c:1049
#, c-format
msgid "Recursion depth %d exceeded max. depth %d.\n"
msgstr ""
#: src/ftp.c:1096 src/http.c:1054
#, c-format
msgid ""
"Local file `%s' is more recent, not retrieving.\n"
"\n"
msgstr ""
#: src/ftp.c:1102 src/http.c:1060
#, c-format
msgid "The sizes do not match (local %ld), retrieving.\n"
msgstr ""
#: src/ftp.c:1119
msgid "Invalid name of the symlink, skipping.\n"
msgstr ""
#: src/ftp.c:1136
#, c-format
msgid ""
"Already have correct symlink %s -> %s\n"
"\n"
msgstr ""
#: src/ftp.c:1144
#, c-format
msgid "Creating symlink %s -> %s\n"
msgstr ""
#: src/ftp.c:1155
#, c-format
msgid "Symlinks not supported, skipping symlink `%s'.\n"
msgstr ""
#: src/ftp.c:1167
#, c-format
msgid "Skipping directory `%s'.\n"
msgstr ""
#: src/ftp.c:1176
#, c-format
msgid "%s: unknown/unsupported file type.\n"
msgstr ""
#: src/ftp.c:1193
#, c-format
msgid "%s: corrupt time-stamp.\n"
msgstr ""
#: src/ftp.c:1213
#, c-format
msgid "Will not retrieve dirs since depth is %d (max %d).\n"
msgstr ""
#: src/ftp.c:1252
#, c-format
msgid "Not descending to `%s' as it is excluded/not-included.\n"
msgstr ""
#: src/ftp.c:1297
#, c-format
msgid "Rejecting `%s'.\n"
msgstr ""
#. No luck.
#. #### This message SUCKS. We should see what was the
#. reason that nothing was retrieved.
#: src/ftp.c:1344
#, c-format
msgid "No matches on pattern `%s'.\n"
msgstr ""
#: src/ftp.c:1404
#, c-format
msgid "Wrote HTML-ized index to `%s' [%ld].\n"
msgstr ""
#: src/ftp.c:1409
#, c-format
msgid "Wrote HTML-ized index to `%s'.\n"
msgstr ""
#: src/getopt.c:454
#, c-format
msgid "%s: option `%s' is ambiguous\n"
msgstr ""
#: src/getopt.c:478
#, c-format
msgid "%s: option `--%s' doesn't allow an argument\n"
msgstr ""
#: src/getopt.c:483
#, c-format
msgid "%s: option `%c%s' doesn't allow an argument\n"
msgstr ""
#: src/getopt.c:498
#, c-format
msgid "%s: option `%s' requires an argument\n"
msgstr ""
#. --option
#: src/getopt.c:528
#, c-format
msgid "%s: unrecognized option `--%s'\n"
msgstr ""
#. +option or -option
#: src/getopt.c:532
#, c-format
msgid "%s: unrecognized option `%c%s'\n"
msgstr ""
#. 1003.2 specifies the format of this message.
#: src/getopt.c:563
#, c-format
msgid "%s: illegal option -- %c\n"
msgstr ""
#. 1003.2 specifies the format of this message.
#: src/getopt.c:602
#, c-format
msgid "%s: option requires an argument -- %c\n"
msgstr ""
#: src/host.c:432
#, c-format
msgid "%s: Cannot determine user-id.\n"
msgstr ""
#: src/host.c:444
#, c-format
msgid "%s: Warning: uname failed: %s\n"
msgstr ""
#: src/host.c:456
#, c-format
msgid "%s: Warning: gethostname failed\n"
msgstr ""
#: src/host.c:484
#, c-format
msgid "%s: Warning: cannot determine local IP address.\n"
msgstr ""
#: src/host.c:498
#, c-format
msgid "%s: Warning: cannot reverse-lookup local IP address.\n"
msgstr ""
#. This gets ticked pretty often. Karl Berry reports
#. that there can be valid reasons for the local host
#. name not to be an FQDN, so I've decided to remove the
#. annoying warning.
#: src/host.c:511
#, c-format
msgid "%s: Warning: reverse-lookup of local address did not yield FQDN!\n"
msgstr ""
#: src/host.c:539
msgid "Host not found"
msgstr ""
#: src/host.c:541
msgid "Unknown error"
msgstr ""
#: src/html.c:439 src/html.c:441
#, c-format
msgid "Index of /%s on %s:%d"
msgstr ""
#: src/html.c:463
msgid "time unknown "
msgstr ""
#: src/html.c:467
msgid "File "
msgstr ""
#: src/html.c:470
msgid "Directory "
msgstr ""
#: src/html.c:473
msgid "Link "
msgstr ""
#: src/html.c:476
msgid "Not sure "
msgstr ""
#: src/html.c:494
#, c-format
msgid " (%s bytes)"
msgstr ""
#: src/http.c:492
msgid "Failed writing HTTP request.\n"
msgstr ""
#: src/http.c:497
#, c-format
msgid "%s request sent, awaiting response... "
msgstr ""
#: src/http.c:536
msgid "End of file while parsing headers.\n"
msgstr ""
#: src/http.c:547
#, c-format
msgid "Read error (%s) in headers.\n"
msgstr ""
#: src/http.c:587
msgid "No data received"
msgstr ""
#: src/http.c:589
msgid "Malformed status line"
msgstr ""
#: src/http.c:594
msgid "(no description)"
msgstr ""
#. If we have tried it already, then there is not point
#. retrying it.
#: src/http.c:678
msgid "Authorization failed.\n"
msgstr ""
#: src/http.c:685
msgid "Unknown authentication scheme.\n"
msgstr ""
#: src/http.c:748
#, c-format
msgid "Location: %s%s\n"
msgstr ""
#: src/http.c:749 src/http.c:774
msgid "unspecified"
msgstr ""
#: src/http.c:750
msgid " [following]"
msgstr ""
#. No need to print this output if the body won't be
#. downloaded at all, or if the original server response is
#. printed.
#: src/http.c:764
msgid "Length: "
msgstr ""
#: src/http.c:769
#, c-format
msgid " (%s to go)"
msgstr ""
#: src/http.c:774
msgid "ignored"
msgstr ""
#: src/http.c:857
msgid "Warning: wildcards not supported in HTTP.\n"
msgstr ""
#. If opt.noclobber is turned on and file already exists, do not
#. retrieve the file
#: src/http.c:872
#, c-format
msgid "File `%s' already there, will not retrieve.\n"
msgstr ""
#: src/http.c:978
#, c-format
msgid "Cannot write to `%s' (%s).\n"
msgstr ""
#: src/http.c:988
#, c-format
msgid "ERROR: Redirection (%d) without location.\n"
msgstr ""
#: src/http.c:1011
#, c-format
msgid "%s ERROR %d: %s.\n"
msgstr ""
#: src/http.c:1023
msgid "Last-modified header missing -- time-stamps turned off.\n"
msgstr ""
#: src/http.c:1031
msgid "Last-modified header invalid -- time-stamp ignored.\n"
msgstr ""
#: src/http.c:1064
msgid "Remote file is newer, retrieving.\n"
msgstr ""
#: src/http.c:1098
#, c-format
msgid ""
"%s (%s) - `%s' saved [%ld/%ld]\n"
"\n"
msgstr ""
#: src/http.c:1130
#, c-format
msgid "%s (%s) - Connection closed at byte %ld. "
msgstr ""
#: src/http.c:1138
#, c-format
msgid ""
"%s (%s) - `%s' saved [%ld/%ld])\n"
"\n"
msgstr ""
#: src/http.c:1150
#, c-format
msgid "%s (%s) - Connection closed at byte %ld/%ld. "
msgstr ""
#: src/http.c:1161
#, c-format
msgid "%s (%s) - Read error at byte %ld (%s)."
msgstr ""
#: src/http.c:1169
#, c-format
msgid "%s (%s) - Read error at byte %ld/%ld (%s). "
msgstr ""
#: src/init.c:312 src/netrc.c:250
#, c-format
msgid "%s: Cannot read %s (%s).\n"
msgstr ""
#: src/init.c:333 src/init.c:339
#, c-format
msgid "%s: Error in %s at line %d.\n"
msgstr ""
#: src/init.c:370
#, c-format
msgid "%s: Warning: Both system and user wgetrc point to `%s'.\n"
msgstr ""
#: src/init.c:458
#, c-format
msgid "%s: BUG: unknown command `%s', value `%s'.\n"
msgstr ""
#: src/init.c:485
#, c-format
msgid "%s: %s: Please specify on or off.\n"
msgstr ""
#: src/init.c:503 src/init.c:760 src/init.c:782 src/init.c:855
#, c-format
msgid "%s: %s: Invalid specification `%s'.\n"
msgstr ""
#: src/init.c:616 src/init.c:638 src/init.c:660 src/init.c:686
#, c-format
msgid "%s: Invalid specification `%s'\n"
msgstr ""
#: src/main.c:101
#, c-format
msgid "Usage: %s [OPTION]... [URL]...\n"
msgstr ""
#: src/main.c:109
#, c-format
msgid "GNU Wget %s, a non-interactive network retriever.\n"
msgstr ""
#. Had to split this in parts, so the #@@#%# Ultrix compiler and cpp
#. don't bitch. Also, it makes translation much easier.
#: src/main.c:114
msgid ""
"\n"
"Mandatory arguments to long options are mandatory for short options too.\n"
"\n"
msgstr ""
#: src/main.c:117
msgid ""
"Startup:\n"
" -V, --version display the version of Wget and exit.\n"
" -h, --help print this help.\n"
" -b, --background go to background after startup.\n"
" -e, --execute=COMMAND execute a `.wgetrc' command.\n"
"\n"
msgstr ""
#: src/main.c:123
msgid ""
"Logging and input file:\n"
" -o, --output-file=FILE log messages to FILE.\n"
" -a, --append-output=FILE append messages to FILE.\n"
" -d, --debug print debug output.\n"
" -q, --quiet quiet (no output).\n"
" -v, --verbose be verbose (this is the default).\n"
" -nv, --non-verbose turn off verboseness, without being quiet.\n"
" -i, --input-file=FILE read URL-s from file.\n"
" -F, --force-html treat input file as HTML.\n"
"\n"
msgstr ""
#: src/main.c:133
msgid ""
"Download:\n"
" -t, --tries=NUMBER set number of retries to NUMBER (0 "
"unlimits).\n"
" -O --output-document=FILE write documents to FILE.\n"
" -nc, --no-clobber don't clobber existing files.\n"
" -c, --continue restart getting an existing file.\n"
" --dot-style=STYLE set retrieval display style.\n"
" -N, --timestamping don't retrieve files if older than local.\n"
" -S, --server-response print server response.\n"
" --spider don't download anything.\n"
" -T, --timeout=SECONDS set the read timeout to SECONDS.\n"
" -w, --wait=SECONDS wait SECONDS between retrievals.\n"
" -Y, --proxy=on/off turn proxy on or off.\n"
" -Q, --quota=NUMBER set retrieval quota to NUMBER.\n"
"\n"
msgstr ""
#: src/main.c:147
msgid ""
"Directories:\n"
" -nd --no-directories don't create directories.\n"
" -x, --force-directories force creation of directories.\n"
" -nH, --no-host-directories don't create host directories.\n"
" -P, --directory-prefix=PREFIX save files to PREFIX/...\n"
" --cut-dirs=NUMBER ignore NUMBER remote directory "
"components.\n"
"\n"
msgstr ""
#: src/main.c:154
msgid ""
"HTTP options:\n"
" --http-user=USER set http user to USER.\n"
" --http-passwd=PASS set http password to PASS.\n"
" -C, --cache=on/off (dis)allow server-cached data (normally "
"allowed).\n"
" --ignore-length ignore `Content-Length' header field.\n"
" --header=STRING insert STRING among the headers.\n"
" --proxy-user=USER set USER as proxy username.\n"
" --proxy-passwd=PASS set PASS as proxy password.\n"
" -s, --save-headers save the HTTP headers to file.\n"
" -U, --user-agent=AGENT identify as AGENT instead of Wget/VERSION.\n"
"\n"
msgstr ""
#: src/main.c:165
msgid ""
"FTP options:\n"
" --retr-symlinks retrieve FTP symbolic links.\n"
" -g, --glob=on/off turn file name globbing on or off.\n"
" --passive-ftp use the \"passive\" transfer mode.\n"
"\n"
msgstr ""
#: src/main.c:170
msgid ""
"Recursive retrieval:\n"
" -r, --recursive recursive web-suck -- use with care!.\n"
" -l, --level=NUMBER maximum recursion depth (0 to unlimit).\n"
" --delete-after delete downloaded files.\n"
" -k, --convert-links convert non-relative links to relative.\n"
" -m, --mirror turn on options suitable for mirroring.\n"
" -nr, --dont-remove-listing don't remove `.listing' files.\n"
"\n"
msgstr ""
#: src/main.c:178
msgid ""
"Recursive accept/reject:\n"
" -A, --accept=LIST list of accepted extensions.\n"
" -R, --reject=LIST list of rejected extensions.\n"
" -D, --domains=LIST list of accepted domains.\n"
" --exclude-domains=LIST comma-separated list of rejected "
"domains.\n"
" -L, --relative follow relative links only.\n"
" --follow-ftp follow FTP links from HTML documents.\n"
" -H, --span-hosts go to foreign hosts when recursive.\n"
" -I, --include-directories=LIST list of allowed directories.\n"
" -X, --exclude-directories=LIST list of excluded directories.\n"
" -nh, --no-host-lookup don't DNS-lookup hosts.\n"
" -np, --no-parent don't ascend to the parent directory.\n"
"\n"
msgstr ""
#: src/main.c:191
msgid "Mail bug reports and suggestions to <bug-wget@gnu.org>.\n"
msgstr ""
#: src/main.c:347
#, c-format
msgid "%s: debug support not compiled in.\n"
msgstr ""
#: src/main.c:395
msgid ""
"Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.\n"
"This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
msgstr ""
#: src/main.c:401
msgid ""
"\n"
"Written by Hrvoje Niksic <hniksic@srce.hr>.\n"
msgstr ""
#: src/main.c:465
#, c-format
msgid "%s: %s: invalid command\n"
msgstr ""
#: src/main.c:515
#, c-format
msgid "%s: illegal option -- `-n%c'\n"
msgstr ""
#. #### Something nicer should be printed here -- similar to the
#. pre-1.5 `--help' page.
#: src/main.c:518 src/main.c:560 src/main.c:591
#, c-format
msgid "Try `%s --help' for more options.\n"
msgstr ""
#: src/main.c:571
msgid "Can't be verbose and quiet at the same time.\n"
msgstr ""
#: src/main.c:577
msgid "Can't timestamp and not clobber old files at the same time.\n"
msgstr ""
#. No URL specified.
#: src/main.c:586
#, c-format
msgid "%s: missing URL\n"
msgstr ""
#: src/main.c:674
#, c-format
msgid "No URLs found in %s.\n"
msgstr ""
#: src/main.c:683
#, c-format
msgid ""
"\n"
"FINISHED --%s--\n"
"Downloaded: %s bytes in %d files\n"
msgstr ""
#: src/main.c:688
#, c-format
msgid "Download quota (%s bytes) EXCEEDED!\n"
msgstr ""
#. Please note that the double `%' in `%%s' is intentional, because
#. redirect_output passes tmp through printf.
#: src/main.c:715
msgid "%s received, redirecting output to `%%s'.\n"
msgstr ""
#: src/mswindows.c:118
#, c-format
msgid ""
"\n"
"CTRL+Break received, redirecting output to `%s'.\n"
"Execution continued in background.\n"
"You may stop Wget by pressing CTRL+ALT+DELETE.\n"
msgstr ""
#. parent, no error
#: src/mswindows.c:135 src/utils.c:268
msgid "Continuing in background.\n"
msgstr ""
#: src/mswindows.c:137 src/utils.c:270
#, c-format
msgid "Output will be written to `%s'.\n"
msgstr ""
#: src/mswindows.c:227
#, c-format
msgid "Starting WinHelp %s\n"
msgstr ""
#: src/mswindows.c:254 src/mswindows.c:262
#, c-format
msgid "%s: Couldn't find usable socket driver.\n"
msgstr ""
#: src/netrc.c:334
#, c-format
msgid "%s: %s:%d: warning: \"%s\" token appears before any machine name\n"
msgstr ""
#: src/netrc.c:365
#, c-format
msgid "%s: %s:%d: unknown token \"%s\"\n"
msgstr ""
#: src/netrc.c:429
#, c-format
msgid "Usage: %s NETRC [HOSTNAME]\n"
msgstr ""
#: src/netrc.c:439
#, c-format
msgid "%s: cannot stat %s: %s\n"
msgstr ""
#: src/recur.c:449 src/retr.c:462
#, c-format
msgid "Removing %s.\n"
msgstr ""
#: src/recur.c:450
#, c-format
msgid "Removing %s since it should be rejected.\n"
msgstr ""
#: src/recur.c:609
msgid "Loading robots.txt; please ignore errors.\n"
msgstr ""
#: src/retr.c:193
#, c-format
msgid ""
"\n"
" [ skipping %dK ]"
msgstr ""
#: src/retr.c:344
msgid "Could not find proxy host.\n"
msgstr ""
#: src/retr.c:355
#, c-format
msgid "Proxy %s: Must be HTTP.\n"
msgstr ""
#: src/retr.c:398
#, c-format
msgid "%s: Redirection to itself.\n"
msgstr ""
#: src/retr.c:483
msgid ""
"Giving up.\n"
"\n"
msgstr ""
#: src/retr.c:483
msgid ""
"Retrying.\n"
"\n"
msgstr ""
#: src/url.c:940
#, c-format
msgid "Error (%s): Link %s without a base provided.\n"
msgstr ""
#: src/url.c:955
#, c-format
msgid "Error (%s): Base %s relative, without referer URL.\n"
msgstr ""
#: src/url.c:1373
#, c-format
msgid "Converting %s... "
msgstr ""
#: src/url.c:1378 src/url.c:1389
#, c-format
msgid "Cannot convert links in %s: %s\n"
msgstr ""
#: src/utils.c:71
#, c-format
msgid "%s: %s: Not enough memory.\n"
msgstr ""
#: src/utils.c:203
msgid "Unknown/unsupported protocol"
msgstr ""
#: src/utils.c:206
msgid "Invalid port specification"
msgstr ""
#: src/utils.c:209
msgid "Invalid host name"
msgstr ""
#: src/utils.c:430
#, c-format
msgid "Failed to unlink symlink `%s': %s\n"
msgstr ""

3206
src/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

158
src/Makefile.in Normal file
View File

@ -0,0 +1,158 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: @VERSION@
#
SHELL = /bin/sh
top_srcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
ANSI2KNR = @ANSI2KNR@
o = .@U@o
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sysconfdir = @sysconfdir@
localedir = $(prefix)/share/locale
CC = @CC@
CPPFLAGS = @CPPFLAGS@
# The following line is losing on some versions of make!
DEFS = @DEFS@ -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
exeext = @exeext@
INCLUDES = -I. -I$(srcdir)
COMPILE = $(CC) $(INCLUDES) $(CPPFLAGS) $(DEFS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
RM = rm -f
ETAGS = etags
# Conditional compiles
ALLOCA = @ALLOCA@
MD5_OBJ = @MD5_OBJ@
OPIE_OBJ = @OPIE_OBJ@
OBJ = $(ALLOCA) cmpt$o connect$o fnmatch$o ftp$o ftp-basic$o \
ftp-ls$o $(OPIE_OBJ) getopt$o headers$o host$o html$o \
http$o init$o log$o main$o $(MD5_OBJ) netrc$o rbuf$o \
recur$o retr$o url$o utils$o version$o
.SUFFIXES:
.SUFFIXES: .c .o ._c ._o
.c.o:
$(COMPILE) -c $<
.c._c: $(ANSI2KNR)
$(ANSI2KNR) $< > $*.tmp && mv $*.tmp $@
._c._o:
@echo $(COMPILE) -c $<
@rm -f _$*.c
@ln $< _$*.c && $(COMPILE) -c _$*.c && mv _$*.o $@ && rm _$*.c
.c._o: $(ANSI2KNR)
$(ANSI2KNR) $< > $*.tmp && mv $*.tmp $*._c
@echo $(COMPILE) -c $*._c
@rm -f _$*.c
@ln $*._c _$*.c && $(COMPILE) -c _$*.c && mv _$*.o $@ && rm _$*.c
# Dependencies for building
wget$(exeext): $(OBJ)
$(LINK) $(OBJ) $(LIBS)
ansi2knr: ansi2knr.o
$(CC) -o ansi2knr ansi2knr.o $(LIBS)
$(OBJ): $(ANSI2KNR)
#
# Dependencies for installing
#
install: install.bin
uninstall: uninstall.bin
install.bin: wget$(exeext)
$(top_srcdir)/mkinstalldirs $(bindir)
$(INSTALL_PROGRAM) wget$(exeext) $(bindir)/wget$(exeext)
uninstall.bin:
$(RM) $(bindir)/wget$(exeext)
#
# Dependencies for cleanup
#
clean:
$(RM) *.o wget$(exeext) *~ *.bak core $(ANSI2KNR) *._o *._c
distclean: clean
$(RM) Makefile config.h
realclean: distclean
$(RM) TAGS
#
# Dependencies for maintenance
#
subdir = src
Makefile: Makefile.in ../config.status
cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
TAGS: *.c *.h
-$(ETAGS) *.c *.h
# DO NOT DELETE THIS LINE -- make depend depends on it.
cmpt$o: config.h wget.h sysdep.h options.h
connect$o: config.h wget.h sysdep.h options.h connect.h host.h
fnmatch$o: config.h wget.h sysdep.h options.h fnmatch.h
ftp-basic$o: config.h wget.h sysdep.h options.h utils.h rbuf.h connect.h host.h
ftp-ls$o: config.h wget.h sysdep.h options.h utils.h ftp.h rbuf.h
ftp-opie$o: config.h wget.h sysdep.h options.h md5.h
ftp$o: config.h wget.h sysdep.h options.h utils.h url.h rbuf.h retr.h ftp.h html.h connect.h host.h fnmatch.h netrc.h
getopt$o: wget.h sysdep.h options.h
headers$o: config.h wget.h sysdep.h options.h connect.h rbuf.h headers.h
host$o: config.h wget.h sysdep.h options.h utils.h host.h url.h
html$o: config.h wget.h sysdep.h options.h url.h utils.h ftp.h rbuf.h html.h
http$o: config.h wget.h sysdep.h options.h utils.h url.h host.h rbuf.h retr.h headers.h connect.h fnmatch.h netrc.h
init$o: config.h wget.h sysdep.h options.h utils.h init.h host.h recur.h netrc.h
log$o: config.h wget.h sysdep.h options.h utils.h
main$o: config.h wget.h sysdep.h options.h utils.h getopt.h init.h retr.h rbuf.h recur.h host.h
md5$o: wget.h sysdep.h options.h md5.h
mswindows$o: config.h winsock.h wget.h sysdep.h options.h url.h
netrc$o: wget.h sysdep.h options.h utils.h netrc.h init.h
rbuf$o: config.h wget.h sysdep.h options.h rbuf.h connect.h
recur$o: config.h wget.h sysdep.h options.h url.h recur.h utils.h retr.h rbuf.h ftp.h fnmatch.h host.h
retr$o: config.h wget.h sysdep.h options.h utils.h retr.h rbuf.h url.h recur.h ftp.h host.h connect.h
url$o: config.h wget.h sysdep.h options.h utils.h url.h host.h html.h
utils$o: config.h wget.h sysdep.h options.h utils.h fnmatch.h

504
src/alloca.c Normal file
View File

@ -0,0 +1,504 @@
/* alloca.c -- allocate automatically reclaimed memory
(Mostly) portable public-domain implementation -- D A Gwyn
This implementation of the PWB library alloca function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
J.Otto Tennant <jot@cray.com> contributed the Cray support.
There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef emacs
#include "blockinput.h"
#endif
/* If compiling with GCC 2, this file's not needed. */
#if !defined (__GNUC__) || __GNUC__ < 2
/* If someone has defined alloca as a macro,
there must be some other way alloca is supposed to work. */
#ifndef alloca
#ifdef emacs
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs */
/* If your stack is a linked list of frames, you have to
provide an "address metric" ADDRESS_FUNCTION macro. */
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
long i00afunc ();
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
#else
#define ADDRESS_FUNCTION(arg) &(arg)
#endif
#if __STDC__
typedef void *pointer;
#else
typedef char *pointer;
#endif
#ifndef NULL
#define NULL 0
#endif
/* Different portions of Emacs need to call different versions of
malloc. The Emacs executable needs alloca to call xmalloc, because
ordinary malloc isn't protected from input signals. On the other
hand, the utilities in lib-src need alloca to call malloc; some of
them are very simple, and don't have an xmalloc routine.
Non-Emacs programs expect this to call xmalloc.
Callers below should use malloc. */
#ifndef emacs
#define malloc xmalloc
#endif
extern pointer malloc ();
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
#define STACK_DIR stack_dir
static void
find_stack_direction ()
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
#endif /* STACK_DIRECTION == 0 */
/* An "alloca header" is used to:
(a) chain together all alloca'ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc
alignment chunk size. The following default should work okay. */
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* To force sizeof(header). */
struct
{
union hdr *next; /* For chaining headers. */
char *deep; /* For stack depth measure. */
} h;
} header;
static header *last_alloca_header = NULL; /* -> last alloca header. */
/* Return a pointer to at least SIZE bytes of storage,
which will be automatically reclaimed upon exit from
the procedure that called alloca. Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32. */
pointer
alloca (size)
unsigned size;
{
auto char probe; /* Probes stack depth: */
register char *depth = ADDRESS_FUNCTION (probe);
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* Unknown growth direction. */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca'd storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* Traverses linked list. */
#ifdef emacs
BLOCK_INPUT;
#endif
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free ((pointer) hp); /* Collect garbage. */
hp = np; /* -> next header. */
}
else
break; /* Rest are not deeper. */
last_alloca_header = hp; /* -> last valid storage. */
#ifdef emacs
UNBLOCK_INPUT;
#endif
}
if (size == 0)
return NULL; /* No allocation required. */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) + size);
/* Address of header. */
if (new == 0)
abort();
((header *) new)->h.next = last_alloca_header;
((header *) new)->h.deep = depth;
last_alloca_header = (header *) new;
/* User storage begins just after header. */
return (pointer) ((char *) new + sizeof (header));
}
}
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
#ifdef DEBUG_I00AFUNC
#include <stdio.h>
#endif
#ifndef CRAY_STACK
#define CRAY_STACK
#ifndef CRAY2
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
struct stack_control_header
{
long shgrow:32; /* Number of times stack has grown. */
long shaseg:32; /* Size of increments to stack. */
long shhwm:32; /* High water mark of stack. */
long shsize:32; /* Current size of stack (all segments). */
};
/* The stack segment linkage control information occurs at
the high-address end of a stack segment. (The stack
grows from low addresses to high addresses.) The initial
part of the stack segment linkage control information is
0200 (octal) words. This provides for register storage
for the routine which overflows the stack. */
struct stack_segment_linkage
{
long ss[0200]; /* 0200 overflow words. */
long sssize:32; /* Number of words in this segment. */
long ssbase:32; /* Offset to stack base. */
long:32;
long sspseg:32; /* Offset to linkage control of previous
segment of stack. */
long:32;
long sstcpt:32; /* Pointer to task common address block. */
long sscsnm; /* Private control structure number for
microtasking. */
long ssusr1; /* Reserved for user. */
long ssusr2; /* Reserved for user. */
long sstpid; /* Process ID for pid based multi-tasking. */
long ssgvup; /* Pointer to multitasking thread giveup. */
long sscray[7]; /* Reserved for Cray Research. */
long ssa0;
long ssa1;
long ssa2;
long ssa3;
long ssa4;
long ssa5;
long ssa6;
long ssa7;
long sss0;
long sss1;
long sss2;
long sss3;
long sss4;
long sss5;
long sss6;
long sss7;
};
#else /* CRAY2 */
/* The following structure defines the vector of words
returned by the STKSTAT library routine. */
struct stk_stat
{
long now; /* Current total stack size. */
long maxc; /* Amount of contiguous space which would
be required to satisfy the maximum
stack demand to date. */
long high_water; /* Stack high-water mark. */
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
long hits; /* Number of internal buffer hits. */
long extends; /* Number of block extensions. */
long stko_mallocs; /* Block allocations by $STKOFEN. */
long underflows; /* Number of stack underflow calls ($STKRETN). */
long stko_free; /* Number of deallocations by $STKRETN. */
long stkm_free; /* Number of deallocations by $STKMRET. */
long segments; /* Current number of stack segments. */
long maxs; /* Maximum number of stack segments so far. */
long pad_size; /* Stack pad size. */
long current_address; /* Current stack segment address. */
long current_size; /* Current stack segment size. This
number is actually corrupted by STKSTAT to
include the fifteen word trailer area. */
long initial_address; /* Address of initial segment. */
long initial_size; /* Size of initial segment. */
};
/* The following structure describes the data structure which trails
any stack segment. I think that the description in 'asdef' is
out of date. I only describe the parts that I am sure about. */
struct stk_trailer
{
long this_address; /* Address of this block. */
long this_size; /* Size of this block (does not include
this trailer). */
long unknown2;
long unknown3;
long link; /* Address of trailer block of previous
segment. */
long unknown5;
long unknown6;
long unknown7;
long unknown8;
long unknown9;
long unknown10;
long unknown11;
long unknown12;
long unknown13;
long unknown14;
};
#endif /* CRAY2 */
#endif /* not CRAY_STACK */
#ifdef CRAY2
/* Determine a "stack measure" for an arbitrary ADDRESS.
I doubt that "lint" will like this much. */
static long
i00afunc (long *address)
{
struct stk_stat status;
struct stk_trailer *trailer;
long *block, size;
long result = 0;
/* We want to iterate through all of the segments. The first
step is to get the stack status structure. We could do this
more quickly and more directly, perhaps, by referencing the
$LM00 common block, but I know that this works. */
STKSTAT (&status);
/* Set up the iteration. */
trailer = (struct stk_trailer *) (status.current_address
+ status.current_size
- 15);
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
if (trailer == 0)
abort ();
/* Discard segments that do not contain our argument address. */
while (trailer != 0)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
if (block == 0 || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
break;
}
/* Set the result to the offset in this segment and add the sizes
of all predecessor segments. */
result = address - block;
if (trailer == 0)
{
return result;
}
do
{
if (trailer->this_size <= 0)
abort ();
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
while (trailer != 0);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
from subtracting the address of the first block. This is probably
not what you want. */
return (result);
}
#else /* not CRAY2 */
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Determine the number of the cell within the stack,
given the address of the cell. The purpose of this
routine is to linearize, in some sense, stack addresses
for alloca. */
static long
i00afunc (long address)
{
long stkl = 0;
long size, pseg, this_segment, stack;
long result = 0;
struct stack_segment_linkage *ssptr;
/* Register B67 contains the address of the end of the
current stack segment. If you (as a subprogram) store
your registers on the stack and find that you are past
the contents of B67, you have overflowed the segment.
B67 also points to the stack segment linkage control
area, which is what we are really interested in. */
stkl = CRAY_STACKSEG_END ();
ssptr = (struct stack_segment_linkage *) stkl;
/* If one subtracts 'size' from the end of the segment,
one has the address of the first word of the segment.
If this is not the first segment, 'pseg' will be
nonzero. */
pseg = ssptr->sspseg;
size = ssptr->sssize;
this_segment = stkl - size;
/* It is possible that calling this routine itself caused
a stack overflow. Discard stack segments which do not
contain the target address. */
while (!(this_segment <= address && address <= stkl))
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
#endif
if (pseg == 0)
break;
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
this_segment = stkl - size;
}
result = address - this_segment;
/* If you subtract pseg from the current end of the stack,
you get the address of the previous stack segment's end.
This seems a little convoluted to me, but I'll bet you save
a cycle somewhere. */
while (pseg != 0)
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o\n", pseg, size);
#endif
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
result += size;
}
return (result);
}
#endif /* not CRAY2 */
#endif /* CRAY */
#endif /* no alloca */
#endif /* not GCC version 2 */

550
src/ansi2knr.c Normal file
View File

@ -0,0 +1,550 @@
/* ansi2knr.c */
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
/*
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone for the
consequences of using it or for whether it serves any particular purpose or
works at all, unless he says so in writing. Refer to the GNU General Public
License (the "GPL") for full details.
Everyone is granted permission to copy, modify and redistribute ansi2knr,
but only under the conditions described in the GPL. A copy of this license
is supposed to have been given to you along with ansi2knr so you can know
your rights and responsibilities. It should be in a file named COPYLEFT.
Among other things, the copyright notice and this notice must be preserved
on all copies.
We explicitly state here what we believe is already implied by the GPL: if
the ansi2knr program is distributed as a separate set of sources and a
separate executable file which are aggregated on a storage medium together
with another program, this in itself does not bring the other program under
the GPL, nor does the mere fact that such a program or the procedures for
constructing it invoke the ansi2knr executable bring any other part of the
program under the GPL.
*/
/*
* Usage:
ansi2knr input_file [output_file]
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes function definitions by seeing a non-keyword
* identifier at the left margin, followed by a left parenthesis,
* with a right parenthesis as the last character on the line,
* and with a left brace as the first token on the following line
* (ignoring possible intervening comments).
* It will recognize a multi-line header provided that no intervening
* line ends with a left or right brace or a semicolon.
* These algorithms ignore whitespace and comments, except that
* the function name must be the first thing on the line.
* The following constructs will confuse it:
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Some macros that tinker with the syntax of the function header.
*/
/*
* The original and principal author of ansi2knr is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history
* that follows (in reverse chronological order):
lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
compilers that don't understand void, as suggested by
Tom Lane
lpd 96-01-15 changed to require that the first non-comment token
on the line following a function header be a left brace,
to reduce sensitivity to macros, as suggested by Tom Lane
<tgl@sss.pgh.pa.us>
lpd 95-06-22 removed #ifndefs whose sole purpose was to define
undefined preprocessor symbols as 0; changed all #ifdefs
for configuration symbols to #ifs
lpd 95-04-05 changed copyright notice to make it clear that
including ansi2knr in a program does not bring the entire
program under the GPL
lpd 94-12-18 added conditionals for systems where ctype macros
don't handle 8-bit characters properly, suggested by
Francois Pinard <pinard@iro.umontreal.ca>;
removed --varargs switch (this is now the default)
lpd 94-10-10 removed CONFIG_BROKETS conditional
lpd 94-07-16 added some conditionals to help GNU `configure',
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
properly erase prototype args in function parameters,
contributed by Jim Avera <jima@netcom.com>;
correct error in writeblanks (it shouldn't erase EOLs)
lpd 89-xx-xx original version
*/
/* Most of the conditionals here are to make ansi2knr work with */
/* or without the GNU configure machinery. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#if HAVE_CONFIG_H
/*
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
This will define HAVE_CONFIG_H and so, activate the following lines.
*/
# if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
#else /* not HAVE_CONFIG_H */
/* Otherwise do it the hard way */
# ifdef BSD
# include <strings.h>
# else
# ifdef VMS
extern int strlen(), strncmp();
# else
# include <string.h>
# endif
# endif
#endif /* not HAVE_CONFIG_H */
#if STDC_HEADERS
# include <stdlib.h>
#else
/*
malloc and free should be declared in stdlib.h,
but if you've got a K&R compiler, they probably aren't.
*/
# ifdef MSDOS
# include <malloc.h>
# else
# ifdef VMS
extern char *malloc();
extern void free();
# else
extern char *malloc();
extern int free();
# endif
# endif
#endif
/*
* The ctype macros don't always handle 8-bit characters correctly.
* Compensate for this here.
*/
#ifdef isascii
# undef HAVE_ISASCII /* just in case */
# define HAVE_ISASCII 1
#else
#endif
#if STDC_HEADERS || !HAVE_ISASCII
# define is_ascii(c) 1
#else
# define is_ascii(c) isascii(c)
#endif
#define is_space(c) (is_ascii(c) && isspace(c))
#define is_alpha(c) (is_ascii(c) && isalpha(c))
#define is_alnum(c) (is_ascii(c) && isalnum(c))
/* Scanning macros */
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
/* Forward references */
char *skipspace();
int writeblanks();
int test1();
int convert1();
/* The main program */
int
main(argc, argv)
int argc;
char *argv[];
{ FILE *in, *out;
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
char *more;
/*
* In previous versions, ansi2knr recognized a --varargs switch.
* If this switch was supplied, ansi2knr would attempt to convert
* a ... argument to va_alist and va_dcl; if this switch was not
* supplied, ansi2knr would simply drop any such arguments.
* Now, ansi2knr always does this conversion, and we only
* check for this switch for backward compatibility.
*/
int convert_varargs = 1;
if ( argc > 1 && argv[1][0] == '-' )
{ if ( !strcmp(argv[1], "--varargs") )
{ convert_varargs = 1;
argc--;
argv++;
}
else
{ fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
exit(1);
}
}
if (argc < 2 || argc > 3)
{
printf("Usage: ansi2knr input_file [output_file]\n");
exit(1);
}
in = fopen(argv[1], "r");
if ( in == NULL )
{
fprintf(stderr, "Cannot open input file %s\n", argv[1]);
exit(1);
}
if (argc == 3)
{
out = fopen(argv[2], "w");
if ( out == NULL )
{
fprintf(stderr, "Cannot open output file %s\n", argv[2]);
exit(1);
}
}
else
{
out = stdout;
}
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
buf = malloc(bufsize);
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{
test: line += strlen(line);
switch ( test1(buf) )
{
case 2: /* a function header */
convert1(buf, out, 1, convert_varargs);
break;
case 1: /* a function */
/* Check for a { at the start of the next line. */
more = ++line;
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
goto wl;
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
goto wl;
switch ( *skipspace(more, 1) )
{
case '{':
/* Definitely a function header. */
convert1(buf, out, 0, convert_varargs);
fputs(more, out);
break;
case 0:
/* The next line was blank or a comment: */
/* keep scanning for a non-comment. */
line += strlen(line);
goto f;
default:
/* buf isn't a function header, but */
/* more might be. */
fputs(buf, out);
strcpy(buf, more);
line = buf;
goto test;
}
break;
case -1: /* maybe the start of a function */
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
wl: fputs(buf, out);
break;
}
line = buf;
}
if ( line != buf )
fputs(buf, out);
free(buf);
fclose(out);
fclose(in);
return 0;
}
/* Skip over space and comments, in either direction. */
char *
skipspace(p, dir)
register char *p;
register int dir; /* 1 for forward, -1 for backward */
{ for ( ; ; )
{ while ( is_space(*p) )
p += dir;
if ( !(*p == '/' && p[dir] == '*') )
break;
p += dir; p += dir;
while ( !(*p == '*' && p[dir] == '/') )
{ if ( *p == 0 )
return p; /* multi-line comment?? */
p += dir;
}
p += dir; p += dir;
}
return p;
}
/*
* Write blanks over part of a string.
* Don't overwrite end-of-line characters.
*/
int
writeblanks(start, end)
char *start;
char *end;
{ char *p;
for ( p = start; p < end; p++ )
if ( *p != '\r' && *p != '\n' )
*p = ' ';
return 0;
}
/*
* Test whether the string in buf is a function definition.
* The string may contain and/or end with a newline.
* Return as follows:
* 0 - definitely not a function definition;
* 1 - definitely a function definition;
* 2 - definitely a function prototype (NOT USED);
* -1 - may be the beginning of a function definition,
* append another line and look again.
* The reason we don't attempt to convert function prototypes is that
* Ghostscript's declaration-generating macros look too much like
* prototypes, and confuse the algorithms.
*/
int
test1(buf)
char *buf;
{ register char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
bend = skipspace(buf + strlen(buf) - 1, -1);
switch ( *bend )
{
case ';': contin = 0 /*2*/; break;
case ')': contin = 1; break;
case '{': return 0; /* not a function */
case '}': return 0; /* not a function */
default: contin = -1;
}
while ( isidchar(*p) )
p++;
endfn = p;
p = skipspace(p, 1);
if ( *p++ != '(' )
return 0; /* not a function */
p = skipspace(p, 1);
if ( *p == ')' )
return 0; /* no parameters */
/* Check that the apparent function name isn't a keyword. */
/* We only need to check for keywords that could be followed */
/* by a left parenthesis (which, unfortunately, is most of them). */
{ static char *words[] =
{ "asm", "auto", "case", "char", "const", "double",
"extern", "float", "for", "if", "int", "long",
"register", "return", "short", "signed", "sizeof",
"static", "switch", "typedef", "unsigned",
"void", "volatile", "while", 0
};
char **key = words;
char *kp;
int len = endfn - buf;
while ( (kp = *key) != 0 )
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
return 0; /* name is a keyword */
key++;
}
}
return contin;
}
/* Convert a recognized function definition or header to K&R syntax. */
int
convert1(buf, out, header, convert_varargs)
char *buf;
FILE *out;
int header; /* Boolean */
int convert_varargs; /* Boolean */
{ char *endfn;
register char *p;
/*
* The breaks table contains pointers to the beginning and end
* of each argument.
*/
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
char *vararg = 0;
/* Pre-ANSI implementations don't agree on whether strchr */
/* is called strchr or index, so we open-code it here. */
for ( endfn = buf; *(endfn++) != '('; )
;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == 0 )
{ /* Couldn't allocate break table, give up */
fprintf(stderr, "Unable to allocate break table!\n");
fputs(buf, out);
return -1;
}
btop = breaks + num_breaks * 2 - 2;
bp = breaks;
/* Parse the argument list */
do
{ int level = 0;
char *lp = NULL;
char *rp;
char *end = NULL;
if ( bp >= btop )
{ /* Filled up break table. */
/* Allocate a bigger one and start over. */
free((char *)breaks);
num_breaks <<= 1;
goto top;
}
*bp++ = p;
/* Find the end of the argument */
for ( ; end == NULL; p++ )
{ switch(*p)
{
case ',':
if ( !level ) end = p;
break;
case '(':
if ( !level ) lp = p;
level++;
break;
case ')':
if ( --level < 0 ) end = p;
else rp = p;
break;
case '/':
p = skipspace(p, 1) - 1;
break;
default:
;
}
}
/* Erase any embedded prototype parameters. */
if ( lp )
writeblanks(lp + 1, rp);
p--; /* back up over terminator */
/* Find the name being declared. */
/* This is complicated because of procedure and */
/* array modifiers. */
for ( ; ; )
{ p = skipspace(p - 1, -1);
switch ( *p )
{
case ']': /* skip array dimension(s) */
case ')': /* skip procedure args OR name */
{ int level = 1;
while ( level )
switch ( *--p )
{
case ']': case ')': level++; break;
case '[': case '(': level--; break;
case '/': p = skipspace(p, -1) + 1; break;
default: ;
}
}
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
{ /* We found the name being declared */
while ( !isidfirstchar(*p) )
p = skipspace(p, 1) + 1;
goto found;
}
break;
default:
goto found;
}
}
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
{ if ( convert_varargs )
{ *bp++ = "va_alist";
vararg = p-2;
}
else
{ p++;
if ( bp == breaks + 1 ) /* sole argument */
writeblanks(breaks[0], p);
else
writeblanks(bp[-1] - 1, p);
bp--;
}
}
else
{ while ( isidchar(*p) ) p--;
*bp++ = p+1;
}
p = end;
}
while ( *p++ == ',' );
*bp = p;
/* Make a special check for 'void' arglist */
if ( bp == breaks+2 )
{ p = skipspace(breaks[0], 1);
if ( !strncmp(p, "void", 4) )
{ p = skipspace(p+4, 1);
if ( p == breaks[2] - 1 )
{ bp = breaks; /* yup, pretend arglist is empty */
writeblanks(breaks[0], p + 1);
}
}
}
/* Put out the function name and left parenthesis. */
p = buf;
while ( p != endfn ) putc(*p, out), p++;
/* Put out the declaration. */
if ( header )
{ fputs(");", out);
for ( p = breaks[0]; *p; p++ )
if ( *p == '\r' || *p == '\n' )
putc(*p, out);
}
else
{ for ( ap = breaks+1; ap < bp; ap += 2 )
{ p = *ap;
while ( isidchar(*p) )
putc(*p, out), p++;
if ( ap < bp - 1 )
fputs(", ", out);
}
fputs(") ", out);
/* Put out the argument declarations */
for ( ap = breaks+2; ap <= bp; ap += 2 )
(*ap)[-1] = ';';
if ( vararg != 0 )
{ *vararg = 0;
fputs(breaks[0], out); /* any prior args */
fputs("va_dcl", out); /* the final arg */
fputs(bp[0], out);
}
else
fputs(breaks[0], out);
}
free((char *)breaks);
return 0;
}

1191
src/cmpt.c Normal file

File diff suppressed because it is too large Load Diff

183
src/config.h.in Normal file
View File

@ -0,0 +1,183 @@
/* Configuration header file.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef CONFIG_H
#define CONFIG_H
/* Define if you have the <alloca.h> header file. */
#undef HAVE_ALLOCA_H
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define to empty if the keyword does not work. */
#undef const
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if your architecture is big endian (with the most
significant byte first). */
#undef WORDS_BIGENDIAN
/* Define this if you want the NLS support. */
#undef HAVE_NLS
/* Define if you want the FTP support for Opie compiled in. */
#undef USE_OPIE
/* Define if you want the HTTP Digest Authorization compiled in. */
#undef USE_DIGEST
/* Define if you want the debug output support compiled in. */
#undef DEBUG
/* Define if you have sys/time.h header. */
#undef HAVE_SYS_TIME_H
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if you have struct utimbuf. */
#undef HAVE_STRUCT_UTIMBUF
/* Define if you have the uname function. */
#undef HAVE_UNAME
/* Define if you have the gethostname function. */
#undef HAVE_GETHOSTNAME
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define if you have the sys/utsname.h header. */
#undef HAVE_SYS_UTSNAME_H
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the vsnprintf function. */
#undef HAVE_VSNPRINTF
/* Define if you have the strstr function. */
#undef HAVE_STRSTR
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
/* Define if you have the strncasecmp function. */
#undef HAVE_STRNCASECMP
/* Define if you have the strptime function. */
#undef HAVE_STRPTIME
/* Define if you have the mktime function. */
#undef HAVE_MKTIME
/* Define if you have the symlink function. */
#undef HAVE_SYMLINK
/* Define if you have the access function. */
#undef HAVE_ACCESS
/* Define if you have the isatty function. */
#undef HAVE_ISATTY
/* Define if you have the signal function. */
#undef HAVE_SIGNAL
/* Define if you have the gettext function. */
#undef HAVE_GETTEXT
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define if you have the <sys/utime.h> header file. */
#undef HAVE_SYS_UTIME_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define if you have the <libintl.h> header file. */
#undef HAVE_LIBINTL_H
/* Define if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to be the name of the operating system. */
#undef OS_TYPE
/* Define if you wish to compile with socks support. */
#undef HAVE_SOCKS
/* Define to 1 if ANSI function prototypes are usable. */
#undef PROTOTYPES
#endif /* CONFIG_H */

308
src/connect.c Normal file
View File

@ -0,0 +1,308 @@
/* Establishing and handling network connections.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef WINDOWS
# include <winsock.h>
#else
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
# include <arpa/inet.h>
#endif /* WINDOWS */
#include <errno.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H */
#include "wget.h"
#include "connect.h"
#include "host.h"
#ifndef errno
extern int errno;
#endif
/* Variables shared by bindport and acceptport: */
static int msock = -1;
static struct sockaddr *addr;
/* Create an internet connection to HOSTNAME on PORT. The created
socket will be stored to *SOCK. */
uerr_t
make_connection (int *sock, char *hostname, unsigned short port)
{
struct sockaddr_in sock_name;
/* struct hostent *hptr; */
/* Get internet address of the host. We can do it either by calling
ngethostbyname, or by calling store_hostaddress, from host.c.
storehostaddress is better since it caches calls to
gethostbyname. */
#if 1
if (!store_hostaddress ((unsigned char *)&sock_name.sin_addr, hostname))
return HOSTERR;
#else /* never */
if (!(hptr = ngethostbyname (hostname)))
return HOSTERR;
/* Copy the address of the host to socket description. */
memcpy (&sock_name.sin_addr, hptr->h_addr, hptr->h_length);
#endif /* never */
/* Set port and protocol */
sock_name.sin_family = AF_INET;
sock_name.sin_port = htons (port);
/* Make an internet socket, stream type. */
if ((*sock = socket (AF_INET, SOCK_STREAM, 0)) == -1)
return CONSOCKERR;
/* Connect the socket to the remote host. */
if (connect (*sock, (struct sockaddr *) &sock_name, sizeof (sock_name)))
{
if (errno == ECONNREFUSED)
return CONREFUSED;
else
return CONERROR;
}
DEBUGP (("Created fd %d.\n", *sock));
return NOCONERROR;
}
/* Bind the local port PORT. This does all the necessary work, which
is creating a socket, setting SO_REUSEADDR option on it, then
calling bind() and listen(). If *PORT is 0, a random port is
chosen by the system, and its value is stored to *PORT. The
internal variable MPORT is set to the value of the ensuing master
socket. Call acceptport() to block for and accept a connection. */
uerr_t
bindport (unsigned short *port)
{
int optval = 1;
static struct sockaddr_in srv;
msock = -1;
addr = (struct sockaddr *) &srv;
if ((msock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
return CONSOCKERR;
if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
(char *)&optval, sizeof (optval)) < 0)
return CONSOCKERR;
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = htonl (INADDR_ANY);
srv.sin_port = htons (*port);
if (bind (msock, addr, sizeof (struct sockaddr_in)) < 0)
{
CLOSE (msock);
msock = -1;
return BINDERR;
}
DEBUGP (("Master socket fd %d bound.\n", msock));
if (!*port)
{
size_t addrlen = sizeof (struct sockaddr_in);
if (getsockname (msock, addr, (int *)&addrlen) < 0)
{
CLOSE (msock);
msock = -1;
return CONPORTERR;
}
*port = ntohs (srv.sin_port);
}
if (listen (msock, 1) < 0)
{
CLOSE (msock);
msock = -1;
return LISTENERR;
}
return BINDOK;
}
#ifdef HAVE_SELECT
/* Wait for file descriptor FD to be readable, MAXTIME being the
timeout in seconds. If WRITEP is non-zero, checks for FD being
writable instead.
Returns 1 if FD is accessible, 0 for timeout and -1 for error in
select(). */
static int
select_fd (int fd, int maxtime, int writep)
{
fd_set fds, exceptfds;
struct timeval timeout;
FD_ZERO (&fds);
FD_SET (fd, &fds);
FD_ZERO (&exceptfds);
FD_SET (fd, &exceptfds);
timeout.tv_sec = maxtime;
timeout.tv_usec = 0;
/* HPUX reportedly warns here. What is the correct incantation? */
return select (fd + 1, writep ? NULL : &fds, writep ? &fds : NULL,
&exceptfds, &timeout);
}
#endif /* HAVE_SELECT */
/* Call accept() on MSOCK and store the result to *SOCK. This assumes
that bindport() has been used to initialize MSOCK to a correct
value. It blocks the caller until a connection is established. If
no connection is established for OPT.TIMEOUT seconds, the function
exits with an error status. */
uerr_t
acceptport (int *sock)
{
int addrlen = sizeof (struct sockaddr_in);
#ifdef HAVE_SELECT
if (select_fd (msock, opt.timeout, 0) <= 0)
return ACCEPTERR;
#endif
if ((*sock = accept (msock, addr, &addrlen)) < 0)
return ACCEPTERR;
DEBUGP (("Created socket fd %d.\n", *sock));
return ACCEPTOK;
}
/* Close SOCK, as well as the most recently remembered MSOCK, created
via bindport(). If SOCK is -1, close MSOCK only. */
void
closeport (int sock)
{
/*shutdown (sock, 2);*/
if (sock != -1)
CLOSE (sock);
if (msock != -1)
CLOSE (msock);
msock = -1;
}
/* Return the local IP address associated with the connection on FD.
It is returned in a static buffer. */
unsigned char *
conaddr (int fd)
{
static unsigned char res[4];
struct sockaddr_in mysrv;
struct sockaddr *myaddr;
size_t addrlen = sizeof (mysrv);
myaddr = (struct sockaddr *) (&mysrv);
if (getsockname (fd, myaddr, (int *)&addrlen) < 0)
return NULL;
memcpy (res, &mysrv.sin_addr, 4);
return res;
}
/* Read at most LEN bytes from FD, storing them to BUF. This is
virtually the same as read(), but takes care of EINTR braindamage
and uses select() to timeout the stale connections (a connection is
stale if more than OPT.TIMEOUT time is spent in select() or
read()). */
int
iread (int fd, char *buf, int len)
{
int res;
do
{
#ifdef HAVE_SELECT
if (opt.timeout)
{
do
{
res = select_fd (fd, opt.timeout, 0);
}
while (res == -1 && errno == EINTR);
if (res <= 0)
{
/* Set errno to ETIMEDOUT on timeout. */
if (res == 0)
/* #### Potentially evil! */
errno = ETIMEDOUT;
return -1;
}
}
#endif
res = READ (fd, buf, len);
}
while (res == -1 && errno == EINTR);
return res;
}
/* Write LEN bytes from BUF to FD. This is similar to iread(), but
doesn't bother with select(). Unlike iread(), it makes sure that
all of BUF is actually written to FD, so callers needn't bother
with checking that the return value equals to LEN. Instead, you
should simply check for -1. */
int
iwrite (int fd, char *buf, int len)
{
int res = 0;
/* `write' may write less than LEN bytes, thus the outward loop
keeps trying it until all was written, or an error occurred. The
inner loop is reserved for the usual EINTR f*kage, and the
innermost loop deals with the same during select(). */
while (len > 0)
{
do
{
#ifdef HAVE_SELECT
if (opt.timeout)
{
do
{
res = select_fd (fd, opt.timeout, 1);
}
while (res == -1 && errno == EINTR);
if (res <= 0)
{
/* Set errno to ETIMEDOUT on timeout. */
if (res == 0)
/* #### Potentially evil! */
errno = ETIMEDOUT;
return -1;
}
}
#endif
res = WRITE (fd, buf, len);
}
while (res == -1 && errno == EINTR);
if (res <= 0)
break;
buf += res;
len -= res;
}
return res;
}

33
src/connect.h Normal file
View File

@ -0,0 +1,33 @@
/* Declarations for connect.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef CONNECT_H
#define CONNECT_H
/* Function declarations */
uerr_t make_connection PARAMS ((int *, char *, unsigned short));
uerr_t bindport PARAMS ((unsigned short *));
uerr_t acceptport PARAMS ((int *));
void closeport PARAMS ((int));
unsigned char *conaddr PARAMS ((int));
int iread PARAMS ((int, char *, int));
int iwrite PARAMS ((int, char *, int));
#endif /* CONNECT_H */

200
src/fnmatch.c Normal file
View File

@ -0,0 +1,200 @@
/* Pattern matching (globbing).
Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* NOTE: Some Un*xes have their own fnmatch() -- yet, they are
reportedly unreliable and buggy. Thus I chose never to use it;
this version (from GNU Bash) is used unconditionally. */
#include <config.h>
#include <errno.h>
#include "wget.h"
#include "fnmatch.h"
/* Match STRING against the filename pattern PATTERN, returning zero
if it matches, FNM_NOMATCH if not. */
int
fnmatch (const char *pattern, const char *string, int flags)
{
register const char *p = pattern, *n = string;
register char c;
if ((flags & ~__FNM_FLAGS) != 0)
{
errno = EINVAL;
return (-1);
}
while ((c = *p++) != '\0')
{
switch (c)
{
case '?':
if (*n == '\0')
return (FNM_NOMATCH);
else if ((flags & FNM_PATHNAME) && *n == '/')
return (FNM_NOMATCH);
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
c = *p++;
if (*n != c)
return (FNM_NOMATCH);
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
if (((flags & FNM_PATHNAME) && *n == '/') ||
(c == '?' && *n == '\0'))
return (FNM_NOMATCH);
if (c == '\0')
return (0);
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
if ((c == '[' || *n == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return (0);
return (FNM_NOMATCH);
}
case '[':
{
/* Nonzero if the sense of the character class is
inverted. */
register int not;
if (*n == '\0')
return (FNM_NOMATCH);
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
/* Make sure there is a closing `]'. If there isn't,
the `[' is just a character to be matched. */
{
register const char *np;
for (np = p; np && *np && *np != ']'; np++);
if (np && !*np)
{
if (*n != '[')
return (FNM_NOMATCH);
goto next_char;
}
}
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
while (1)
{
register char cstart = c, cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
cstart = cend = *p++;
if (c == '\0')
/* [ (unterminated) loses. */
return (FNM_NOMATCH);
c = *p++;
if ((flags & FNM_PATHNAME) && c == '/')
/* [/] can never match. */
return (FNM_NOMATCH);
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return (FNM_NOMATCH);
c = *p++;
}
if (*n >= cstart && *n <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return (FNM_NOMATCH);
next_char:
break;
matched:
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return (FNM_NOMATCH);
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
/* 1003.2d11 is unclear if this is right. %%% */
++p;
}
if (not)
return (FNM_NOMATCH);
}
break;
default:
if (c != *n)
return (FNM_NOMATCH);
}
++n;
}
if (*n == '\0')
return (0);
return (FNM_NOMATCH);
}
/* Return non-zero if S contains globbing wildcards (`*', `?', `[' or
`]'). */
int
has_wildcards_p (const char *s)
{
for (; *s; s++)
if (*s == '*' || *s == '?' || *s == '[' || *s == ']')
return 1;
return 0;
}

35
src/fnmatch.h Normal file
View File

@ -0,0 +1,35 @@
/* Declarations for fnmatch.c.
Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef MTCH_H
#define MTCH_H
/* Bits set in the FLAGS argument to `fnmatch'. */
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
#define FNM_NOMATCH 1
int fnmatch PARAMS ((const char *, const char *, int));
int has_wildcards_p PARAMS ((const char *));
#endif /* MTCH_H */

539
src/ftp-basic.c Normal file
View File

@ -0,0 +1,539 @@
/* Basic FTP routines.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <ctype.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <sys/types.h>
#ifdef WINDOWS
# include <winsock.h>
#endif
#include "wget.h"
#include "utils.h"
#include "rbuf.h"
#include "connect.h"
#include "host.h"
#ifndef errno
extern int errno;
#endif
#ifndef h_errno
extern int h_errno;
#endif
char ftp_last_respline[128];
/* Get the response of FTP server and allocate enough room to handle
it. <CR> and <LF> characters are stripped from the line, and the
line is 0-terminated. All the response lines but the last one are
skipped. The last line is determined as described in RFC959. */
uerr_t
ftp_response (struct rbuf *rbuf, char **line)
{
int i;
int bufsize = 40;
*line = (char *)xmalloc (bufsize);
do
{
for (i = 0; 1; i++)
{
int res;
if (i > bufsize - 1)
*line = (char *)xrealloc (*line, (bufsize <<= 1));
res = RBUF_READCHAR (rbuf, *line + i);
/* RES is number of bytes read. */
if (res == 1)
{
if ((*line)[i] == '\n')
{
(*line)[i] = '\0';
/* Get rid of \r. */
if (i > 0 && (*line)[i - 1] == '\r')
(*line)[i - 1] = '\0';
break;
}
}
else
return FTPRERR;
}
if (opt.server_response)
logprintf (LOG_ALWAYS, "%s\n", *line);
else
DEBUGP (("%s\n", *line));
}
while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
return FTPOK;
}
/* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
it if printing is required. If VALUE is NULL, just use
command<CR><LF>. */
static char *
ftp_request (const char *command, const char *value)
{
char *res = (char *)xmalloc (strlen (command)
+ (value ? (1 + strlen (value)) : 0)
+ 2 + 1);
sprintf (res, "%s%s%s\r\n", command, value ? " " : "", value ? value : "");
if (opt.server_response)
{
/* Hack: don't print out password. */
if (strncmp (res, "PASS", 4) != 0)
logprintf (LOG_ALWAYS, "--> %s\n", res);
else
logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
}
else
DEBUGP (("\n--> %s\n", res));
return res;
}
#ifdef USE_OPIE
const char *calculate_skey_response PARAMS ((int, const char *, const char *));
#endif
/* Sends the USER and PASS commands to the server, to control
connection socket csock. */
uerr_t
ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
{
uerr_t err;
char *request, *respline;
int nwritten;
/* Get greeting. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '2')
{
free (respline);
return FTPSRVERR;
}
free (respline);
/* Send USER username. */
request = ftp_request ("USER", acc);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
/* An unprobable possibility of logging without a password. */
if (*respline == '2')
{
free (respline);
return FTPOK;
}
/* Else, only response 3 is appropriate. */
if (*respline != '3')
{
free (respline);
return FTPLOGREFUSED;
}
#ifdef USE_OPIE
{
static const char *skey_head[] = {
"331 s/key ",
"331 opiekey "
};
int i;
for (i = 0; i < ARRAY_SIZE (skey_head); i++)
{
if (strncmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
break;
}
if (i < ARRAY_SIZE (skey_head))
{
const char *cp;
int skey_sequence = 0;
for (cp = respline + strlen (skey_head[i]);
'0' <= *cp && *cp <= '9';
cp++)
{
skey_sequence = skey_sequence * 10 + *cp - '0';
}
if (*cp == ' ')
cp++;
else
{
bad:
free (respline);
return FTPLOGREFUSED;
}
if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
goto bad;
pass = cp;
}
}
#endif /* USE_OPIE */
free (respline);
/* Send PASS password. */
request = ftp_request ("PASS", pass);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '2')
{
free (respline);
return FTPLOGINC;
}
free (respline);
/* All OK. */
return FTPOK;
}
/* Bind a port and send the appropriate PORT command to the FTP
server. Use acceptport after RETR, to get the socket of data
connection. */
uerr_t
ftp_port (struct rbuf *rbuf)
{
uerr_t err;
char *request, *respline, *bytes;
unsigned char *in_addr;
int nwritten;
unsigned short port;
/* Setting port to 0 lets the system choose a free port. */
port = 0;
/* Bind the port. */
err = bindport (&port);
if (err != BINDOK)
return err;
/* Get the address of this side of the connection. */
if (!(in_addr = conaddr (RBUF_FD (rbuf))))
return HOSTERR;
/* Construct the argument of PORT (of the form a,b,c,d,e,f). */
bytes = (char *)alloca (6 * 4 + 1);
sprintf (bytes, "%d,%d,%d,%d,%d,%d", in_addr[0], in_addr[1],
in_addr[2], in_addr[3], (unsigned) (port & 0xff00) >> 8,
port & 0xff);
/* Send PORT request. */
request = ftp_request ("PORT", bytes);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '2')
{
free (respline);
return FTPPORTERR;
}
free (respline);
return FTPOK;
}
/* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */
uerr_t
ftp_pasv (struct rbuf *rbuf, unsigned char *addr)
{
char *request, *respline, *s;
int nwritten, i;
uerr_t err;
/* Form the request. */
request = ftp_request ("PASV", NULL);
/* And send it. */
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get the server response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '2')
{
free (respline);
return FTPNOPASV;
}
/* Parse the request. */
s = respline;
for (s += 4; *s && !ISDIGIT (*s); s++);
if (!*s)
return FTPINVPASV;
for (i = 0; i < 6; i++)
{
addr[i] = 0;
for (; ISDIGIT (*s); s++)
addr[i] = (*s - '0') + 10 * addr[i];
if (*s == ',')
s++;
else if (i < 5)
{
/* When on the last number, anything can be a terminator. */
free (respline);
return FTPINVPASV;
}
}
free (respline);
return FTPOK;
}
/* Sends the TYPE request to the server. */
uerr_t
ftp_type (struct rbuf *rbuf, int type)
{
char *request, *respline;
int nwritten;
uerr_t err;
char stype[2];
/* Construct argument. */
stype[0] = type;
stype[1] = 0;
/* Send TYPE request. */
request = ftp_request ("TYPE", stype);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '2')
{
free (respline);
return FTPUNKNOWNTYPE;
}
free (respline);
/* All OK. */
return FTPOK;
}
/* Changes the working directory by issuing a CWD command to the
server. */
uerr_t
ftp_cwd (struct rbuf *rbuf, const char *dir)
{
char *request, *respline;
int nwritten;
uerr_t err;
/* Send CWD request. */
request = ftp_request ("CWD", dir);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline == '5')
{
free (respline);
return FTPNSFOD;
}
if (*respline != '2')
{
free (respline);
return FTPRERR;
}
free (respline);
/* All OK. */
return FTPOK;
}
/* Sends REST command to the FTP server. */
uerr_t
ftp_rest (struct rbuf *rbuf, long offset)
{
char *request, *respline;
int nwritten;
uerr_t err;
static char numbuf[20]; /* Buffer for the number */
long_to_string (numbuf, offset);
request = ftp_request ("REST", numbuf);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline != '3')
{
free (respline);
return FTPRESTFAIL;
}
free (respline);
/* All OK. */
return FTPOK;
}
/* Sends RETR command to the FTP server. */
uerr_t
ftp_retr (struct rbuf *rbuf, const char *file)
{
char *request, *respline;
int nwritten;
uerr_t err;
/* Send RETR request. */
request = ftp_request ("RETR", file);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate response. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline == '5')
{
free (respline);
return FTPNSFOD;
}
if (*respline != '1')
{
free (respline);
return FTPRERR;
}
free (respline);
/* All OK. */
return FTPOK;
}
/* Sends the LIST command to the server. If FILE is NULL, send just
`LIST' (no space). */
uerr_t
ftp_list (struct rbuf *rbuf, const char *file)
{
char *request, *respline;
int nwritten;
uerr_t err;
/* Send LIST request. */
request = ftp_request ("LIST", file);
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
if (nwritten < 0)
{
free (request);
return WRITEFAILED;
}
free (request);
/* Get appropriate respone. */
err = ftp_response (rbuf, &respline);
if (err != FTPOK)
{
free (respline);
return err;
}
if (*respline == '5')
{
free (respline);
return FTPNSFOD;
}
if (*respline != '1')
{
free (respline);
return FTPRERR;
}
free (respline);
/* All OK. */
return FTPOK;
}

388
src/ftp-ls.c Normal file
View File

@ -0,0 +1,388 @@
/* Parsing FTP `ls' output.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include "wget.h"
#include "utils.h"
#include "ftp.h"
/* Converts symbolic permissions to number-style ones, e.g. string
rwxr-xr-x to 755. For now, it knows nothing of
setuid/setgid/sticky. ACLs are ignored. */
static int
symperms (const char *s)
{
int perms = 0, i;
if (strlen (s) < 9)
return 0;
for (i = 0; i < 3; i++, s += 3)
{
perms <<= 3;
perms += (((s[0] == 'r') << 2) + ((s[1] == 'w') << 1) +
(s[2] == 'x' || s[2] == 's'));
}
return perms;
}
/* Convert the Un*x-ish style directory listing stored in FILE to a
linked list of fileinfo (system-independent) entries. The contents
of FILE are considered to be produced by the standard Unix `ls -la'
output (whatever that might be). BSD (no group) and SYSV (with
group) listings are handled.
The time stamps are stored in a separate variable, time_t
compatible (I hope). The timezones are ignored. */
static struct fileinfo *
ftp_parse_unix_ls (const char *file)
{
FILE *fp;
static const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
int next, len, i, error, ignore;
int year, month, day; /* for time analysis */
int hour, min, sec;
struct tm timestruct, *tnow;
time_t timenow;
char *line, *tok; /* tokenizer */
struct fileinfo *dir, *l, cur; /* list creation */
fp = fopen (file, "rb");
if (!fp)
{
logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
return NULL;
}
dir = l = NULL;
/* Line loop to end of file: */
while ((line = read_whole_line (fp)))
{
DEBUGP (("%s\n", line));
len = strlen (line);
/* Destroy <CR> if there is one. */
if (len && line[len - 1] == '\r')
line[--len] = '\0';
/* Skip if total... */
if (!strncasecmp (line, "total", 5))
{
free (line);
continue;
}
/* Get the first token (permissions). */
tok = strtok (line, " ");
if (!tok)
{
free (line);
continue;
}
cur.name = NULL;
cur.linkto = NULL;
/* Decide whether we deal with a file or a directory. */
switch (*tok)
{
case '-':
cur.type = FT_PLAINFILE;
DEBUGP (("PLAINFILE; "));
break;
case 'd':
cur.type = FT_DIRECTORY;
DEBUGP (("DIRECTORY; "));
break;
case 'l':
cur.type = FT_SYMLINK;
DEBUGP (("SYMLINK; "));
break;
default:
cur.type = FT_UNKNOWN;
DEBUGP (("UNKOWN; "));
break;
}
cur.perms = symperms (tok + 1);
DEBUGP (("perms %0o; ", cur.perms));
error = ignore = 0; /* Errnoeous and ignoring entries are
treated equally for now. */
year = hour = min = sec = 0; /* Silence the compiler. */
month = day = 0;
next = -1;
/* While there are tokens on the line, parse them. Next is the
number of tokens left until the filename.
Use the month-name token as the "anchor" (the place where the
position wrt the file name is "known"). When a month name is
encountered, `next' is set to 5. Also, the preceding
characters are parsed to get the file size.
This tactic is quite dubious when it comes to
internationalization issues (non-English month names), but it
works for now. */
while ((tok = strtok (NULL, " ")))
{
--next;
if (next < 0) /* a month name was not encountered */
{
for (i = 0; i < 12; i++)
if (!strcmp (tok, months[i]))
break;
/* If we got a month, it means the token before it is the
size, and the filename is three tokens away. */
if (i != 12)
{
char *t = tok - 2;
long mul = 1;
for (cur.size = 0; t > line && ISDIGIT (*t); mul *= 10, t--)
cur.size += mul * (*t - '0');
if (t == line)
{
/* Something is seriously wrong. */
error = 1;
break;
}
month = i;
next = 5;
DEBUGP (("month: %s; ", months[month]));
}
}
else if (next == 4) /* days */
{
if (tok[1]) /* two-digit... */
day = 10 * (*tok - '0') + tok[1] - '0';
else /* ...or one-digit */
day = *tok - '0';
DEBUGP (("day: %d; ", day));
}
else if (next == 3)
{
/* This ought to be either the time, or the year. Let's
be flexible!
If we have a number x, it's a year. If we have x:y,
it's hours and minutes. If we have x:y:z, z are
seconds. */
year = 0;
min = hour = sec = 0;
/* We must deal with digits. */
if (ISDIGIT (*tok))
{
/* Suppose it's year. */
for (; ISDIGIT (*tok); tok++)
year = (*tok - '0') + 10 * year;
if (*tok == ':')
{
/* This means these were hours! */
hour = year;
year = 0;
++tok;
/* Get the minutes... */
for (; ISDIGIT (*tok); tok++)
min = (*tok - '0') + 10 * min;
if (*tok == ':')
{
/* ...and the seconds. */
++tok;
for (; ISDIGIT (*tok); tok++)
sec = (*tok - '0') + 10 * sec;
}
}
}
if (year)
DEBUGP (("year: %d (no tm); ", year));
else
DEBUGP (("time: %02d:%02d:%02d (no yr); ", hour, min, sec));
}
else if (next == 2) /* The file name */
{
int fnlen;
char *p;
/* Since the file name may contain a SPC, it is possible
for strtok to handle it wrong. */
fnlen = strlen (tok);
if (fnlen < len - (tok - line))
{
/* So we have a SPC in the file name. Restore the
original. */
tok[fnlen] = ' ';
/* If the file is a symbolic link, it should have a
` -> ' somewhere. */
if (cur.type == FT_SYMLINK)
{
p = strstr (tok, " -> ");
if (!p)
{
error = 1;
break;
}
cur.linkto = xstrdup (p + 4);
DEBUGP (("link to: %s\n", cur.linkto));
/* And separate it from the file name. */
*p = '\0';
}
}
/* If we have the filename, add it to the list of files or
directories. */
/* "." and ".." are an exception! */
if (!strcmp (tok, ".") || !strcmp (tok, ".."))
{
DEBUGP (("\nIgnoring `.' and `..'; "));
ignore = 1;
break;
}
/* Some FTP sites choose to have ls -F as their default
LIST output, which marks the symlinks with a trailing
`@', directory names with a trailing `/' and
executables with a trailing `*'. This is no problem
unless encountering a symbolic link ending with `@',
or an executable ending with `*' on a server without
default -F output. I believe these cases are very
rare. */
fnlen = strlen (tok); /* re-calculate `fnlen' */
cur.name = (char *)xmalloc (fnlen + 1);
memcpy (cur.name, tok, fnlen + 1);
if (fnlen)
{
if (cur.type == FT_DIRECTORY && cur.name[fnlen - 1] == '/')
{
cur.name[fnlen - 1] = '\0';
DEBUGP (("trailing `/' on dir.\n"));
}
else if (cur.type == FT_SYMLINK && cur.name[fnlen - 1] == '@')
{
cur.name[fnlen - 1] = '\0';
DEBUGP (("trailing `@' on link.\n"));
}
else if (cur.type == FT_PLAINFILE
&& (cur.perms & 0111)
&& cur.name[fnlen - 1] == '*')
{
cur.name[fnlen - 1] = '\0';
DEBUGP (("trailing `*' on exec.\n"));
}
} /* if (fnlen) */
else
error = 1;
break;
}
else
abort ();
} /* while */
if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
error = 1;
DEBUGP (("\n"));
if (error || ignore)
{
DEBUGP (("Skipping.\n"));
FREE_MAYBE (cur.name);
FREE_MAYBE (cur.linkto);
free (line);
continue;
}
if (!dir)
{
l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
memcpy (l, &cur, sizeof (cur));
l->prev = l->next = NULL;
}
else
{
cur.prev = l;
l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
l = l->next;
memcpy (l, &cur, sizeof (cur));
l->next = NULL;
}
/* Get the current time. */
timenow = time (NULL);
tnow = localtime (&timenow);
/* Build the time-stamp (the idea by zaga@fly.cc.fer.hr). */
timestruct.tm_sec = sec;
timestruct.tm_min = min;
timestruct.tm_hour = hour;
timestruct.tm_mday = day;
timestruct.tm_mon = month;
if (year == 0)
{
/* Some listings will not specify the year if it is "obvious"
that the file was from the previous year. E.g. if today
is 97-01-12, and you see a file of Dec 15th, its year is
1996, not 1997. Thanks to Vladimir Volovich for
mentioning this! */
if (month > tnow->tm_mon)
timestruct.tm_year = tnow->tm_year - 1;
else
timestruct.tm_year = tnow->tm_year;
}
else
timestruct.tm_year = year;
if (timestruct.tm_year >= 1900)
timestruct.tm_year -= 1900;
timestruct.tm_wday = 0;
timestruct.tm_yday = 0;
timestruct.tm_isdst = -1;
l->tstamp = mktime (&timestruct); /* store the time-stamp */
free (line);
}
fclose (fp);
return dir;
}
/* This function is just a stub. It should actually accept some kind
of information what system it is running on -- e.g. FPL_UNIX,
FPL_DOS, FPL_NT, FPL_VMS, etc. and a "guess-me" value, like
FPL_GUESS. Then it would call the appropriate parsers to fill up
fileinfos.
Since we currently support only the Unix FTP servers, this function
simply returns the result of ftp_parse_unix_ls(). */
struct fileinfo *
ftp_parse_ls (const char *file)
{
return ftp_parse_unix_ls (file);
}

2179
src/ftp-opie.c Normal file

File diff suppressed because it is too large Load Diff

1476
src/ftp.c Normal file

File diff suppressed because it is too large Load Diff

95
src/ftp.h Normal file
View File

@ -0,0 +1,95 @@
/* Declarations for FTP support.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef FTP_H
#define FTP_H
/* Need it for struct rbuf. */
#include "rbuf.h"
uerr_t ftp_response PARAMS ((struct rbuf *, char **));
uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *));
uerr_t ftp_port PARAMS ((struct rbuf *));
uerr_t ftp_pasv PARAMS ((struct rbuf *, unsigned char *));
uerr_t ftp_type PARAMS ((struct rbuf *, int));
uerr_t ftp_cwd PARAMS ((struct rbuf *, const char *));
uerr_t ftp_retr PARAMS ((struct rbuf *, const char *));
uerr_t ftp_rest PARAMS ((struct rbuf *, long));
uerr_t ftp_list PARAMS ((struct rbuf *, const char *));
struct urlinfo;
/* File types. */
enum ftype
{
FT_PLAINFILE,
FT_DIRECTORY,
FT_SYMLINK,
FT_UNKNOWN
};
/* Globbing (used by ftp_retrieve_glob). */
enum
{
GLOBALL, GETALL, GETONE
};
/* Information about one filename in a linked list. */
struct fileinfo
{
enum ftype type; /* file type */
char *name; /* file name */
long size; /* file size */
long tstamp; /* time-stamp */
int perms; /* file permissions */
char *linkto; /* link to which file points */
struct fileinfo *prev; /* previous... */
struct fileinfo *next; /* ...and next structure. */
};
/* Commands for FTP functions. */
enum command
{
DO_LOGIN = 0x0001, /* Connect and login to the server. */
DO_CWD = 0x0002, /* Change current directory. */
DO_RETR = 0x0004, /* Retrieve the file. */
DO_LIST = 0x0008, /* Retrieve the directory list. */
LEAVE_PENDING = 0x0010 /* Do not close the socket. */
};
enum fstatus
{
NOTHING = 0x0000, /* Nothing done yet. */
ON_YOUR_OWN = 0x0001, /* The ftp_loop_internal sets the
defaults. */
DONE_CWD = 0x0002 /* The current working directory is
correct. */
};
typedef struct
{
int st; /* connection status */
int cmd; /* command code */
struct rbuf rbuf; /* control connection buffer */
long dltime; /* time of the download */
} ccon;
struct fileinfo *ftp_parse_ls PARAMS ((const char *));
uerr_t ftp_loop PARAMS ((struct urlinfo *, int *));
#endif /* FTP_H */

712
src/getopt.c Normal file
View File

@ -0,0 +1,712 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* NOTE!!! AIX requires this to be the first thing in the file.
Do not put ANYTHING before it! */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include "wget.h"
#if !__STDC__ && !defined(const) && IN_GCC
#define const
#endif
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
#include <stdlib.h>
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
/* #define GETOPT_COMPAT */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (const char *str, int chr)
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
static void
my_bcopy (const char *from, char *to, int size)
{
int i;
for (i = 0; i < size; i++)
to[i] = from[i];
}
#endif /* GNU C library. */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (char **argv)
{
int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
char **temp = (char **) alloca (nonopts_size);
/* Interchange the two blocks of data in ARGV. */
my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
(optind - last_nonopt) * sizeof (char *));
my_bcopy ((char *) temp,
(char *) &argv[first_nonopt + optind - last_nonopt],
nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (int argc, char *const *argv, const char *optstring,
const struct option *longopts, int *longind, int long_only)
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound;
indfound = 0; /* To silence the compiler. */
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
exec_name, argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*s)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = s + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
_("%s: option `--%s' doesn't allow an argument\n"),
exec_name, pfound->name);
else
/* +option or -option */
fprintf (stderr,
_("%s: option `%c%s' doesn't allow an argument\n"),
exec_name, argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr,
_("%s: option `%s' requires an argument\n"),
exec_name, argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
exec_name, nextchar);
else
/* +option or -option */
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
exec_name, argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
#if 0
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
exec_name, c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", exec_name, c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, _("%s: illegal option -- %c\n"), exec_name, c);
#endif
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
#if 0
fprintf (stderr, "%s: option `-%c' requires an argument\n",
exec_name, c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, _("%s: option requires an argument -- %c\n"),
exec_name, c);
#endif
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
/* Calls internal getopt function to enable long option names. */
int
getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind)
{
return _getopt_internal (argc, argv, shortopts, longopts, longind, 0);
}
int
getopt (int argc, char *const *argv, const char *optstring)
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

129
src/getopt.h Normal file
View File

@ -0,0 +1,129 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if __STDC__
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* not __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

178
src/headers.c Normal file
View File

@ -0,0 +1,178 @@
/* Generic support for headers.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <ctype.h>
#include "wget.h"
#include "connect.h"
#include "rbuf.h"
#include "headers.h"
/* This file contains the generic routines for work with headers.
Currently they are used only by HTTP in http.c, but they can be
used by anything that cares about RFC822-style headers.
Header is defined in RFC2068, as quoted below. Note that this
definition is not HTTP-specific -- it is virtually
indistinguishable from the one given in RFC822 or RFC1036.
message-header = field-name ":" [ field-value ] CRLF
field-name = token
field-value = *( field-content | LWS )
field-content = <the OCTETs making up the field-value
and consisting of either *TEXT or combinations
of token, tspecials, and quoted-string>
The public functions are header_get() and header_process(), which
see. */
/* Get a header from read-buffer RBUF and return it in *HDR.
As defined in RFC2068 and elsewhere, a header can be folded into
multiple lines if the continuation line begins with a space or
horizontal TAB. Also, this function will accept a header ending
with just LF instead of CRLF.
The header may be of arbitrary length; the function will allocate
as much memory as necessary for it to fit. It need not contain a
`:', thus you can use it to retrieve, say, HTTP status line.
The trailing CRLF or LF are stripped from the header, and it is
zero-terminated. #### Is this well-behaved? */
int
header_get (struct rbuf *rbuf, char **hdr, enum header_get_flags flags)
{
int i;
int bufsize = 80;
*hdr = (char *)xmalloc (bufsize);
for (i = 0; 1; i++)
{
int res;
/* #### Use DO_REALLOC? */
if (i > bufsize - 1)
*hdr = (char *)xrealloc (*hdr, (bufsize <<= 1));
res = RBUF_READCHAR (rbuf, *hdr + i);
if (res == 1)
{
if ((*hdr)[i] == '\n')
{
if (!((flags & HG_NO_CONTINUATIONS)
|| i == 0
|| (i == 1 && (*hdr)[0] == '\r')))
{
char next;
/* If the header is non-empty, we need to check if
it continues on to the other line. We do that by
peeking at the next character. */
res = rbuf_peek (rbuf, &next);
if (res == 0)
return HG_EOF;
else if (res == -1)
return HG_ERROR;
/* If the next character is HT or SP, just continue. */
if (next == '\t' || next == ' ')
continue;
}
/* The header ends. */
(*hdr)[i] = '\0';
/* Get rid of '\r'. */
if (i > 0 && (*hdr)[i - 1] == '\r')
(*hdr)[i - 1] = '\0';
break;
}
}
else if (res == 0)
return HG_EOF;
else
return HG_ERROR;
}
DEBUGP (("%s\n", *hdr));
return HG_OK;
}
/* Check whether HEADER begins with NAME and, if yes, skip the `:' and
the whitespace, and call PROCFUN with the arguments of HEADER's
contents (after the `:' and space) and ARG. Otherwise, return 0. */
int
header_process (const char *header, const char *name,
int (*procfun) (const char *, void *),
void *arg)
{
/* Check whether HEADER matches NAME. */
while (*name && (tolower (*name) == tolower (*header)))
++name, ++header;
if (*name || *header++ != ':')
return 0;
header += skip_lws (header);
return ((*procfun) (header, arg));
}
/* Helper functions for use with header_process(). */
/* Extract a long integer from HEADER and store it to CLOSURE. If an
error is encountered, return 0, else 1. */
int
header_extract_number (const char *header, void *closure)
{
const char *p = header;
long result;
for (result = 0; ISDIGIT (*p); p++)
result = 10 * result + (*p - '0');
if (*p)
return 0;
*(long *)closure = result;
return 1;
}
/* Strdup HEADER, and place the pointer to CLOSURE. */
int
header_strdup (const char *header, void *closure)
{
*(char **)closure = xstrdup (header);
return 1;
}
/* Skip LWS (linear white space), if present. Returns number of
characters to skip. */
int
skip_lws (const char *string)
{
const char *p = string;
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
++p;
return p - string;
}

35
src/headers.h Normal file
View File

@ -0,0 +1,35 @@
/* Declarations for `headers.c'.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
enum {
HG_OK, HG_ERROR, HG_EOF
};
enum header_get_flags { HG_NONE = 0,
HG_NO_CONTINUATIONS = 0x2 };
int header_get PARAMS ((struct rbuf *, char **, enum header_get_flags));
int header_process PARAMS ((const char *, const char *,
int (*) (const char *, void *),
void *));
int header_extract_number PARAMS ((const char *, void *));
int header_strdup PARAMS ((const char *, void *));
int skip_lws PARAMS ((const char *));

560
src/host.c Normal file
View File

@ -0,0 +1,560 @@
/* Dealing with host names.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <assert.h>
#include <sys/types.h>
#ifdef WINDOWS
# include <winsock.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
#endif /* WINDOWS */
#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#include <errno.h>
#include "wget.h"
#include "utils.h"
#include "host.h"
#include "url.h"
#ifndef errno
extern int errno;
#endif
/* Host list entry */
struct host
{
/* Host's symbolical name, as encountered at the time of first
inclusion, e.g. "fly.cc.fer.hr". */
char *hostname;
/* Host's "real" name, i.e. its IP address, written out in ASCII
form of N.N.N.N, e.g. "161.53.70.130". */
char *realname;
/* More than one HOSTNAME can correspond to the same REALNAME. For
our purposes, the canonical name of the host is its HOSTNAME when
it was first encountered. This entry is said to have QUALITY. */
int quality;
/* Next entry in the list. */
struct host *next;
};
static struct host *hlist;
static struct host *add_hlist PARAMS ((struct host *, const char *,
const char *, int));
/* The same as gethostbyname, but supports internet addresses of the
form `N.N.N.N'. */
struct hostent *
ngethostbyname (const char *name)
{
struct hostent *hp;
unsigned long addr;
addr = (unsigned long)inet_addr (name);
if ((int)addr != -1)
hp = gethostbyaddr ((char *)&addr, sizeof (addr), AF_INET);
else
hp = gethostbyname (name);
return hp;
}
/* Search for HOST in the linked list L, by hostname. Return the
entry, if found, or NULL. The search is case-insensitive. */
static struct host *
search_host (struct host *l, const char *host)
{
for (; l; l = l->next)
if (strcasecmp (l->hostname, host) == 0)
return l;
return NULL;
}
/* Like search_host, but searches by address. */
static struct host *
search_address (struct host *l, const char *address)
{
for (; l; l = l->next)
{
int cmp = strcmp (l->realname, address);
if (cmp == 0)
return l;
else if (cmp > 0)
return NULL;
}
return NULL;
}
/* Store the address of HOSTNAME, internet-style, to WHERE. First
check for it in the host list, and (if not found), use
ngethostbyname to get it.
Return 1 on successful finding of the hostname, 0 otherwise. */
int
store_hostaddress (unsigned char *where, const char *hostname)
{
struct host *t;
unsigned long addr;
struct hostent *hptr;
struct in_addr in;
char *inet_s;
/* If the address is of the form d.d.d.d, there will be no trouble
with it. */
addr = (unsigned long)inet_addr (hostname);
if ((int)addr == -1)
{
/* If it is not of that form, try to find it in the cache. */
t = search_host (hlist, hostname);
if (t)
addr = (unsigned long)inet_addr (t->realname);
}
/* If we have the numeric address, just store it. */
if ((int)addr != -1)
{
/* This works on both little and big endian architecture, as
inet_addr returns the address in the proper order. It
appears to work on 64-bit machines too. */
memcpy (where, &addr, 4);
return 1;
}
/* Since all else has failed, let's try gethostbyname(). Note that
we use gethostbyname() rather than ngethostbyname(), because we
*know* the address is not numerical. */
hptr = gethostbyname (hostname);
if (!hptr)
return 0;
/* Copy the address of the host to socket description. */
memcpy (where, hptr->h_addr_list[0], hptr->h_length);
/* Now that we're here, we could as well cache the hostname for
future use, as in realhost(). First, we have to look for it by
address to know if it's already in the cache by another name. */
/* Originally, we copied to in.s_addr, but it appears to be missing
on some systems. */
memcpy (&in, *hptr->h_addr_list, sizeof (in));
STRDUP_ALLOCA (inet_s, inet_ntoa (in));
t = search_address (hlist, inet_s);
if (t) /* Found in the list, as realname. */
{
/* Set the default, 0 quality. */
hlist = add_hlist (hlist, hostname, inet_s, 0);
return 1;
}
/* Since this is really the first time this host is encountered,
set quality to 1. */
hlist = add_hlist (hlist, hostname, inet_s, 1);
return 1;
}
/* Add a host to the host list. The list is sorted by addresses. For
equal addresses, the entries with quality should bubble towards the
beginning of the list. */
static struct host *
add_hlist (struct host *l, const char *nhost, const char *nreal, int quality)
{
struct host *t, *old, *beg;
/* The entry goes to the beginning of the list if the list is empty
or the order requires it. */
if (!l || (strcmp (nreal, l->realname) < 0))
{
t = (struct host *)xmalloc (sizeof (struct host));
t->hostname = xstrdup (nhost);
t->realname = xstrdup (nreal);
t->quality = quality;
t->next = l;
return t;
}
beg = l;
/* Second two one-before-the-last element. */
while (l->next)
{
int cmp;
old = l;
l = l->next;
cmp = strcmp (nreal, l->realname);
if (cmp >= 0)
continue;
/* If the next list element is greater than s, put s between the
current and the next list element. */
t = (struct host *)xmalloc (sizeof (struct host));
old->next = t;
t->next = l;
t->hostname = xstrdup (nhost);
t->realname = xstrdup (nreal);
t->quality = quality;
return beg;
}
t = (struct host *)xmalloc (sizeof (struct host));
t->hostname = xstrdup (nhost);
t->realname = xstrdup (nreal);
t->quality = quality;
/* Insert the new element after the last element. */
l->next = t;
t->next = NULL;
return beg;
}
/* Determine the "real" name of HOST, as perceived by Wget. If HOST
is referenced by more than one name, "real" name is considered to
be the first one encountered in the past.
If the host cannot be found in the list of already dealt-with
hosts, try with its INET address. If this fails too, add it to the
list. The routine does not call gethostbyname twice for the same
host if it can possibly avoid it. */
char *
realhost (const char *host)
{
struct host *l;
struct in_addr in;
struct hostent *hptr;
char *inet_s;
DEBUGP (("Checking for %s.\n", host));
/* Look for the host, looking by the host name. */
l = search_host (hlist, host);
if (l && l->quality) /* Found it with quality */
{
DEBUGP (("%s was already used, by that name.\n", host));
/* Here we return l->hostname, not host, because of the possible
case differences (e.g. jaGOR.srce.hr and jagor.srce.hr are
the same, but we want the one that was first. */
return xstrdup (l->hostname);
}
else if (!l) /* Not found, with or without quality */
{
/* The fact that gethostbyname will get called makes it
necessary to store it to the list, to ensure that
gethostbyname will not be called twice for the same string.
However, the quality argument must be set appropriately.
Note that add_hlist must be called *after* the realname
search, or the quality would be always set to 0 */
DEBUGP (("This is the first time I hear about host %s by that name.\n",
host));
hptr = ngethostbyname (host);
if (!hptr)
return xstrdup (host);
/* Originally, we copied to in.s_addr, but it appears to be
missing on some systems. */
memcpy (&in, *hptr->h_addr_list, sizeof (in));
STRDUP_ALLOCA (inet_s, inet_ntoa (in));
}
else /* Found, without quality */
{
/* This case happens when host is on the list,
but not as first entry (the one with quality).
Then we just get its INET address and pick
up the first entry with quality. */
DEBUGP (("We've dealt with host %s, but under the name %s.\n",
host, l->realname));
STRDUP_ALLOCA (inet_s, l->realname);
}
/* Now we certainly have the INET address. The following loop is
guaranteed to pick either an entry with quality (because it is
the first one), or none at all. */
l = search_address (hlist, inet_s);
if (l) /* Found in the list, as realname. */
{
/* Set the default, 0 quality. */
hlist = add_hlist (hlist, host, inet_s, 0);
return xstrdup (l->hostname);
}
/* Since this is really the first time this host is encountered,
set quality to 1. */
hlist = add_hlist (hlist, host, inet_s, 1);
return xstrdup (host);
}
/* Compare two hostnames (out of URL-s if the arguments are URL-s),
taking care of aliases. It uses realhost() to determine a unique
hostname for each of two hosts. If simple_check is non-zero, only
strcmp() is used for comparison. */
int
same_host (const char *u1, const char *u2)
{
const char *s;
char *p1, *p2;
char *real1, *real2;
/* Skip protocol, if present. */
u1 += skip_url (u1);
u2 += skip_url (u2);
u1 += skip_proto (u1);
u2 += skip_proto (u2);
/* Skip username ans password, if present. */
u1 += skip_uname (u1);
u2 += skip_uname (u2);
for (s = u1; *u1 && *u1 != '/' && *u1 != ':'; u1++);
p1 = strdupdelim (s, u1);
for (s = u2; *u2 && *u2 != '/' && *u2 != ':'; u2++);
p2 = strdupdelim (s, u2);
DEBUGP (("Comparing hosts %s and %s...\n", p1, p2));
if (strcasecmp (p1, p2) == 0)
{
free (p1);
free (p2);
DEBUGP (("They are quite alike.\n"));
return 1;
}
else if (opt.simple_check)
{
free (p1);
free (p2);
DEBUGP (("Since checking is simple, I'd say they are not the same.\n"));
return 0;
}
real1 = realhost (p1);
real2 = realhost (p2);
free (p1);
free (p2);
if (strcasecmp (real1, real2) == 0)
{
DEBUGP (("They are alike, after realhost()->%s.\n", real1));
free (real1);
free (real2);
return 1;
}
else
{
DEBUGP (("They are not the same (%s, %s).\n", real1, real2));
free (real1);
free (real2);
return 0;
}
}
/* Determine whether a URL is acceptable to be followed, according to
a list of domains to accept. */
int
accept_domain (struct urlinfo *u)
{
assert (u->host != NULL);
if (opt.domains)
{
if (!sufmatch ((const char **)opt.domains, u->host))
return 0;
}
if (opt.exclude_domains)
{
if (sufmatch ((const char **)opt.exclude_domains, u->host))
return 0;
}
return 1;
}
/* Check whether WHAT is matched in LIST, each element of LIST being a
pattern to match WHAT against, using backward matching (see
match_backwards() in utils.c).
If an element of LIST matched, 1 is returned, 0 otherwise. */
int
sufmatch (const char **list, const char *what)
{
int i, j, k, lw;
lw = strlen (what);
for (i = 0; list[i]; i++)
{
for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
if (tolower (list[i][j]) != tolower (what[k]))
break;
/* The domain must be first to reach to beginning. */
if (j == -1)
return 1;
}
return 0;
}
/* Return email address of the form username@FQDN suitable for
anonymous FTP passwords. This process is error-prone, and the
escape hatch is the MY_HOST preprocessor constant, which can be
used to hard-code either your hostname or FQDN at compile-time.
If the FQDN cannot be determined, a warning is printed, and the
function returns a short `username@' form, accepted by most
anonymous servers.
If not even the username cannot be divined, it means things are
seriously fucked up, and Wget exits. */
char *
ftp_getaddress (void)
{
static char *address;
/* Do the drill only the first time, as it won't change. */
if (!address)
{
char userid[32]; /* 9 should be enough for Unix, but
I'd rather be on the safe side. */
char *host, *fqdn;
if (!pwd_cuserid (userid))
{
logprintf (LOG_ALWAYS, _("%s: Cannot determine user-id.\n"),
exec_name);
exit (1);
}
#ifdef MY_HOST
STRDUP_ALLOCA (host, MY_HOST);
#else /* not MY_HOST */
#ifdef HAVE_UNAME
{
struct utsname ubuf;
if (uname (&ubuf) < 0)
{
logprintf (LOG_ALWAYS, _("%s: Warning: uname failed: %s\n"),
exec_name, strerror (errno));
fqdn = "";
goto giveup;
}
STRDUP_ALLOCA (host, ubuf.nodename);
}
#else /* not HAVE_UNAME */
#ifdef HAVE_GETHOSTNAME
host = alloca (256);
if (gethostname (host, 256) < 0)
{
logprintf (LOG_ALWAYS, _("%s: Warning: gethostname failed\n"),
exec_name);
fqdn = "";
goto giveup;
}
#else /* not HAVE_GETHOSTNAME */
#error Cannot determine host name.
#endif /* not HAVE_GETHOSTNAME */
#endif /* not HAVE_UNAME */
#endif /* not MY_HOST */
/* If the address we got so far contains a period, don't bother
anymore. */
if (strchr (host, '.'))
fqdn = host;
else
{
/* #### I've seen the following scheme fail on at least one
system! Do we care? */
char *tmpstore;
/* According to Richard Stevens, the correct way to find the
FQDN is to (1) find the host name, (2) find its IP
address using gethostbyname(), and (3) get the FQDN using
gethostbyaddr(). So that's what we'll do. Step one has
been done above. */
/* (2) */
struct hostent *hp = gethostbyname (host);
if (!hp || !hp->h_addr_list)
{
logprintf (LOG_ALWAYS, _("\
%s: Warning: cannot determine local IP address.\n"),
exec_name);
fqdn = "";
goto giveup;
}
/* Copy the argument, so the call to gethostbyaddr doesn't
clobber it -- just in case. */
tmpstore = (char *)alloca (hp->h_length);
memcpy (tmpstore, *hp->h_addr_list, hp->h_length);
/* (3) */
hp = gethostbyaddr (tmpstore, hp->h_length, hp->h_addrtype);
if (!hp || !hp->h_name)
{
logprintf (LOG_ALWAYS, _("\
%s: Warning: cannot reverse-lookup local IP address.\n"),
exec_name);
fqdn = "";
goto giveup;
}
if (!strchr (hp->h_name, '.'))
{
#if 0
/* This gets ticked pretty often. Karl Berry reports
that there can be valid reasons for the local host
name not to be an FQDN, so I've decided to remove the
annoying warning. */
logprintf (LOG_ALWAYS, _("\
%s: Warning: reverse-lookup of local address did not yield FQDN!\n"),
exec_name);
#endif
fqdn = "";
goto giveup;
}
/* Once we're here, hp->h_name contains the correct FQDN. */
STRDUP_ALLOCA (fqdn, hp->h_name);
}
giveup:
address = (char *)xmalloc (strlen (userid) + 1 + strlen (fqdn) + 1);
sprintf (address, "%s@%s", userid, fqdn);
}
return address;
}
/* Print error messages for host errors. */
char *
herrmsg (int error)
{
/* Can't use switch since some constants are equal (at least on my
system), and the compiler signals "duplicate case value". */
if (error == HOST_NOT_FOUND
|| error == NO_RECOVERY
|| error == NO_DATA
|| error == NO_ADDRESS
|| error == TRY_AGAIN)
return _("Host not found");
else
return _("Unknown error");
}
/* Clean the host list. This is a separate function, so we needn't
export HLIST and its implementation. Ha! */
void
clean_hosts (void)
{
struct host *l = hlist;
while (l)
{
struct host *p = l->next;
free (l->hostname);
free (l->realname);
free (l);
l = p;
}
hlist = NULL;
}

41
src/host.h Normal file
View File

@ -0,0 +1,41 @@
/* Declarations for host.c
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef HOST_H
#define HOST_H
struct urlinfo;
/* Function declarations */
struct hostent *ngethostbyname PARAMS ((const char *));
int store_hostaddress PARAMS ((unsigned char *, const char *));
void clean_hosts PARAMS ((void));
char *realhost PARAMS ((const char *));
int same_host PARAMS ((const char *, const char *));
int accept_domain PARAMS ((struct urlinfo *));
int sufmatch PARAMS ((const char **, const char *));
char *ftp_getaddress PARAMS ((void));
char *herrmsg PARAMS ((int));
#endif /* HOST_H */

508
src/html.c Normal file
View File

@ -0,0 +1,508 @@
/* A simple HTML parser.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <ctype.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include "wget.h"
#include "url.h"
#include "utils.h"
#include "ftp.h"
#include "html.h"
#ifndef errno
extern int errno;
#endif
static state_t global_state;
struct tag_attr {
char *tag;
char *attr;
};
/* Match a string against a null-terminated list of identifiers. */
static int
idmatch (struct tag_attr *tags, const char *tag, const char *attr)
{
int i;
if (!tag || !attr)
return 0;
for (i = 0; tags[i].tag; i++)
if (!strcasecmp (tags[i].tag, tag) && !strcasecmp (tags[i].attr, attr))
return 1;
return 0;
}
/* Parse BUF (a buffer of BUFSIZE characters) searching for HTML tags
describing URLs to follow. When a tag is encountered, extract its
components (as described by html_allow[] array), and return the
address and the length of the string. Return NULL if no URL is
found. */
const char *
htmlfindurl (const char *buf, int bufsize, int *size, int init)
{
const char *p, *ph;
state_t *s;
/* NULL-terminated list of tags and modifiers someone would want to
follow -- feel free to edit to suit your needs: */
static struct tag_attr html_allow[] = {
{ "a", "href" },
{ "img", "src" },
{ "img", "href" },
{ "body", "background" },
{ "frame", "src" },
{ "iframe", "src" },
{ "fig", "src" },
{ "overlay", "src" },
{ "applet", "code" },
{ "script", "src" },
{ "embed", "src" },
{ "bgsound", "src" },
{ "area", "href" },
{ "img", "lowsrc" },
{ "input", "src" },
{ "layer", "src" },
{ "table", "background"},
{ "th", "background"},
{ "td", "background"},
/* Tags below this line are treated specially. */
{ "base", "href" },
{ "meta", "content" },
{ NULL, NULL }
};
s = &global_state;
if (init)
{
DEBUGP (("Resetting a parser state.\n"));
memset (s, 0, sizeof (*s));
}
while (1)
{
if (!bufsize)
break;
/* Let's look for a tag, if we are not already in one. */
if (!s->at_value)
{
/* Find '<'. */
if (*buf != '<')
for (; bufsize && *buf != '<'; ++buf, --bufsize);
if (!bufsize)
break;
/* Skip spaces. */
for (++buf, --bufsize; bufsize && ISSPACE (*buf) && *buf != '>';
++buf, --bufsize);
if (!bufsize)
break;
p = buf;
/* Find the tag end. */
for (; bufsize && !ISSPACE (*buf) && *buf != '>' && *buf != '=';
++buf, --bufsize);
if (!bufsize)
break;
if (*buf == '=')
{
/* <tag=something> is illegal. Just skip it. */
++buf, --bufsize;
continue;
}
if (p == buf)
{
/* *buf == '>'. */
++buf, --bufsize;
continue;
}
s->tag = strdupdelim (p, buf);
if (*buf == '>')
{
free (s->tag);
s->tag = NULL;
++buf, --bufsize;
continue;
}
}
else /* s->at_value */
{
/* Reset AT_VALUE. */
s->at_value = 0;
/* If in quotes, just skip out of them and continue living. */
if (s->in_quote)
{
s->in_quote = 0;
for (; bufsize && *buf != s->quote_char; ++buf, --bufsize);
if (!bufsize)
break;
++buf, --bufsize;
}
if (!bufsize)
break;
if (*buf == '>')
{
FREE_MAYBE (s->tag);
FREE_MAYBE (s->attr);
s->tag = s->attr = NULL;
continue;
}
}
/* Find the attributes. */
do
{
FREE_MAYBE (s->attr);
s->attr = NULL;
if (!bufsize)
break;
/* Skip the spaces if we have them. We don't have them at
places like <img alt="something"src="something-else">.
^ no spaces here */
if (ISSPACE (*buf))
for (++buf, --bufsize; bufsize && ISSPACE (*buf) && *buf != '>';
++buf, --bufsize);
if (!bufsize || *buf == '>')
break;
if (*buf == '=')
{
/* This is the case of <tag = something>, which is
illegal. Just skip it. */
++buf, --bufsize;
continue;
}
p = buf;
/* Find the attribute end. */
for (; bufsize && !ISSPACE (*buf) && *buf != '>' && *buf != '=';
++buf, --bufsize);
if (!bufsize || *buf == '>')
break;
/* Construct the attribute. */
s->attr = strdupdelim (p, buf);
/* Now we must skip the spaces to find '='. */
if (*buf != '=')
{
for (; bufsize && ISSPACE (*buf) && *buf != '>'; ++buf, --bufsize);
if (!bufsize || *buf == '>')
break;
}
/* If we still don't have '=', something is amiss. */
if (*buf != '=')
continue;
/* Find the beginning of attribute value by skipping the
spaces. */
++buf, --bufsize;
for (; bufsize && ISSPACE (*buf) && *buf != '>'; ++buf, --bufsize);
if (!bufsize || *buf == '>')
break;
ph = NULL;
/* The value of an attribute can, but does not have to be
quoted. */
if (*buf == '\"' || *buf == '\'')
{
s->in_quote = 1;
s->quote_char = *buf;
p = buf + 1;
for (++buf, --bufsize;
bufsize && *buf != s->quote_char && *buf != '\n';
++buf, --bufsize)
if (*buf == '#')
ph = buf;
if (!bufsize)
{
s->in_quote = 0;
break;
}
if (*buf == '\n')
{
/* #### Is the following logic good?
Obviously no longer in quote. It might be well
to check whether '>' was encountered, but that
would be encouraging writers of invalid HTMLs,
and we don't want that, now do we? */
s->in_quote = 0;
continue;
}
}
else
{
p = buf;
for (; bufsize && !ISSPACE (*buf) && *buf != '>'; ++buf, --bufsize)
if (*buf == '#')
ph = buf;
if (!bufsize)
break;
}
/* If '#' was found unprotected in a URI, it is probably an
HTML marker, or color spec. */
*size = (ph ? ph : buf) - p;
/* The URI is liable to be returned if:
1) *size != 0;
2) its tag and attribute are found in html_allow. */
if (*size && idmatch (html_allow, s->tag, s->attr))
{
if (!strcasecmp (s->tag, "base") && !strcasecmp (s->attr, "href"))
{
FREE_MAYBE (s->base);
s->base = strdupdelim (p, buf);
}
else if (!strcasecmp (s->tag, "meta") && !strcasecmp (s->attr, "content"))
{
/* Some pages use a META tag to specify that the page
be refreshed by a new page after a given number of
seconds. We need to attempt to extract an URL for
the new page from the other garbage present. The
general format for this is:
<META HTTP-EQUIV=Refresh CONTENT="0; URL=index2.html">
So we just need to skip past the "0; URL="
garbage to get to the URL. META tags are also
used for specifying random things like the page
author's name and what editor was used to create
it. So we need to be careful to ignore them and
not assume that an URL will be present at all. */
for (; *size && ISDIGIT (*p); p++, *size -= 1);
if (*p == ';')
{
for (p++, *size -= 1; *size && ISSPACE (*p); p++, *size -= 1) ;
if (!strncasecmp (p, "URL=", 4))
{
p += 4, *size -= 4;
s->at_value = 1;
return p;
}
}
}
else
{
s->at_value = 1;
return p;
}
}
/* Exit from quote. */
if (*buf == s->quote_char)
{
s->in_quote = 0;
++buf, --bufsize;
}
} while (*buf != '>');
FREE_MAYBE (s->tag);
FREE_MAYBE (s->attr);
s->tag = s->attr = NULL;
if (!bufsize)
break;
}
FREE_MAYBE (s->tag);
FREE_MAYBE (s->attr);
FREE_MAYBE (s->base);
memset (s, 0, sizeof (*s)); /* just to be sure */
DEBUGP (("HTML parser ends here (state destroyed).\n"));
return NULL;
}
/* The function returns the base reference of HTML buffer id, or NULL
if one wasn't defined for that buffer. */
const char *
html_base (void)
{
return global_state.base;
}
/* The function returns the pointer to the malloc-ed quoted version of
string s. It will recognize and quote numeric and special graphic
entities, as per RFC1866:
`&' -> `&amp;'
`<' -> `&lt;'
`>' -> `&gt;'
`"' -> `&quot;'
No other entities are recognized or replaced. */
static char *
html_quote_string (const char *s)
{
const char *b = s;
char *p, *res;
int i;
/* Pass through the string, and count the new size. */
for (i = 0; *s; s++, i++)
{
if (*s == '&')
i += 4; /* `amp;' */
else if (*s == '<' || *s == '>')
i += 3; /* `lt;' and `gt;' */
else if (*s == '\"')
i += 5; /* `quot;' */
}
res = (char *)xmalloc (i + 1);
s = b;
for (p = res; *s; s++)
{
switch (*s)
{
case '&':
*p++ = '&';
*p++ = 'a';
*p++ = 'm';
*p++ = 'p';
*p++ = ';';
break;
case '<': case '>':
*p++ = '&';
*p++ = (*s == '<' ? 'l' : 'g');
*p++ = 't';
*p++ = ';';
break;
case '\"':
*p++ = '&';
*p++ = 'q';
*p++ = 'u';
*p++ = 'o';
*p++ = 't';
*p++ = ';';
break;
default:
*p++ = *s;
}
}
*p = '\0';
return res;
}
/* The function creates an HTML index containing references to given
directories and files on the appropriate host. The references are
FTP. */
uerr_t
ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
{
FILE *fp;
char *upwd;
char *htclfile; /* HTML-clean file name */
if (!opt.dfp)
{
fp = fopen (file, "wb");
if (!fp)
{
logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
return FOPENERR;
}
}
else
fp = opt.dfp;
if (u->user)
{
char *tmpu, *tmpp; /* temporary, clean user and passwd */
tmpu = CLEANDUP (u->user);
tmpp = u->passwd ? CLEANDUP (u->passwd) : NULL;
upwd = (char *)xmalloc (strlen (tmpu)
+ (tmpp ? (1 + strlen (tmpp)) : 0) + 2);
sprintf (upwd, "%s%s%s@", tmpu, tmpp ? ":" : "", tmpp ? tmpp : "");
free (tmpu);
FREE_MAYBE (tmpp);
}
else
upwd = xstrdup ("");
fprintf (fp, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
fprintf (fp, "<html>\n<head>\n<title>");
fprintf (fp, _("Index of /%s on %s:%d"), u->dir, u->host, u->port);
fprintf (fp, "</title>\n</head>\n<body>\n<h1>");
fprintf (fp, _("Index of /%s on %s:%d"), u->dir, u->host, u->port);
fprintf (fp, "</h1>\n<hr>\n<pre>\n");
while (f)
{
fprintf (fp, " ");
if (f->tstamp != -1)
{
/* #### Should we translate the months? */
static char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
struct tm *ptm = localtime ((time_t *)&f->tstamp);
fprintf (fp, "%d %s %02d ", ptm->tm_year + 1900, months[ptm->tm_mon],
ptm->tm_mday);
if (ptm->tm_hour)
fprintf (fp, "%02d:%02d ", ptm->tm_hour, ptm->tm_min);
else
fprintf (fp, " ");
}
else
fprintf (fp, _("time unknown "));
switch (f->type)
{
case FT_PLAINFILE:
fprintf (fp, _("File "));
break;
case FT_DIRECTORY:
fprintf (fp, _("Directory "));
break;
case FT_SYMLINK:
fprintf (fp, _("Link "));
break;
default:
fprintf (fp, _("Not sure "));
break;
}
htclfile = html_quote_string (f->name);
fprintf (fp, "<a href=\"ftp://%s%s:%hu", upwd, u->host, u->port);
if (*u->dir != '/')
putc ('/', fp);
fprintf (fp, "%s", u->dir);
if (*u->dir)
putc ('/', fp);
fprintf (fp, "%s", htclfile);
if (f->type == FT_DIRECTORY)
putc ('/', fp);
fprintf (fp, "\">%s", htclfile);
if (f->type == FT_DIRECTORY)
putc ('/', fp);
fprintf (fp, "</a> ");
if (f->type == FT_PLAINFILE)
fprintf (fp, _(" (%s bytes)"), legible (f->size));
else if (f->type == FT_SYMLINK)
fprintf (fp, "-> %s", f->linkto ? f->linkto : "(nil)");
putc ('\n', fp);
free (htclfile);
f = f->next;
}
fprintf (fp, "</pre>\n</body>\n</html>\n");
free (upwd);
if (!opt.dfp)
fclose (fp);
else
fflush (fp);
return FTPOK;
}

39
src/html.h Normal file
View File

@ -0,0 +1,39 @@
/* HTML parser declarations.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef HTML_H
#define HTML_H
/* Structure of a parser state */
typedef struct
{
int at_value, in_quote;
char quote_char;
char *tag, *attr;
char *base;
} state_t;
struct fileinfo;
/* Function declarations */
const char *htmlfindurl PARAMS ((const char *, int, int *, int));
const char *html_base PARAMS ((void));
uerr_t ftp_index PARAMS ((const char *, struct urlinfo *, struct fileinfo *));
#endif /* HTML_H */

1589
src/http.c Normal file

File diff suppressed because it is too large Load Diff

928
src/init.c Normal file
View File

@ -0,0 +1,928 @@
/* Reading/parsing the initialization file.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <errno.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include "wget.h"
#include "utils.h"
#include "init.h"
#include "host.h"
#include "recur.h"
#include "netrc.h"
#ifndef errno
extern int errno;
#endif
#define CMD_DECLARE(func) static int func \
PARAMS ((const char *, const char *, void *))
CMD_DECLARE (cmd_boolean);
CMD_DECLARE (cmd_boolean);
CMD_DECLARE (cmd_number);
CMD_DECLARE (cmd_number_inf);
CMD_DECLARE (cmd_string);
CMD_DECLARE (cmd_vector);
CMD_DECLARE (cmd_directory_vector);
CMD_DECLARE (cmd_bytes);
CMD_DECLARE (cmd_time);
CMD_DECLARE (cmd_spec_dirstruct);
CMD_DECLARE (cmd_spec_dotstyle);
CMD_DECLARE (cmd_spec_header);
CMD_DECLARE (cmd_spec_htmlify);
CMD_DECLARE (cmd_spec_mirror);
CMD_DECLARE (cmd_spec_outputdocument);
CMD_DECLARE (cmd_spec_recursive);
CMD_DECLARE (cmd_spec_useragent);
/* List of recognized commands, each consisting of name, closure and
function. When adding a new command, simply add it to the list,
but be sure to keep the list sorted alphabetically, as comind()
depends on it. */
static struct {
char *name;
void *closure;
int (*action) PARAMS ((const char *, const char *, void *));
} commands[] = {
{ "accept", &opt.accepts, cmd_vector },
{ "addhostdir", &opt.add_hostdir, cmd_boolean },
{ "alwaysrest", &opt.always_rest, cmd_boolean }, /* deprecated */
{ "background", &opt.background, cmd_boolean },
{ "backups", &opt.backups, cmd_number },
{ "base", &opt.base_href, cmd_string },
{ "cache", &opt.proxy_cache, cmd_boolean },
{ "continue", &opt.always_rest, cmd_boolean },
{ "convertlinks", &opt.convert_links, cmd_boolean },
{ "cutdirs", &opt.cut_dirs, cmd_number },
#ifdef DEBUG
{ "debug", &opt.debug, cmd_boolean },
#endif
{ "deleteafter", &opt.delete_after, cmd_boolean },
{ "dirprefix", &opt.dir_prefix, cmd_string },
{ "dirstruct", NULL, cmd_spec_dirstruct },
{ "domains", &opt.domains, cmd_vector },
{ "dotbytes", &opt.dot_bytes, cmd_bytes },
{ "dotsinline", &opt.dots_in_line, cmd_number },
{ "dotspacing", &opt.dot_spacing, cmd_number },
{ "dotstyle", NULL, cmd_spec_dotstyle },
{ "excludedirectories", &opt.excludes, cmd_directory_vector },
{ "excludedomains", &opt.exclude_domains, cmd_vector },
{ "followftp", &opt.follow_ftp, cmd_boolean },
{ "forcehtml", &opt.force_html, cmd_boolean },
{ "ftpproxy", &opt.ftp_proxy, cmd_string },
{ "glob", &opt.ftp_glob, cmd_boolean },
{ "header", NULL, cmd_spec_header },
{ "htmlify", NULL, cmd_spec_htmlify },
{ "httppasswd", &opt.http_passwd, cmd_string },
{ "httpproxy", &opt.http_proxy, cmd_string },
{ "httpuser", &opt.http_user, cmd_string },
{ "ignorelength", &opt.ignore_length, cmd_boolean },
{ "includedirectories", &opt.includes, cmd_directory_vector },
{ "input", &opt.input_filename, cmd_string },
{ "killlonger", &opt.kill_longer, cmd_boolean },
{ "logfile", &opt.lfilename, cmd_string },
{ "login", &opt.ftp_acc, cmd_string },
{ "mirror", NULL, cmd_spec_mirror },
{ "netrc", &opt.netrc, cmd_boolean },
{ "noclobber", &opt.noclobber, cmd_boolean },
{ "noparent", &opt.no_parent, cmd_boolean },
{ "noproxy", &opt.no_proxy, cmd_vector },
{ "numtries", &opt.ntry, cmd_number_inf }, /* deprecated */
{ "outputdocument", NULL, cmd_spec_outputdocument },
{ "passiveftp", &opt.ftp_pasv, cmd_boolean },
{ "passwd", &opt.ftp_pass, cmd_string },
{ "proxypasswd", &opt.proxy_passwd, cmd_string },
{ "proxyuser", &opt.proxy_user, cmd_string },
{ "quiet", &opt.quiet, cmd_boolean },
{ "quota", &opt.quota, cmd_bytes },
{ "reclevel", &opt.reclevel, cmd_number_inf },
{ "recursive", NULL, cmd_spec_recursive },
{ "reject", &opt.rejects, cmd_vector },
{ "relativeonly", &opt.relative_only, cmd_boolean },
{ "removelisting", &opt.remove_listing, cmd_boolean },
{ "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
{ "robots", &opt.use_robots, cmd_boolean },
{ "saveheaders", &opt.save_headers, cmd_boolean },
{ "serverresponse", &opt.server_response, cmd_boolean },
{ "simplehostcheck", &opt.simple_check, cmd_boolean },
{ "spanhosts", &opt.spanhost, cmd_boolean },
{ "spider", &opt.spider, cmd_boolean },
{ "timeout", &opt.timeout, cmd_time },
{ "timestamping", &opt.timestamping, cmd_boolean },
{ "tries", &opt.ntry, cmd_number_inf },
{ "useproxy", &opt.use_proxy, cmd_boolean },
{ "useragent", NULL, cmd_spec_useragent },
{ "verbose", &opt.verbose, cmd_boolean },
{ "wait", &opt.wait, cmd_time }
};
/* Return index of COM if it is a valid command, or -1 otherwise. COM
is looked up in `commands' using binary search algorithm. */
static int
comind (const char *com)
{
int min = 0, max = ARRAY_SIZE (commands);
do
{
int i = (min + max) / 2;
int cmp = strcasecmp (com, commands[i].name);
if (cmp == 0)
return i;
else if (cmp < 0)
max = i - 1;
else
min = i + 1;
}
while (min <= max);
return -1;
}
/* Reset the variables to default values. */
static void
defaults (void)
{
char *tmp;
/* Most of the default values are 0. Just reset everything, and
fill in the non-zero values. Note that initializing pointers to
NULL this way is technically illegal, but porting Wget to a
machine where NULL is not all-zero bit pattern will be the least
of the implementors' worries. */
memset (&opt, 0, sizeof (opt));
opt.verbose = -1;
opt.dir_prefix = xstrdup (".");
opt.ntry = 20;
opt.reclevel = 5;
opt.add_hostdir = 1;
opt.ftp_acc = xstrdup ("anonymous");
/*opt.ftp_pass = xstrdup (ftp_getaddress ());*/
opt.netrc = 1;
opt.ftp_glob = 1;
opt.htmlify = 1;
opt.use_proxy = 1;
tmp = getenv ("no_proxy");
if (tmp)
opt.no_proxy = sepstring (tmp);
opt.proxy_cache = 1;
#ifdef HAVE_SELECT
opt.timeout = 900;
#endif
opt.use_robots = 1;
opt.remove_listing = 1;
opt.dot_bytes = 1024;
opt.dot_spacing = 10;
opt.dots_in_line = 50;
}
/* Return the user's home directory (strdup-ed), or NULL if none is
found. */
char *
home_dir (void)
{
char *home = getenv ("HOME");
if (!home)
{
#ifndef WINDOWS
/* If HOME is not defined, try getting it from the password
file. */
struct passwd *pwd = getpwuid (getuid ());
if (!pwd || !pwd->pw_dir)
return NULL;
home = pwd->pw_dir;
#else /* WINDOWS */
home = "C:\\";
/* #### Maybe I should grab home_dir from registry, but the best
that I could get from there is user's Start menu. It sucks! */
#endif /* WINDOWS */
}
return home ? xstrdup (home) : NULL;
}
/* Return the path to the user's .wgetrc. This is either the value of
`WGETRC' environment variable, or `$HOME/.wgetrc'.
If the `WGETRC' variable exists but the file does not exist, the
function will exit(). */
static char *
wgetrc_file_name (void)
{
char *env, *home;
char *file = NULL;
/* Try the environment. */
env = getenv ("WGETRC");
if (env && *env)
{
if (!file_exists_p (env))
{
fprintf (stderr, "%s: %s: %s.\n", exec_name, file, strerror (errno));
exit (1);
}
return xstrdup (env);
}
#ifndef WINDOWS
/* If that failed, try $HOME/.wgetrc. */
home = home_dir ();
if (home)
{
file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
sprintf (file, "%s/.wgetrc", home);
}
#else /* WINDOWS */
/* Under Windows, "home" is (for the purposes of this function) the
directory where `wget.exe' resides, and `wget.ini' will be used
as file name. SYSTEM_WGETRC should not be defined under WINDOWS.
It is not as trivial as I assumed, because on 95 argv[0] is full
path, but on NT you get what you typed in command line. --dbudor */
home = ws_mypath ();
if (home)
{
file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
sprintf (file, "%swget.ini", home);
}
#endif /* WINDOWS */
FREE_MAYBE (home);
if (!file)
return NULL;
if (!file_exists_p (file))
{
free (file);
return NULL;
}
return file;
}
/* Initialize variables from a wgetrc file */
static void
run_wgetrc (const char *file)
{
FILE *fp;
char *line;
int ln;
fp = fopen (file, "rb");
if (!fp)
{
fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
file, strerror (errno));
return;
}
/* Reset line number. */
ln = 1;
while ((line = read_whole_line (fp)))
{
char *com, *val;
int status;
int length = strlen (line);
if (length && line[length - 1] == '\r')
line[length - 1] = '\0';
/* Parse the line. */
status = parse_line (line, &com, &val);
free (line);
/* If everything is OK, set the value. */
if (status == 1)
{
if (!setval (com, val))
fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
file, ln);
free (com);
free (val);
}
else if (status == 0)
fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
file, ln);
++ln;
}
fclose (fp);
}
/* Initialize the defaults and run the system wgetrc and user's own
wgetrc. */
void
initialize (void)
{
char *file;
/* Load the hard-coded defaults. */
defaults ();
/* If SYSTEM_WGETRC is defined, use it. */
#ifdef SYSTEM_WGETRC
if (file_exists_p (SYSTEM_WGETRC))
run_wgetrc (SYSTEM_WGETRC);
#endif
/* Override it with your own, if one exists. */
file = wgetrc_file_name ();
if (!file)
return;
/* #### We should somehow canonicalize `file' and SYSTEM_WGETRC,
really. */
#ifdef SYSTEM_WGETRC
if (!strcmp (file, SYSTEM_WGETRC))
{
fprintf (stderr, _("\
%s: Warning: Both system and user wgetrc point to `%s'.\n"),
exec_name, file);
}
else
#endif
run_wgetrc (file);
free (file);
return;
}
/* Parse the line pointed by line, with the syntax:
<sp>* command <sp>* = <sp>* value <newline>
Uses malloc to allocate space for command and value.
If the line is invalid, data is freed and 0 is returned.
Return values:
1 - success
0 - failure
-1 - empty */
int
parse_line (const char *line, char **com, char **val)
{
const char *p = line;
const char *orig_comptr, *end;
char *new_comptr;
/* Skip spaces. */
while (*p == ' ' || *p == '\t')
++p;
/* Don't process empty lines. */
if (!*p || *p == '\n' || *p == '#')
return -1;
for (orig_comptr = p; ISALPHA (*p) || *p == '_' || *p == '-'; p++)
;
/* The next char should be space or '='. */
if (!ISSPACE (*p) && (*p != '='))
return 0;
*com = (char *)xmalloc (p - orig_comptr + 1);
for (new_comptr = *com; orig_comptr < p; orig_comptr++)
{
if (*orig_comptr == '_' || *orig_comptr == '-')
continue;
*new_comptr++ = *orig_comptr;
}
*new_comptr = '\0';
/* If the command is invalid, exit now. */
if (comind (*com) == -1)
{
free (*com);
return 0;
}
/* Skip spaces before '='. */
for (; ISSPACE (*p); p++);
/* If '=' not found, bail out. */
if (*p != '=')
{
free (*com);
return 0;
}
/* Skip spaces after '='. */
for (++p; ISSPACE (*p); p++);
/* Get the ending position. */
for (end = p; *end && *end != '\n'; end++);
/* Allocate *val, and copy from line. */
*val = strdupdelim (p, end);
return 1;
}
/* Set COM to VAL. This is the meat behind processing `.wgetrc'. No
fatals -- error signal prints a warning and resets to default
value. All error messages are printed to stderr, *not* to
opt.lfile, since opt.lfile wasn't even generated yet. */
int
setval (const char *com, const char *val)
{
int ind;
if (!com || !val)
return 0;
ind = comind (com);
if (ind == -1)
{
/* #### Should I just abort()? */
#ifdef DEBUG
fprintf (stderr, _("%s: BUG: unknown command `%s', value `%s'.\n"),
exec_name, com, val);
#endif
return 0;
}
return ((*commands[ind].action) (com, val, commands[ind].closure));
}
/* Generic helper functions, for use with `commands'. */
static int myatoi PARAMS ((const char *s));
/* Store the boolean value from VAL to CLOSURE. COM is ignored,
except for error messages. */
static int
cmd_boolean (const char *com, const char *val, void *closure)
{
int bool_value;
if (!strcasecmp (val, "on")
|| (*val == '1' && !*(val + 1)))
bool_value = 1;
else if (!strcasecmp (val, "off")
|| (*val == '0' && !*(val + 1)))
bool_value = 0;
else
{
fprintf (stderr, _("%s: %s: Please specify on or off.\n"),
exec_name, com);
return 0;
}
*(int *)closure = bool_value;
return 1;
}
/* Set the non-negative integer value from VAL to CLOSURE. With
incorrect specification, the number remains unchanged. */
static int
cmd_number (const char *com, const char *val, void *closure)
{
int num = myatoi (val);
if (num == -1)
{
fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
exec_name, com, val);
return 0;
}
*(int *)closure = num;
return 1;
}
/* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
static int
cmd_number_inf (const char *com, const char *val, void *closure)
{
if (!strcasecmp (val, "inf"))
{
*(int *)closure = 0;
return 1;
}
return cmd_number (com, val, closure);
}
/* Copy (strdup) the string at COM to a new location and place a
pointer to *CLOSURE. */
static int
cmd_string (const char *com, const char *val, void *closure)
{
char **pstring = (char **)closure;
FREE_MAYBE (*pstring);
*pstring = xstrdup (val);
return 1;
}
/* Merge the vector (array of strings separated with `,') in COM with
the vector (NULL-terminated array of strings) pointed to by
CLOSURE. */
static int
cmd_vector (const char *com, const char *val, void *closure)
{
char ***pvec = (char ***)closure;
if (*val)
*pvec = merge_vecs (*pvec, sepstring (val));
else
{
free_vec (*pvec);
*pvec = NULL;
}
return 1;
}
static int
cmd_directory_vector (const char *com, const char *val, void *closure)
{
char ***pvec = (char ***)closure;
if (*val)
{
/* Strip the trailing slashes from directories. */
char **t, **seps;
seps = sepstring (val);
for (t = seps; t && *t; t++)
{
int len = strlen (*t);
/* Skip degenerate case of root directory. */
if (len > 1)
{
if ((*t)[len - 1] == '/')
(*t)[len - 1] = '\0';
}
}
*pvec = merge_vecs (*pvec, seps);
}
else
{
free_vec (*pvec);
*pvec = NULL;
}
return 1;
}
/* Set the value stored in VAL to CLOSURE (which should point to a
long int), allowing several postfixes, with the following syntax
(regexp):
[0-9]+ -> bytes
[0-9]+[kK] -> bytes * 1024
[0-9]+[mM] -> bytes * 1024 * 1024
inf -> 0
Anything else is flagged as incorrect, and CLOSURE is unchanged. */
static int
cmd_bytes (const char *com, const char *val, void *closure)
{
long result;
long *out = (long *)closure;
const char *p;
result = 0;
p = val;
/* Check for "inf". */
if (p[0] == 'i' && p[1] == 'n' && p[2] == 'f' && p[3] == '\0')
{
*out = 0;
return 1;
}
/* Search for digits and construct result. */
for (; *p && ISDIGIT (*p); p++)
result = (10 * result) + (*p - '0');
/* If no digits were found, or more than one character is following
them, bail out. */
if (p == val || (*p != '\0' && *(p + 1) != '\0'))
{
printf (_("%s: Invalid specification `%s'\n"), com, val);
return 0;
}
/* Search for a designator. */
switch (tolower (*p))
{
case '\0':
/* None */
break;
case 'k':
/* Kilobytes */
result *= 1024;
break;
case 'm':
/* Megabytes */
result *= (long)1024 * 1024;
break;
case 'g':
/* Gigabytes */
result *= (long)1024 * 1024 * 1024;
break;
default:
printf (_("%s: Invalid specification `%s'\n"), com, val);
return 0;
}
*out = result;
return 1;
}
/* Store the value of VAL to *OUT, allowing suffixes for minutes and
hours. */
static int
cmd_time (const char *com, const char *val, void *closure)
{
long result = 0;
const char *p = val;
/* Search for digits and construct result. */
for (; *p && ISDIGIT (*p); p++)
result = (10 * result) + (*p - '0');
/* If no digits were found, or more than one character is following
them, bail out. */
if (p == val || (*p != '\0' && *(p + 1) != '\0'))
{
printf (_("%s: Invalid specification `%s'\n"), com, val);
return 0;
}
/* Search for a suffix. */
switch (tolower (*p))
{
case '\0':
/* None */
break;
case 'm':
/* Minutes */
result *= 60;
break;
case 'h':
/* Seconds */
result *= 3600;
break;
case 'd':
/* Days (overflow on 16bit machines) */
result *= 86400L;
break;
case 'w':
/* Weeks :-) */
result *= 604800L;
break;
default:
printf (_("%s: Invalid specification `%s'\n"), com, val);
return 0;
}
*(long *)closure = result;
return 1;
}
/* Specialized helper functions, used by `commands' to handle some
options specially. */
static int check_user_specified_header PARAMS ((const char *));
static int
cmd_spec_dirstruct (const char *com, const char *val, void *closure)
{
if (!cmd_boolean (com, val, &opt.dirstruct))
return 0;
/* Since dirstruct behaviour is explicitly changed, no_dirstruct
must be affected inversely. */
if (opt.dirstruct)
opt.no_dirstruct = 0;
else
opt.no_dirstruct = 1;
return 1;
}
static int
cmd_spec_dotstyle (const char *com, const char *val, void *closure)
{
/* Retrieval styles. */
if (!strcasecmp (val, "default"))
{
/* Default style: 1K dots, 10 dots in a cluster, 50 dots in a
line. */
opt.dot_bytes = 1024;
opt.dot_spacing = 10;
opt.dots_in_line = 50;
}
else if (!strcasecmp (val, "binary"))
{
/* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots
(384K) in a line. */
opt.dot_bytes = 8192;
opt.dot_spacing = 16;
opt.dots_in_line = 48;
}
else if (!strcasecmp (val, "mega"))
{
/* "Mega" retrieval, for retrieving very long files; each dot is
64K, 8 dots in a cluster, 6 clusters (3M) in a line. */
opt.dot_bytes = 65536L;
opt.dot_spacing = 8;
opt.dots_in_line = 48;
}
else if (!strcasecmp (val, "giga"))
{
/* "Giga" retrieval, for retrieving very very *very* long files;
each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a
line. */
opt.dot_bytes = (1L << 20);
opt.dot_spacing = 8;
opt.dots_in_line = 32;
}
else if (!strcasecmp (val, "micro"))
{
/* "Micro" retrieval, for retrieving very small files (and/or
slow connections); each dot is 128 bytes, 8 dots in a
cluster, 6 clusters (6K) in a line. */
opt.dot_bytes = 128;
opt.dot_spacing = 8;
opt.dots_in_line = 48;
}
else
{
fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
exec_name, com, val);
return 0;
}
return 1;
}
static int
cmd_spec_header (const char *com, const char *val, void *closure)
{
if (!*val)
{
/* Empty header means reset headers. */
FREE_MAYBE (opt.user_header);
opt.user_header = NULL;
}
else
{
int i;
if (!check_user_specified_header (val))
{
fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
exec_name, com, val);
return 0;
}
i = opt.user_header ? strlen (opt.user_header) : 0;
opt.user_header = (char *)xrealloc (opt.user_header, i + strlen (val)
+ 2 + 1);
strcpy (opt.user_header + i, val);
i += strlen (val);
opt.user_header[i++] = '\r';
opt.user_header[i++] = '\n';
opt.user_header[i] = '\0';
}
return 1;
}
static int
cmd_spec_htmlify (const char *com, const char *val, void *closure)
{
int flag = cmd_boolean (com, val, &opt.htmlify);
if (flag && !opt.htmlify)
opt.remove_listing = 0;
return flag;
}
static int
cmd_spec_mirror (const char *com, const char *val, void *closure)
{
int mirror;
if (!cmd_boolean (com, val, &mirror))
return 0;
if (mirror)
{
opt.recursive = 1;
if (!opt.no_dirstruct)
opt.dirstruct = 1;
opt.timestamping = 1;
opt.reclevel = 0;
opt.remove_listing = 0;
}
return 1;
}
static int
cmd_spec_outputdocument (const char *com, const char *val, void *closure)
{
FREE_MAYBE (opt.output_document);
opt.output_document = xstrdup (val);
opt.ntry = 1;
return 1;
}
static int
cmd_spec_recursive (const char *com, const char *val, void *closure)
{
if (!cmd_boolean (com, val, &opt.recursive))
return 0;
else
{
if (opt.recursive && !opt.no_dirstruct)
opt.dirstruct = 1;
}
return 1;
}
static int
cmd_spec_useragent (const char *com, const char *val, void *closure)
{
/* Just check for empty string and newline, so we don't throw total
junk to the server. */
if (!*val || strchr (val, '\n'))
{
fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
exec_name, com, val);
return 0;
}
opt.useragent = xstrdup (val);
return 1;
}
/* Miscellaneous useful routines. */
/* Return the integer value of a positive integer written in S, or -1
if an error was encountered. */
static int
myatoi (const char *s)
{
int res;
const char *orig = s;
for (res = 0; *s && ISDIGIT (*s); s++)
res = 10 * res + (*s - '0');
if (*s || orig == s)
return -1;
else
return res;
}
#define ISODIGIT(x) ((x) >= '0' && (x) <= '7')
static int
check_user_specified_header (const char *s)
{
const char *p;
for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
/* The header MUST contain `:' preceded by at least one
non-whitespace character. */
if (*p != ':' || p == s)
return 0;
/* The header MUST NOT contain newlines. */
if (strchr (s, '\n'))
return 0;
return 1;
}
/* Free the memory allocated by global variables. */
void
cleanup (void)
{
extern acc_t *netrc_list;
recursive_cleanup ();
clean_hosts ();
free_netrc (netrc_list);
if (opt.dfp)
fclose (opt.dfp);
FREE_MAYBE (opt.lfilename);
free (opt.dir_prefix);
FREE_MAYBE (opt.input_filename);
FREE_MAYBE (opt.output_document);
free_vec (opt.accepts);
free_vec (opt.rejects);
free_vec (opt.excludes);
free_vec (opt.includes);
free_vec (opt.domains);
free (opt.ftp_acc);
free (opt.ftp_pass);
FREE_MAYBE (opt.ftp_proxy);
FREE_MAYBE (opt.http_proxy);
free_vec (opt.no_proxy);
FREE_MAYBE (opt.useragent);
FREE_MAYBE (opt.http_user);
FREE_MAYBE (opt.http_passwd);
FREE_MAYBE (opt.user_header);
}

29
src/init.h Normal file
View File

@ -0,0 +1,29 @@
/* Declarations for init.c.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef INIT_H
#define INIT_H
void initialize PARAMS ((void));
int parse_line PARAMS ((const char *, char **, char **));
int setval PARAMS ((const char *, const char *));
char *home_dir PARAMS ((void));
void cleanup PARAMS ((void));
#endif /* INIT_H */

317
src/log.c Normal file
View File

@ -0,0 +1,317 @@
/* Messages logging.
Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdlib.h>
#if defined(__STDC__) && defined(HAVE_STDARG_H)
/* If we have __STDC__ and stdarg.h, we'll assume it's an ANSI system. */
# define USE_STDARG
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <assert.h>
#include <errno.h>
#include "wget.h"
#include "utils.h"
#ifndef errno
extern int errno;
#endif
/* We expect no message passed to logprintf() to be bigger than this.
Before a message is printed, we make sure that at least this much
room is left for printing it. */
#define SAVED_LOG_MAXMSG 32768
/* Maximum allowed growing size. */
#define SAVED_LOG_MAXSIZE (10 * 1L << 20)
static char *saved_log;
/* Size of the current log. */
static long saved_log_size;
/* Offset into the log where we are about to print (size of the
used-up part of SAVED_LOG). */
static long saved_log_offset;
/* Whether logging is saved at all. */
int save_log_p;
static FILE *logfp;
/* Check X against opt.verbose and opt.quiet. The semantics is as
follows:
* LOG_ALWAYS - print the message unconditionally;
* LOG_NOTQUIET - print the message if opt.quiet is non-zero;
* LOG_NONVERBOSE - print the message if opt.verbose is zero;
* LOG_VERBOSE - print the message if opt.verbose is non-zero. */
#define CHECK_VERBOSE(x) \
switch (x) \
{ \
case LOG_ALWAYS: \
break; \
case LOG_NOTQUIET: \
if (opt.quiet) \
return; \
break; \
case LOG_NONVERBOSE: \
if (opt.verbose || opt.quiet) \
return; \
break; \
case LOG_VERBOSE: \
if (!opt.verbose) \
return; \
}
#define CANONICALIZE_LOGFP_OR_RETURN do { \
if (logfp == stdin) \
return; \
else if (!logfp) \
/* #### Should this ever happen? */ \
logfp = stderr; \
} while (0)
void
logputs (enum log_options o, const char *s)
{
CHECK_VERBOSE (o);
CANONICALIZE_LOGFP_OR_RETURN;
fputs (s, logfp);
if (!opt.no_flush)
fflush (logfp);
if (save_log_p && saved_log_size < SAVED_LOG_MAXSIZE)
{
int len = strlen (s);
/* Increase size of SAVED_LOG exponentially. */
DO_REALLOC (saved_log, saved_log_size,
saved_log_offset + len + 1, char);
memcpy (saved_log + saved_log_offset, s, len + 1);
saved_log_offset += len;
}
}
/* Print a message to the log file logfp. If logfp is NULL, print to
stderr. If logfp is stdin, don't print at all. A copy of message
will be saved to saved_log, for later reusal by dump_log(). */
static void
logvprintf (enum log_options o, const char *fmt, va_list args)
{
CHECK_VERBOSE (o);
CANONICALIZE_LOGFP_OR_RETURN;
/* Originally, we first used vfprintf(), and then checked whether
the message needs to be stored with vsprintf(). However, Watcom
C didn't like ARGS being used twice, so now we first vsprintf()
the message, and then fwrite() it to LOGFP. */
if (save_log_p && saved_log_size < SAVED_LOG_MAXSIZE)
{
int len;
/* Increase size of `saved_log' exponentially. */
DO_REALLOC (saved_log, saved_log_size,
saved_log_offset + SAVED_LOG_MAXMSG, char);
/* Print the message to the log saver... */
#ifdef HAVE_VSNPRINTF
vsnprintf (saved_log + saved_log_offset, SAVED_LOG_MAXMSG, fmt, args);
#else /* not HAVE_VSNPRINTF */
vsprintf (saved_log + saved_log_offset, fmt, args);
#endif /* not HAVE_VSNPRINTF */
/* ...and then dump it to LOGFP. */
len = strlen (saved_log + saved_log_offset);
fwrite (saved_log + saved_log_offset, len, 1, logfp);
saved_log_offset += len;
/* If we ran off the limits and corrupted something, bail out
immediately. */
assert (saved_log_size >= saved_log_offset);
}
else
vfprintf (logfp, fmt, args);
if (!opt.no_flush)
fflush (logfp);
}
/* Flush LOGFP. */
void
logflush (void)
{
CANONICALIZE_LOGFP_OR_RETURN;
fflush (logfp);
}
/* Portability makes these two functions look like @#%#@$@#$. */
#ifdef USE_STDARG
void
logprintf (enum log_options o, const char *fmt, ...)
#else /* not USE_STDARG */
void
logprintf (va_alist)
va_dcl
#endif /* not USE_STDARG */
{
va_list args;
#ifndef USE_STDARG
enum log_options o;
const char *fmt;
#endif
#ifdef USE_STDARG
va_start (args, fmt);
#else
va_start (args);
o = va_arg (args, enum log_options);
fmt = va_arg (args, char *);
#endif
logvprintf (o, fmt, args);
va_end (args);
}
#ifdef DEBUG
/* The same as logprintf(), but does anything only if opt.debug is
non-zero. */
#ifdef USE_STDARG
void
debug_logprintf (const char *fmt, ...)
#else /* not USE_STDARG */
void
debug_logprintf (va_alist)
va_dcl
#endif /* not USE_STDARG */
{
if (opt.debug)
{
va_list args;
#ifndef USE_STDARG
const char *fmt;
#endif
#ifdef USE_STDARG
va_start (args, fmt);
#else
va_start (args);
fmt = va_arg (args, char *);
#endif
logvprintf (LOG_ALWAYS, fmt, args);
va_end (args);
}
}
#endif /* DEBUG */
/* Open FILE and set up a logging stream. If FILE cannot be opened,
exit with status of 1. */
void
log_init (const char *file, int appendp)
{
if (file)
{
logfp = fopen (file, appendp ? "a" : "w");
if (!logfp)
{
perror (opt.lfilename);
exit (1);
}
}
else
{
logfp = stderr;
/* If the output is a TTY, enable logging, which will make Wget
remember all the printed messages, to be able to dump them to
a log file in case SIGHUP or SIGUSR1 is received (or
Ctrl+Break is pressed under Windows). */
if (1
#ifdef HAVE_ISATTY
&& isatty (fileno (logfp))
#endif
)
{
save_log_p = 1;
}
}
}
/* Close LOGFP, inhibit further logging and free the memory associated
with it. */
void
log_close (void)
{
fclose (logfp);
save_log_p = 0;
FREE_MAYBE (saved_log);
saved_log = NULL;
saved_log_size = saved_log_offset = 0;
}
/* Dump SAVED_LOG using logprintf(), but quit further logging to memory.
Also, free the memory occupied by saved_log. */
static void
log_dump (void)
{
save_log_p = 0;
if (!saved_log)
return;
logputs (LOG_ALWAYS, saved_log);
free (saved_log);
saved_log = NULL;
saved_log_size = saved_log_offset = 0;
}
/* Redirect output to `wget-log' if opt.lfile is stdout. MESSIJ is
printed on stdout, and should contain *exactly one* `%s', which
will be replaced by the log file name.
If logging was not enabled, MESSIJ will not be printed. */
void
redirect_output (const char *messij)
{
char *logfile;
if (!save_log_p)
return;
logfile = unique_name (DEFAULT_LOGFILE);
logfp = fopen (logfile, "w");
if (!logfp)
{
printf ("%s: %s: %s\n", exec_name, logfile, strerror (errno));
/* `stdin' is magic to not print anything. */
logfp = stdin;
}
printf (messij, logfile);
free (logfile);
/* Dump all the previous messages to LOGFILE. */
log_dump ();
}

721
src/main.c Normal file
View File

@ -0,0 +1,721 @@
/* Command line parsing.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <sys/types.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_NLS
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif /* HAVE_LOCALE_H */
#endif /* HAVE_NLS */
#define OPTIONS_DEFINED_HERE /* for options.h */
#include "wget.h"
#include "utils.h"
#include "getopt.h"
#include "init.h"
#include "retr.h"
#include "recur.h"
#include "host.h"
#ifndef PATH_SEPARATOR
# define PATH_SEPARATOR '/'
#endif
extern char *version_string;
#ifndef errno
extern int errno;
#endif
struct options opt;
/* From log.c. */
void log_init PARAMS ((const char *, int));
void log_close PARAMS ((void));
void redirect_output PARAMS ((const char *));
static RETSIGTYPE redirect_output_signal PARAMS ((int));
const char *exec_name;
/* Initialize I18N. The initialization amounts to invoking
setlocale(), bindtextdomain() and textdomain().
Does nothing if NLS is disabled or missing. */
static void
i18n_initialize (void)
{
/* If HAVE_NLS is defined, assume the existence of the three
functions invoked here. */
#ifdef HAVE_NLS
/* Set the current locale. */
/* Here we use LC_MESSAGES instead of LC_ALL, for two reasons.
First, message catalogs are all of I18N Wget uses anyway.
Second, setting LC_ALL has a dangerous potential of messing
things up. For example, when in a foreign locale, Solaris
strptime() fails to handle international dates correctly, which
makes http_atotm() malfunction. */
setlocale (LC_MESSAGES, "");
/* Set the text message domain. */
bindtextdomain ("wget", LOCALEDIR);
textdomain ("wget");
#endif /* HAVE_NLS */
}
/* Print the usage message. */
static void
print_usage (void)
{
printf (_("Usage: %s [OPTION]... [URL]...\n"), exec_name);
}
/* Print the help message, describing all the available options. If
you add an option, be sure to update this list. */
static void
print_help (void)
{
printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
version_string);
print_usage ();
/* Had to split this in parts, so the #@@#%# Ultrix compiler and cpp
don't bitch. Also, it makes translation much easier. */
printf ("%s%s%s%s%s%s%s%s%s%s", _("\
\n\
Mandatory arguments to long options are mandatory for short options too.\n\
\n"), _("\
Startup:\n\
-V, --version display the version of Wget and exit.\n\
-h, --help print this help.\n\
-b, --background go to background after startup.\n\
-e, --execute=COMMAND execute a `.wgetrc\' command.\n\
\n"), _("\
Logging and input file:\n\
-o, --output-file=FILE log messages to FILE.\n\
-a, --append-output=FILE append messages to FILE.\n\
-d, --debug print debug output.\n\
-q, --quiet quiet (no output).\n\
-v, --verbose be verbose (this is the default).\n\
-nv, --non-verbose turn off verboseness, without being quiet.\n\
-i, --input-file=FILE read URL-s from file.\n\
-F, --force-html treat input file as HTML.\n\
\n"), _("\
Download:\n\
-t, --tries=NUMBER set number of retries to NUMBER (0 unlimits).\n\
-O --output-document=FILE write documents to FILE.\n\
-nc, --no-clobber don\'t clobber existing files.\n\
-c, --continue restart getting an existing file.\n\
--dot-style=STYLE set retrieval display style.\n\
-N, --timestamping don\'t retrieve files if older than local.\n\
-S, --server-response print server response.\n\
--spider don\'t download anything.\n\
-T, --timeout=SECONDS set the read timeout to SECONDS.\n\
-w, --wait=SECONDS wait SECONDS between retrievals.\n\
-Y, --proxy=on/off turn proxy on or off.\n\
-Q, --quota=NUMBER set retrieval quota to NUMBER.\n\
\n"), _("\
Directories:\n\
-nd --no-directories don\'t create directories.\n\
-x, --force-directories force creation of directories.\n\
-nH, --no-host-directories don\'t create host directories.\n\
-P, --directory-prefix=PREFIX save files to PREFIX/...\n\
--cut-dirs=NUMBER ignore NUMBER remote directory components.\n\
\n"), _("\
HTTP options:\n\
--http-user=USER set http user to USER.\n\
--http-passwd=PASS set http password to PASS.\n\
-C, --cache=on/off (dis)allow server-cached data (normally allowed).\n\
--ignore-length ignore `Content-Length\' header field.\n\
--header=STRING insert STRING among the headers.\n\
--proxy-user=USER set USER as proxy username.\n\
--proxy-passwd=PASS set PASS as proxy password.\n\
-s, --save-headers save the HTTP headers to file.\n\
-U, --user-agent=AGENT identify as AGENT instead of Wget/VERSION.\n\
\n"), _("\
FTP options:\n\
--retr-symlinks retrieve FTP symbolic links.\n\
-g, --glob=on/off turn file name globbing on or off.\n\
--passive-ftp use the \"passive\" transfer mode.\n\
\n"), _("\
Recursive retrieval:\n\
-r, --recursive recursive web-suck -- use with care!.\n\
-l, --level=NUMBER maximum recursion depth (0 to unlimit).\n\
--delete-after delete downloaded files.\n\
-k, --convert-links convert non-relative links to relative.\n\
-m, --mirror turn on options suitable for mirroring.\n\
-nr, --dont-remove-listing don\'t remove `.listing\' files.\n\
\n"), _("\
Recursive accept/reject:\n\
-A, --accept=LIST list of accepted extensions.\n\
-R, --reject=LIST list of rejected extensions.\n\
-D, --domains=LIST list of accepted domains.\n\
--exclude-domains=LIST comma-separated list of rejected domains.\n\
-L, --relative follow relative links only.\n\
--follow-ftp follow FTP links from HTML documents.\n\
-H, --span-hosts go to foreign hosts when recursive.\n\
-I, --include-directories=LIST list of allowed directories.\n\
-X, --exclude-directories=LIST list of excluded directories.\n\
-nh, --no-host-lookup don\'t DNS-lookup hosts.\n\
-np, --no-parent don\'t ascend to the parent directory.\n\
\n"), _("Mail bug reports and suggestions to <bug-wget@gnu.org>.\n"));
}
int
main (int argc, char *const *argv)
{
char **url, **t;
int i, c, nurl, status, append_to_log;
static struct option long_options[] =
{
{ "background", no_argument, NULL, 'b' },
{ "continue", no_argument, NULL, 'c' },
{ "convert-links", no_argument, NULL, 'k' },
{ "debug", no_argument, NULL, 'd' },
{ "dont-remove-listing", no_argument, NULL, 21 },
{ "email-address", no_argument, NULL, 'E' }, /* undocumented (debug) */
{ "follow-ftp", no_argument, NULL, 14 },
{ "force-directories", no_argument, NULL, 'x' },
{ "force-hier", no_argument, NULL, 'x' }, /* obsolete */
{ "force-html", no_argument, NULL, 'F'},
{ "help", no_argument, NULL, 'h' },
{ "ignore-length", no_argument, NULL, 10 },
{ "mirror", no_argument, NULL, 'm' },
{ "no-clobber", no_argument, NULL, 13 },
{ "no-directories", no_argument, NULL, 19 },
{ "no-host-directories", no_argument, NULL, 20 },
{ "no-host-lookup", no_argument, NULL, 22 },
{ "no-parent", no_argument, NULL, 5 },
{ "non-verbose", no_argument, NULL, 18 },
{ "passive-ftp", no_argument, NULL, 11 },
{ "quiet", no_argument, NULL, 'q' },
{ "recursive", no_argument, NULL, 'r' },
{ "relative", no_argument, NULL, 'L' },
{ "retr-symlinks", no_argument, NULL, 9 },
{ "save-headers", no_argument, NULL, 's' },
{ "server-response", no_argument, NULL, 'S' },
{ "span-hosts", no_argument, NULL, 'H' },
{ "spider", no_argument, NULL, 4 },
{ "timestamping", no_argument, NULL, 'N' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ "accept", required_argument, NULL, 'A' },
{ "append-output", required_argument, NULL, 'a' },
{ "backups", required_argument, NULL, 23 }, /* undocumented */
{ "base", required_argument, NULL, 'B' },
{ "cache", required_argument, NULL, 'C' },
{ "cut-dirs", required_argument, NULL, 17 },
{ "delete-after", no_argument, NULL, 8 },
{ "directory-prefix", required_argument, NULL, 'P' },
{ "domains", required_argument, NULL, 'D' },
{ "dot-style", required_argument, NULL, 6 },
{ "execute", required_argument, NULL, 'e' },
{ "exclude-directories", required_argument, NULL, 'X' },
{ "exclude-domains", required_argument, NULL, 12 },
{ "glob", required_argument, NULL, 'g' },
{ "header", required_argument, NULL, 3 },
{ "htmlify", required_argument, NULL, 7 },
{ "http-passwd", required_argument, NULL, 2 },
{ "http-user", required_argument, NULL, 1 },
{ "include-directories", required_argument, NULL, 'I' },
{ "input-file", required_argument, NULL, 'i' },
{ "level", required_argument, NULL, 'l' },
{ "no", required_argument, NULL, 'n' },
{ "output-document", required_argument, NULL, 'O' },
{ "output-file", required_argument, NULL, 'o' },
{ "proxy", required_argument, NULL, 'Y' },
{ "proxy-passwd", required_argument, NULL, 16 },
{ "proxy-user", required_argument, NULL, 15 },
{ "quota", required_argument, NULL, 'Q' },
{ "reject", required_argument, NULL, 'R' },
{ "timeout", required_argument, NULL, 'T' },
{ "tries", required_argument, NULL, 't' },
{ "user-agent", required_argument, NULL, 'U' },
{ "use-proxy", required_argument, NULL, 'Y' },
{ "wait", required_argument, NULL, 'w' },
{ 0, 0, 0, 0 }
};
i18n_initialize ();
append_to_log = 0;
/* Construct the name of the executable, without the directory part. */
exec_name = strrchr (argv[0], PATH_SEPARATOR);
if (!exec_name)
exec_name = argv[0];
else
++exec_name;
#ifdef WINDOWS
windows_main_junk (&argc, (char **) argv, (char **) &exec_name);
#endif
initialize ();
while ((c = getopt_long (argc, argv, "\
hVqvdksxmNWrHSLcFbEY:g:T:U:O:l:n:i:o:a:t:D:A:R:P:B:e:Q:X:I:w:",
long_options, (int *)0)) != EOF)
{
switch (c)
{
/* Options without arguments: */
case 4:
setval ("spider", "on");
break;
case 5:
setval ("noparent", "on");
break;
case 8:
setval ("deleteafter", "on");
break;
case 9:
setval ("retrsymlinks", "on");
break;
case 10:
setval ("ignorelength", "on");
break;
case 11:
setval ("passiveftp", "on");
break;
case 13:
setval ("noclobber", "on");
break;
case 14:
setval ("followftp", "on");
break;
case 17:
setval ("cutdirs", optarg);
break;
case 18:
setval ("verbose", "off");
break;
case 19:
setval ("dirstruct", "off");
break;
case 20:
setval ("addhostdir", "off");
break;
case 21:
setval ("removelisting", "off");
break;
case 22:
setval ("simplehostcheck", "on");
break;
case 'b':
setval ("background", "on");
break;
case 'c':
setval ("continue", "on");
break;
case 'd':
#ifdef DEBUG
setval ("debug", "on");
#else /* not DEBUG */
fprintf (stderr, _("%s: debug support not compiled in.\n"),
exec_name);
#endif /* not DEBUG */
break;
case 'E':
/* For debugging purposes. */
printf ("%s\n", ftp_getaddress ());
exit (0);
break;
case 'F':
setval ("forcehtml", "on");
break;
case 'H':
setval ("spanhosts", "on");
break;
case 'h':
print_help ();
#ifdef WINDOWS
ws_help (exec_name);
#endif
exit (0);
break;
case 'k':
setval ("convertlinks", "on");
break;
case 'L':
setval ("relativeonly", "on");
break;
case 'm':
setval ("mirror", "on");
break;
case 'N':
setval ("timestamping", "on");
break;
case 'S':
setval ("serverresponse", "on");
break;
case 's':
setval ("saveheaders", "on");
break;
case 'q':
setval ("quiet", "on");
break;
case 'r':
setval ("recursive", "on");
break;
case 'V':
printf ("GNU Wget %s\n\n", version_string);
printf ("%s", _("\
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.\n\
This program is distributed in the hope that it will be useful,\n\
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
GNU General Public License for more details.\n"));
printf (_("\nWritten by Hrvoje Niksic <hniksic@srce.hr>.\n"));
exit (0);
break;
case 'v':
setval ("verbose", "on");
break;
case 'x':
setval ("dirstruct", "on");
break;
/* Options accepting an argument: */
case 1:
setval ("httpuser", optarg);
break;
case 2:
setval ("httppasswd", optarg);
break;
case 3:
setval ("header", optarg);
break;
case 6:
setval ("dotstyle", optarg);
break;
case 7:
setval ("htmlify", optarg);
break;
case 12:
setval ("excludedomains", optarg);
break;
case 15:
setval ("proxyuser", optarg);
break;
case 16:
setval ("proxypasswd", optarg);
break;
case 23:
setval ("backups", optarg);
break;
case 'A':
setval ("accept", optarg);
break;
case 'a':
setval ("logfile", optarg);
append_to_log = 1;
break;
case 'B':
setval ("base", optarg);
break;
case 'C':
setval ("cache", optarg);
break;
case 'D':
setval ("domains", optarg);
break;
case 'e':
{
char *com, *val;
if (parse_line (optarg, &com, &val))
{
if (!setval (com, val))
exit (1);
}
else
{
fprintf (stderr, _("%s: %s: invalid command\n"), exec_name,
optarg);
exit (1);
}
free (com);
free (val);
}
break;
case 'g':
setval ("glob", optarg);
break;
case 'I':
setval ("includedirectories", optarg);
break;
case 'i':
setval ("input", optarg);
break;
case 'l':
setval ("reclevel", optarg);
break;
case 'n':
{
/* #### The n? options are utter crock! */
char *p;
for (p = optarg; *p; p++)
switch (*p)
{
case 'v':
setval ("verbose", "off");
break;
case 'h':
setval ("simplehostcheck", "on");
break;
case 'H':
setval ("addhostdir", "off");
break;
case 'd':
setval ("dirstruct", "off");
break;
case 'c':
setval ("noclobber", "on");
break;
case 'r':
setval ("removelisting", "off");
break;
case 'p':
setval ("noparent", "on");
break;
default:
printf (_("%s: illegal option -- `-n%c'\n"), exec_name, *p);
print_usage ();
printf ("\n");
printf (_("Try `%s --help\' for more options.\n"), exec_name);
exit (1);
}
break;
}
case 'O':
setval ("outputdocument", optarg);
break;
case 'o':
setval ("logfile", optarg);
break;
case 'P':
setval ("dirprefix", optarg);
break;
case 'Q':
setval ("quota", optarg);
break;
case 'R':
setval ("reject", optarg);
break;
case 'T':
setval ("timeout", optarg);
break;
case 't':
setval ("tries", optarg);
break;
case 'U':
setval ("useragent", optarg);
break;
case 'w':
setval ("wait", optarg);
break;
case 'X':
setval ("excludedirectories", optarg);
break;
case 'Y':
setval ("useproxy", optarg);
break;
case '?':
print_usage ();
printf ("\n");
printf (_("Try `%s --help' for more options.\n"), exec_name);
exit (0);
break;
}
}
if (opt.verbose == -1)
opt.verbose = !opt.quiet;
/* Sanity checks. */
if (opt.verbose && opt.quiet)
{
printf (_("Can't be verbose and quiet at the same time.\n"));
print_usage ();
exit (1);
}
if (opt.timestamping && opt.noclobber)
{
printf (_("\
Can't timestamp and not clobber old files at the same time.\n"));
print_usage ();
exit (1);
}
nurl = argc - optind;
if (!nurl && !opt.input_filename)
{
/* No URL specified. */
printf (_("%s: missing URL\n"), exec_name);
print_usage ();
printf ("\n");
/* #### Something nicer should be printed here -- similar to the
pre-1.5 `--help' page. */
printf (_("Try `%s --help' for more options.\n"), exec_name);
exit (1);
}
if (opt.background)
fork_to_background ();
/* Allocate basic pointer. */
url = ALLOCA_ARRAY (char *, nurl + 1);
/* Fill in the arguments. */
for (i = 0; i < nurl; i++, optind++)
{
char *irix4_cc_needs_this;
STRDUP_ALLOCA (irix4_cc_needs_this, argv[optind]);
url[i] = irix4_cc_needs_this;
}
url[i] = NULL;
/* Change the title of console window on Windows. #### I think this
statement should belong to retrieve_url(). --hniksic. */
#ifdef WINDOWS
ws_changetitle (*url, nurl);
#endif
/* Initialize logging. */
log_init (opt.lfilename, append_to_log);
DEBUGP (("DEBUG output created by Wget %s on %s.\n\n", version_string,
OS_TYPE));
/* Open the output filename if necessary. */
if (opt.output_document)
{
if (HYPHENP (opt.output_document))
opt.dfp = stdout;
else
{
opt.dfp = fopen (opt.output_document, "wb");
if (opt.dfp == NULL)
{
perror (opt.output_document);
exit (1);
}
}
}
#ifdef WINDOWS
ws_startup ();
#endif
/* Setup the signal handler to redirect output when hangup is
received. */
#ifdef HAVE_SIGNAL
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, redirect_output_signal);
/* ...and do the same for SIGUSR1. */
signal (SIGUSR1, redirect_output_signal);
/* Writing to a closed socket normally signals SIGPIPE, and the
process exits. What we want is to ignore SIGPIPE and just check
for the return value of write(). */
signal (SIGPIPE, SIG_IGN);
#endif /* HAVE_SIGNAL */
status = RETROK; /* initialize it, just-in-case */
recursive_reset ();
/* Retrieve the URLs from argument list. */
for (t = url; *t; t++)
{
char *filename, *new_file;
int dt;
status = retrieve_url (*t, &filename, &new_file, NULL, &dt);
if (opt.recursive && status == RETROK && (dt & TEXTHTML))
status = recursive_retrieve (filename, new_file ? new_file : *t);
FREE_MAYBE (new_file);
FREE_MAYBE (filename);
}
/* And then from the input file, if any. */
if (opt.input_filename)
{
int count;
status = retrieve_from_file (opt.input_filename, opt.force_html, &count);
if (!count)
logprintf (LOG_NOTQUIET, _("No URLs found in %s.\n"),
opt.input_filename);
}
/* Print the downloaded sum. */
if (opt.recursive
|| nurl > 1
|| (opt.input_filename && opt.downloaded != 0))
{
logprintf (LOG_NOTQUIET,
_("\nFINISHED --%s--\nDownloaded: %s bytes in %d files\n"),
time_str (NULL), legible (opt.downloaded), opt.numurls);
/* Print quota warning, if exceeded. */
if (opt.quota && opt.downloaded > opt.quota)
logprintf (LOG_NOTQUIET,
_("Download quota (%s bytes) EXCEEDED!\n"),
legible (opt.quota));
}
if (opt.convert_links)
{
convert_all_links ();
}
log_close ();
cleanup ();
if (status == RETROK)
return 0;
else
return 1;
}
/* Hangup signal handler. When wget receives SIGHUP or SIGUSR1, it
will proceed operation as usual, trying to write into a log file.
If that is impossible, the output will be turned off. */
#ifdef HAVE_SIGNAL
static RETSIGTYPE
redirect_output_signal (int sig)
{
char tmp[100];
signal (sig, redirect_output_signal);
/* Please note that the double `%' in `%%s' is intentional, because
redirect_output passes tmp through printf. */
sprintf (tmp, _("%s received, redirecting output to `%%s'.\n"),
(sig == SIGHUP ? "SIGHUP" :
(sig == SIGUSR1 ? "SIGUSR1" :
"WTF?!")));
redirect_output (tmp);
}
#endif /* HAVE_SIGNAL */

410
src/md5.c Normal file
View File

@ -0,0 +1,410 @@
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
according to the definition of MD5 in RFC 1321 from April 1992.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/* Wget */
/*#if STDC_HEADERS || defined _LIBC*/
# include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
/*#else*/
/*# ifndef HAVE_MEMCPY*/
/*# define memcpy(d, s, n) bcopy ((s), (d), (n))*/
/*# endif*/
/*#endif*/
#include "wget.h"
#include "md5.h"
#ifdef _LIBC
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
# define WORDS_BIGENDIAN 1
# endif
#endif
#ifdef WORDS_BIGENDIAN
# define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#else
# define SWAP(n) (n)
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
void
md5_init_ctx (struct md5_ctx *ctx)
{
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/* Put result from CTX in first 16 bytes following RESBUF. The result
must be in little endian byte order.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
void *
md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
{
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
void *
md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
{
/* Take yet unprocessed bytes into account. */
md5_uint32 bytes = ctx->buflen;
size_t pad;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if (ctx->total[0] < bytes)
++ctx->total[1];
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
memcpy (&ctx->buffer[bytes], fillbuf, pad);
/* Put the 64-bit file length in *bits* at the end of the buffer. */
*(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
*(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
(ctx->total[0] >> 29));
/* Process last bytes. */
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
return md5_read_ctx (ctx, resbuf);
}
/* Unused in Wget */
#if 0
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
int
md5_stream (FILE *stream, void *resblock)
{
/* Important: BLOCKSIZE must be a multiple of 64. */
#define BLOCKSIZE 4096
struct md5_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
md5_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
do
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
}
while (sum < BLOCKSIZE && n != 0);
if (n == 0 && ferror (stream))
return 1;
/* If end of file is reached, end the loop. */
if (n == 0)
break;
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
md5_process_block (buffer, BLOCKSIZE, &ctx);
}
/* Add the last bytes if necessary. */
if (sum > 0)
md5_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
md5_finish_ctx (&ctx, resblock);
return 0;
}
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *
md5_buffer (const char *buffer, size_t len, void *resblock)
{
struct md5_ctx ctx;
/* Initialize the computation context. */
md5_init_ctx (&ctx);
/* Process whole buffer but last len % 64 bytes. */
md5_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return md5_finish_ctx (&ctx, resblock);
}
#endif /* 0 */
void
md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&ctx->buffer[left_over], buffer, add);
ctx->buflen += add;
if (left_over + add > 64)
{
md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
(left_over + add) & 63);
ctx->buflen = (left_over + add) & 63;
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len > 64)
{
md5_process_block (buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
memcpy (ctx->buffer, buffer, len);
ctx->buflen = len;
}
}
/* These are the four functions used in the four steps of the MD5 algorithm
and defined in the RFC 1321. The first function is a little bit optimized
(as found in Colin Plumbs public domain implementation). */
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
#define FF(b, c, d) (d ^ (b & (c ^ d)))
#define FG(b, c, d) FF (d, b, c)
#define FH(b, c, d) (b ^ c ^ d)
#define FI(b, c, d) (c ^ (b | ~d))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0. */
void
md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
{
md5_uint32 correct_words[16];
const md5_uint32 *words = (md5_uint32 *)buffer;
size_t nwords = len / sizeof (md5_uint32);
const md5_uint32 *endp = words + nwords;
md5_uint32 A = ctx->A;
md5_uint32 B = ctx->B;
md5_uint32 C = ctx->C;
md5_uint32 D = ctx->D;
/* First increment the byte count. RFC 1321 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += len;
if (ctx->total[0] < len)
++ctx->total[1];
/* Process all bytes in the buffer with 64 bytes in each round of
the loop. */
while (words < endp)
{
md5_uint32 *cwp = correct_words;
md5_uint32 A_save = A;
md5_uint32 B_save = B;
md5_uint32 C_save = C;
md5_uint32 D_save = D;
/* First round: using the given function, the context and a constant
the next context is computed. Because the algorithms processing
unit is a 32-bit word and it is determined to work on words in
little endian byte order we perhaps have to change the byte order
before the computation. To reduce the work for the next steps
we store the swapped words in the array CORRECT_WORDS. */
#define OP(a, b, c, d, s, T) \
do \
{ \
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
++words; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
/* It is unfortunate that C does not provide an operator for
cyclic rotation. Hope the C compiler is smart enough. */
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
/* Before we start, one word to the strange constants.
They are defined in RFC 1321 as
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
*/
/* Round 1. */
OP (A, B, C, D, 7, 0xd76aa478);
OP (D, A, B, C, 12, 0xe8c7b756);
OP (C, D, A, B, 17, 0x242070db);
OP (B, C, D, A, 22, 0xc1bdceee);
OP (A, B, C, D, 7, 0xf57c0faf);
OP (D, A, B, C, 12, 0x4787c62a);
OP (C, D, A, B, 17, 0xa8304613);
OP (B, C, D, A, 22, 0xfd469501);
OP (A, B, C, D, 7, 0x698098d8);
OP (D, A, B, C, 12, 0x8b44f7af);
OP (C, D, A, B, 17, 0xffff5bb1);
OP (B, C, D, A, 22, 0x895cd7be);
OP (A, B, C, D, 7, 0x6b901122);
OP (D, A, B, C, 12, 0xfd987193);
OP (C, D, A, B, 17, 0xa679438e);
OP (B, C, D, A, 22, 0x49b40821);
/* For the second to fourth round we have the possibly swapped words
in CORRECT_WORDS. Redefine the macro to take an additional first
argument specifying the function to use. */
#undef OP
#define OP(f, a, b, c, d, k, s, T) \
do \
{ \
a += f (b, c, d) + correct_words[k] + T; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
/* Round 2. */
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
OP (FG, D, A, B, C, 10, 9, 0x02441453);
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
/* Round 3. */
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
/* Round 4. */
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
/* Add the starting values of the context. */
A += A_save;
B += B_save;
C += C_save;
D += D_save;
}
/* Put checksum in context given as argument. */
ctx->A = A;
ctx->B = B;
ctx->C = C;
ctx->D = D;
}

140
src/md5.h Normal file
View File

@ -0,0 +1,140 @@
/* md5.h - Declaration of functions and data types used for MD5 sum
computing library functions.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _MD5_H
#define _MD5_H 1
#include <stdio.h>
#if defined HAVE_LIMITS_H || _LIBC
# include <limits.h>
#endif
/* The following contortions are an attempt to use the C preprocessor
to determine an unsigned integral type that is 32 bits wide. An
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
doing that would require that the configure script compile and *run*
the resulting executable. Locally running cross-compiled executables
is usually not possible. */
#ifdef _LIBC
# include <sys/types.h>
typedef u_int32_t md5_uint32;
#else
# if defined __STDC__ && __STDC__
# define UINT_MAX_32_BITS 4294967295U
# else
# define UINT_MAX_32_BITS 0xFFFFFFFF
# endif
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
This should be valid for all systems GNU cares about because
that doesn't include 16-bit systems, and only modern systems
(that certainly have <limits.h>) have 64+-bit integral types. */
# ifndef UINT_MAX
# define UINT_MAX UINT_MAX_32_BITS
# endif
# if UINT_MAX == UINT_MAX_32_BITS
typedef unsigned int md5_uint32;
# else
# if USHRT_MAX == UINT_MAX_32_BITS
typedef unsigned short md5_uint32;
# else
# if ULONG_MAX == UINT_MAX_32_BITS
typedef unsigned long md5_uint32;
# else
/* The following line is intended to evoke an error.
Using #error is not portable enough. */
"Cannot determine unsigned 32-bit data type."
# endif
# endif
# endif
#endif
/* Structure to save state of computation between the single steps. */
struct md5_ctx
{
md5_uint32 A;
md5_uint32 B;
md5_uint32 C;
md5_uint32 D;
md5_uint32 total[2];
md5_uint32 buflen;
char buffer[128];
};
/*
* The following three functions are build up the low level used in
* the functions `md5_stream' and `md5_buffer'.
*/
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
extern void md5_init_ctx PARAMS ((struct md5_ctx *ctx));
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void md5_process_block PARAMS ((const void *buffer, size_t len,
struct md5_ctx *ctx));
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void md5_process_bytes PARAMS ((const void *buffer, size_t len,
struct md5_ctx *ctx));
/* Process the remaining bytes in the buffer and put result from CTX
in first 16 bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
extern void *md5_finish_ctx PARAMS ((struct md5_ctx *ctx, void *resbuf));
/* Put result from CTX in first 16 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
extern void *md5_read_ctx PARAMS ((const struct md5_ctx *ctx, void *resbuf));
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
extern int md5_stream PARAMS ((FILE *stream, void *resblock));
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void *md5_buffer PARAMS ((const char *buffer, size_t len,
void *resblock));
#endif

269
src/mswindows.c Normal file
View File

@ -0,0 +1,269 @@
/* mswindows.c -- Windows-specific support
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* #### Someone document these functions! */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <string.h>
#include <assert.h>
#include "wget.h"
#include "url.h"
char *argv0;
/* Defined in log.c. */
void redirect_output (const char *);
static int windows_nt_p;
/* Emulation of Unix sleep. */
unsigned int
sleep (unsigned seconds)
{
Sleep (1000 * seconds);
/* Unix sleep() is interruptible. To make it semi-usable, it
returns a value that says how much it "really" slept, or some
junk like that. Ignore it. */
return 0U;
}
static char *
read_registry (HKEY hkey, char *subkey, char *valuename, char *buf, int *len)
{
HKEY result;
DWORD size = *len;
DWORD type = REG_SZ;
if (RegOpenKeyEx (hkey, subkey, NULL, KEY_READ, &result) != ERROR_SUCCESS)
return NULL;
if (RegQueryValueEx (result, valuename, NULL, &type, buf, &size) != ERROR_SUCCESS)
buf = NULL;
*len = size;
RegCloseKey (result);
return buf;
}
char *
pwd_cuserid (char *where)
{
char buf[32], *ptr;
int len = sizeof (buf);
if (GetUserName (buf, (LPDWORD) &len) == TRUE)
{
;
}
else if (!!(ptr = getenv ("USERNAME")))
{
strcpy (buf, ptr);
}
else if (!read_registry (HKEY_LOCAL_MACHINE, "Network\\Logon",
"username", buf, &len))
{
return NULL;
}
if (where)
{
strncpy (where, buf, len);
return where;
}
return xstrdup (buf);
}
void
windows_main_junk (int *argc, char **argv, char **exec_name)
{
char *p;
argv0 = argv[0];
/* Remove .EXE from filename if it has one. */
*exec_name = xstrdup (*exec_name);
p = strrchr (*exec_name, '.');
if (p)
*p = '\0';
}
/* Winsock stuff. */
static void
ws_cleanup (void)
{
WSACleanup ();
}
static void
ws_hangup (void)
{
redirect_output (_("\n\
CTRL+Break received, redirecting output to `%s'.\n\
Execution continued in background.\n\
You may stop Wget by pressing CTRL+ALT+DELETE.\n"));
}
void
fork_to_background (void)
{
/* Whether we arrange our own version of opt.lfilename here. */
int changedp = 0;
if (!opt.lfilename)
{
opt.lfilename = unique_name (DEFAULT_LOGFILE);
changedp = 1;
}
printf (_("Continuing in background.\n"));
if (changedp)
printf (_("Output will be written to `%s'.\n"), opt.lfilename);
ws_hangup ();
if (!windows_nt_p)
FreeConsole ();
}
static BOOL WINAPI
ws_handler (DWORD dwEvent)
{
switch (dwEvent)
{
#ifdef CTRLC_BACKGND
case CTRL_C_EVENT:
#endif
#ifdef CTRLBREAK_BACKGND
case CTRL_BREAK_EVENT:
#endif
fork_to_background ();
break;
case CTRL_SHUTDOWN_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
default:
WSACleanup ();
return FALSE;
}
return TRUE;
}
void
ws_changetitle (char *url, int nurl)
{
char *title_buf;
if (!nurl)
return;
title_buf = (char *)xmalloc (strlen (url) + 20);
sprintf (title_buf, "Wget %s%s", url, nurl == 1 ? "" : " ...");
/* #### What are the semantics of SetConsoleTitle? Will it free the
given memory later? */
SetConsoleTitle (title_buf);
}
char *
ws_mypath (void)
{
static char *wspathsave;
char *buffer;
int rrr;
char *ptr;
if (wspathsave)
{
return wspathsave;
}
ptr = strrchr (argv0, '\\');
if (ptr)
{
*(ptr + 1) = '\0';
wspathsave = (char*) xmalloc (strlen(argv0)+1);
strcpy (wspathsave, argv0);
return wspathsave;
}
buffer = (char*) xmalloc (256);
rrr = SearchPath (NULL, argv0, strchr (argv0, '.') ? NULL : ".EXE",
256, buffer, &ptr);
if (rrr && rrr <= 256)
{
*ptr = '\0';
wspathsave = (char*) xmalloc (strlen(buffer)+1);
strcpy (wspathsave, buffer);
return wspathsave;
}
free (buffer);
return NULL;
}
void
ws_help (const char *name)
{
char *mypath = ws_mypath ();
if (mypath)
{
struct stat sbuf;
char *buf = (char *)alloca (strlen (mypath) + strlen (name) + 4 + 1);
sprintf (buf, "%s%s.HLP", mypath, name);
if (stat (buf, &sbuf) == 0)
{
printf (_("Starting WinHelp %s\n"), buf);
WinHelp (NULL, buf, HELP_INDEX, NULL);
}
else
{
printf ("%s: %s\n", buf, strerror (errno));
}
}
}
void
ws_startup (void)
{
WORD requested;
WSADATA data;
int err;
OSVERSIONINFO os;
if (GetVersionEx (&os) == TRUE
&& os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
windows_nt_p = 1;
requested = MAKEWORD (1, 1);
err = WSAStartup (requested, &data);
if (err != 0)
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
exec_name);
exit (1);
}
if (LOBYTE (requested) < 1 || (LOBYTE (requested) == 1 &&
HIBYTE (requested) < 1))
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
exec_name);
WSACleanup ();
exit (1);
}
atexit (ws_cleanup);
SetConsoleCtrlHandler (ws_handler, TRUE);
}

109
src/mswindows.h Normal file
View File

@ -0,0 +1,109 @@
/* Declarations for windows
Copyright (C) 1995, 1997, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef MSWINDOWS_H
#define MSWINDOWS_H
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & (_S_IFMT)) == (_S_IFDIR))
#endif
#ifndef S_ISLNK
# define S_ISLNK(a) 0
#endif
/* We have strcasecmp and strncasecmp, just under a different name. */
#define strcasecmp stricmp
#define strncasecmp strnicmp
/* No stat on Windows. */
#define lstat stat
#define PATH_SEPARATOR '\\'
/* Microsoft says stat is _stat, Borland doesn't */
#ifdef _MSC_VER
# define stat _stat
#endif
#define REALCLOSE(x) closesocket (x)
/* read & write don't work with sockets on Windows 95. */
#define READ(fd, buf, cnt) recv ((fd), (buf), (cnt), 0)
#define WRITE(fd, buf, cnt) send ((fd), (buf), (cnt), 0)
/* #### Do we need this? */
#include <direct.h>
/* Windows compilers accept only one arg to mkdir. */
#ifndef __BORLANDC__
# define mkdir(a, b) _mkdir(a)
#else /* __BORLANDC__ */
# define mkdir(a, b) mkdir(a)
#endif /* __BORLANDC__ */
#include <windows.h>
/* Declarations of various socket errors: */
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
/* Public functions. */
unsigned int sleep (unsigned);
void ws_startup (void);
void ws_changetitle (char*, int);
char *ws_mypath (void);
void ws_help (const char *);
void windows_main_junk (int *, char **, char **);
#endif /* MSWINDOWS_H */

490
src/netrc.c Normal file
View File

@ -0,0 +1,490 @@
/* Read and parse the .netrc file to get hosts, accounts, and passwords.
Copyright (C) 1996, Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file used to be kept in synch with the code in Fetchmail, but
the latter has diverged since. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <sys/types.h>
#include <errno.h>
#include "wget.h"
#include "utils.h"
#include "netrc.h"
#include "init.h"
#ifndef errno
extern int errno;
#endif
#define NETRC_FILE_NAME ".netrc"
acc_t *netrc_list;
static acc_t *parse_netrc PARAMS ((const char *));
/* Return the correct user and password, given the host, user (as
given in the URL), and password (as given in the URL). May return
NULL.
If SLACK_DEFAULT is set, allow looking for a "default" account.
You will typically turn it off for HTTP. */
void
search_netrc (const char *host, const char **acc, const char **passwd,
int slack_default)
{
acc_t *l;
static int processed_netrc;
if (!opt.netrc)
return;
/* Find ~/.netrc. */
if (!processed_netrc)
{
char *home = home_dir();
netrc_list = NULL;
processed_netrc = 1;
if (home)
{
int err;
struct stat buf;
char *path = (char *)alloca (strlen (home) + 1
+ strlen (NETRC_FILE_NAME) + 1);
sprintf (path, "%s/%s", home, NETRC_FILE_NAME);
free (home);
err = stat (path, &buf);
if (err == 0)
netrc_list = parse_netrc (path);
}
}
/* If nothing to do... */
if (!netrc_list)
return;
/* Acc and password found; all OK. */
if (*acc && *passwd)
return;
if (!*acc && !slack_default)
return;
/* Some data not given -- try finding the host. */
for (l = netrc_list; l; l = l->next)
{
if (!l->host)
continue;
else if (!strcasecmp (l->host, host))
break;
}
if (l)
{
if (*acc)
{
/* Looking for password in .netrc. */
if (!strcmp (l->acc, *acc))
*passwd = l->passwd; /* usernames match; password OK */
else
*passwd = NULL; /* usernames don't match */
}
else /* NOT *acc */
{
/* If password was given, use it. The account is l->acc. */
*acc = l->acc;
if (l->passwd)
*passwd = l->passwd;
}
return;
}
else
{
if (!slack_default)
return;
if (*acc)
return;
/* Try looking for the default account. */
for (l = netrc_list; l; l = l->next)
if (!l->host)
break;
if (!l)
return;
*acc = l->acc;
if (!*passwd)
*passwd = l->passwd;
return;
}
}
#ifdef STANDALONE
/* Normally, these functions would be defined by your package. */
# define xmalloc malloc
# define xstrdup strdup
/* The function reads a whole line. It reads the line realloc-ing the
storage exponentially, doubling the storage after each overflow to
minimize the number of calls to realloc().
It is not an exemplary of correctness, since it kills off the
newline (and no, there is no way to know if there was a newline at
EOF). */
# define xrealloc realloc
# define DYNAMIC_LINE_BUFFER 40
char *
read_whole_line (FILE *fp)
{
char *line;
int i, bufsize, c;
i = 0;
bufsize = DYNAMIC_LINE_BUFFER;
line = xmalloc(bufsize);
/* Construct the line. */
while ((c = getc(fp)) != EOF && c != '\n')
{
if (i > bufsize - 1)
line = (char *)xrealloc(line, (bufsize <<= 1));
line[i++] = c;
}
if (c == EOF && !i)
{
free(line);
return NULL;
}
/* Check for overflow at zero-termination (no need to double the
buffer in this case. */
if (i == bufsize)
line = (char *)xrealloc(line, i + 1);
line[i] = '\0';
return line;
}
#endif /* STANDALONE */
/* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is
set to a ready-to-use acc_t, in any event. */
static void
maybe_add_to_list (acc_t **newentry, acc_t **list)
{
acc_t *a, *l;
a = *newentry;
l = *list;
/* We need an account name in order to add the entry to the list. */
if (a && ! a->acc)
{
/* Free any allocated space. */
free (a->host);
free (a->acc);
free (a->passwd);
}
else
{
if (a)
{
/* Add the current machine into our list. */
a->next = l;
l = a;
}
/* Allocate a new acc_t structure. */
a = (acc_t *)xmalloc (sizeof (acc_t));
}
/* Zero the structure, so that it is ready to use. */
memset (a, 0, sizeof(*a));
/* Return the new pointers. */
*newentry = a;
*list = l;
return;
}
/* Parse a .netrc file (as described in the ftp(1) manual page). */
static acc_t *
parse_netrc (const char *path)
{
FILE *fp;
char *line, *p, *tok, *premature_token;
acc_t *current, *retval;
int ln;
/* The latest token we've seen in the file. */
enum
{
tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
} last_token = tok_nothing;
current = retval = NULL;
fp = fopen (path, "r");
if (!fp)
{
fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
path, strerror (errno));
return retval;
}
/* Initialize the file data. */
ln = 0;
premature_token = NULL;
/* While there are lines in the file... */
while ((line = read_whole_line (fp)))
{
ln ++;
/* Parse the line. */
p = line;
/* If the line is empty, then end any macro definition. */
if (last_token == tok_macdef && !*p)
/* End of macro if the line is empty. */
last_token = tok_nothing;
/* If we are defining macros, then skip parsing the line. */
while (*p && last_token != tok_macdef)
{
/* Skip any whitespace. */
while (*p && ISSPACE (*p))
p ++;
/* Discard end-of-line comments. */
if (*p == '#')
break;
tok = p;
/* Find the end of the token. */
while (*p && !ISSPACE (*p))
p ++;
/* Null-terminate the token, if it isn't already. */
if (*p)
*p ++ = '\0';
switch (last_token)
{
case tok_login:
if (current)
current->acc = xstrdup (tok);
else
premature_token = "login";
break;
case tok_machine:
/* Start a new machine entry. */
maybe_add_to_list (&current, &retval);
current->host = xstrdup (tok);
break;
case tok_password:
if (current)
current->passwd = xstrdup (tok);
else
premature_token = "password";
break;
/* We handle most of tok_macdef above. */
case tok_macdef:
if (!current)
premature_token = "macdef";
break;
/* We don't handle the account keyword at all. */
case tok_account:
if (!current)
premature_token = "account";
break;
/* We handle tok_nothing below this switch. */
case tok_nothing:
break;
}
if (premature_token)
{
fprintf (stderr, _("\
%s: %s:%d: warning: \"%s\" token appears before any machine name\n"),
exec_name, path, ln, premature_token);
premature_token = NULL;
}
if (last_token != tok_nothing)
/* We got a value, so reset the token state. */
last_token = tok_nothing;
else
{
/* Fetch the next token. */
if (!strcmp (tok, "account"))
last_token = tok_account;
else if (!strcmp (tok, "default"))
{
maybe_add_to_list (&current, &retval);
}
else if (!strcmp (tok, "login"))
last_token = tok_login;
else if (!strcmp (tok, "macdef"))
last_token = tok_macdef;
else if (!strcmp (tok, "machine"))
last_token = tok_machine;
else if (!strcmp (tok, "password"))
last_token = tok_password;
else
fprintf (stderr, _("%s: %s:%d: unknown token \"%s\"\n"),
exec_name, path, ln, tok);
}
}
free (line);
}
fclose (fp);
/* Finalize the last machine entry we found. */
maybe_add_to_list (&current, &retval);
free (current);
/* Reverse the order of the list so that it appears in file order. */
current = retval;
retval = NULL;
while (current)
{
acc_t *saved_reference;
/* Change the direction of the pointers. */
saved_reference = current->next;
current->next = retval;
/* Advance to the next node. */
retval = current;
current = saved_reference;
}
return retval;
}
/* Free a netrc list. */
void
free_netrc(acc_t *l)
{
acc_t *t;
while (l)
{
t = l->next;
FREE_MAYBE (l->acc);
FREE_MAYBE (l->passwd);
FREE_MAYBE (l->host);
free(l);
l = t;
}
}
#ifdef STANDALONE
#include <sys/types.h>
#include <sys/stat.h>
int
main (int argc, char **argv)
{
struct stat sb;
char *program_name, *file, *target;
acc_t *head, *a;
if (argc < 2 || argc > 3)
{
fprintf (stderr, _("Usage: %s NETRC [HOSTNAME]\n"), argv[0]);
exit (1);
}
program_name = argv[0];
file = argv[1];
target = argv[2];
if (stat (file, &sb))
{
fprintf (stderr, _("%s: cannot stat %s: %s\n"), argv[0], file,
strerror (errno));
exit (1);
}
head = parse_netrc (file);
a = head;
while (a)
{
/* Skip if we have a target and this isn't it. */
if (target && a->host && strcmp (target, a->host))
{
a = a->next;
continue;
}
if (!target)
{
/* Print the host name if we have no target. */
if (a->host)
fputs (a->host, stdout);
else
fputs ("DEFAULT", stdout);
fputc (' ', stdout);
}
/* Print the account name. */
fputs (a->acc, stdout);
if (a->passwd)
{
/* Print the password, if there is any. */
fputc (' ', stdout);
fputs (a->passwd, stdout);
}
fputc ('\n', stdout);
/* Exit if we found the target. */
if (target)
exit (0);
a = a->next;
}
/* Exit with failure if we had a target, success otherwise. */
if (target)
exit (1);
exit (0);
}
#endif /* STANDALONE */

30
src/netrc.h Normal file
View File

@ -0,0 +1,30 @@
/* Declarations for netrc.c
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
typedef struct _acc_t
{
char *host; /* NULL if this is the default machine
entry. */
char *acc;
char *passwd; /* NULL if there is no password. */
struct _acc_t *next;
} acc_t;
void search_netrc PARAMS((const char *, const char **, const char **, int));
void free_netrc PARAMS((acc_t *l));

139
src/options.h Normal file
View File

@ -0,0 +1,139 @@
/* struct options.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Needed for FDP. */
#include <stdio.h>
struct options
{
int verbose; /* Are we verbose? */
int quiet; /* Are we quiet? */
int ntry; /* Number of tries per URL */
int background; /* Whether we should work in background. */
int kill_longer; /* Do we reject messages with *more*
data than specified in
content-length? */
int ignore_length; /* Do we heed content-length at all? */
int recursive; /* Are we recursive? */
int spanhost; /* Do we span across hosts in
recursion? */
int relative_only; /* Follow only relative links. */
int no_parent; /* Restrict access to the parent
directory. */
int simple_check; /* Should we use simple checking
(strcmp) or do we create a host
hash and call gethostbyname? */
int reclevel; /* Maximum level of recursion */
int dirstruct; /* Do we build the directory structure
as we go along? */
int no_dirstruct; /* Do we hate dirstruct? */
int cut_dirs; /* Number of directory components to cut. */
int add_hostdir; /* Do we add hostname directory? */
int noclobber; /* Disables clobbering of existing
data. */
char *dir_prefix; /* The top of directory tree */
char *lfilename; /* Log filename */
int no_flush; /* If non-zero, inhibit flushing log. */
char *input_filename; /* Input filename */
int force_html; /* Is the input file an HTML file? */
int spider; /* Is Wget in spider mode? */
char **accepts; /* List of patterns to accept. */
char **rejects; /* List of patterns to reject. */
char **excludes; /* List of excluded FTP directories. */
char **includes; /* List of FTP directories to
follow. */
char **domains; /* See host.c */
char **exclude_domains;
int follow_ftp; /* Are FTP URL-s followed in recursive
retrieving? */
int retr_symlinks; /* Whether we retrieve symlinks in
FTP. */
char *output_document; /* The output file to which the
documents will be printed. */
FILE *dfp; /* The file pointer to the output
document. */
int always_rest; /* Always use REST. */
char *ftp_acc; /* FTP username */
char *ftp_pass; /* FTP password */
int netrc; /* Whether to read .netrc. */
int ftp_glob; /* FTP globbing */
int ftp_pasv; /* Passive FTP. */
char *http_user; /* HTTP user. */
char *http_passwd; /* HTTP password. */
char *user_header; /* User-defined header(s). */
int use_proxy; /* Do we use proxy? */
int proxy_cache; /* Do we load from proxy cache? */
char *http_proxy, *ftp_proxy;
char **no_proxy;
char *base_href;
char *proxy_user; /*oli*/
char *proxy_passwd;
#ifdef HAVE_SELECT
long timeout; /* The value of read timeout in
seconds. */
#endif
long wait; /* The wait period between retries. */
int use_robots; /* Do we heed robots.txt? */
long quota; /* Maximum number of bytes to
retrieve. */
long downloaded; /* How much we downloaded already. */
int numurls; /* Number of successfully downloaded
URLs */
int server_response; /* Do we print server response? */
int save_headers; /* Do we save headers together with
file? */
#ifdef DEBUG
int debug; /* Debugging on/off */
#endif /* DEBUG */
int timestamping; /* Whether to use time-stamping. */
int backups; /* Are backups made? */
char *useragent; /* Naughty User-Agent, which can be
set to something other than
Wget. */
int convert_links; /* Will the links be converted
locally? */
int remove_listing; /* Do we remove .listing files
generated by FTP? */
int htmlify; /* Do we HTML-ify the OS-dependent
listings? */
long dot_bytes; /* How many bytes in a printing
dot. */
int dots_in_line; /* How many dots in one line. */
int dot_spacing; /* How many dots between spacings. */
int delete_after; /* Whether the files will be deleted
after download. */
};
#ifndef OPTIONS_DEFINED_HERE
extern struct options opt;
#endif

102
src/rbuf.c Normal file
View File

@ -0,0 +1,102 @@
/* Buffering read.
Copyright (C) 1995, 1996, 1997, 1998 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 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This is a simple implementation of buffering IO-read functions. */
#include <config.h>
#include <stdio.h>
#include "wget.h"
#include "rbuf.h"
#include "connect.h"
void
rbuf_initialize (struct rbuf *rbuf, int fd)
{
rbuf->fd = fd;
rbuf->buffer_pos = rbuf->buffer;
rbuf->buffer_left = 0;
}
int
rbuf_initialized_p (struct rbuf *rbuf)
{
return rbuf->fd != -1;
}
void
rbuf_uninitialize (struct rbuf *rbuf)
{
rbuf->fd = -1;
}
/* Currently unused -- see RBUF_READCHAR. */
#if 0
/* Function version of RBUF_READCHAR. */
int
rbuf_readchar (struct rbuf *rbuf, char *store)
{
return RBUF_READCHAR (rbuf, store);
}
#endif
/* Like rbuf_readchar(), only don't move the buffer position. */
int
rbuf_peek (struct rbuf *rbuf, char *store)
{
if (!rbuf->buffer_left)
{
int res;
rbuf->buffer_pos = rbuf->buffer;
rbuf->buffer_left = 0;
res = iread (rbuf->fd, rbuf->buffer, sizeof (rbuf->buffer));
if (res <= 0)
return res;
rbuf->buffer_left = res;
}
*store = *rbuf->buffer_pos;
return 1;
}
/* Flush RBUF's buffer to WHERE. Flush MAXSIZE bytes at most.
Returns the number of bytes actually copied. If the buffer is
empty, 0 is returned. */
int
rbuf_flush (struct rbuf *rbuf, char *where, int maxsize)
{
if (!rbuf->buffer_left)
return 0;
else
{
int howmuch = MINVAL (rbuf->buffer_left, maxsize);
if (where)
memcpy (where, rbuf->buffer_pos, howmuch);
rbuf->buffer_left -= howmuch;
rbuf->buffer_pos += howmuch;
return howmuch;
}
}
/* Discard any cached data in RBUF. */
void
rbuf_discard (struct rbuf *rbuf)
{
rbuf->buffer_left = 0;
rbuf->buffer_pos = rbuf->buffer;
}

70
src/rbuf.h Normal file
View File

@ -0,0 +1,70 @@
/* Declarations for rbuf.c.
Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef RBUF_H
#define RBUF_H
/* Retrieval stream */
struct rbuf
{
int fd;
char buffer[4096]; /* the input buffer */
char *buffer_pos; /* current position in the buffer */
size_t buffer_left; /* number of bytes left in the buffer:
buffer_left = buffer_end - buffer_pos */
int internal_dont_touch_this; /* used by RBUF_READCHAR macro */
};
/* Read a character from RBUF. If there is anything in the buffer,
the character is returned from the buffer. Otherwise, refill the
buffer and return the first character.
The return value is the same as with read(2). On buffered read,
the function returns 1.
#### That return value is totally screwed up, and is a direct
result of historical implementation of header code. The macro
should return the character or EOF, and in case of error store it
to rbuf->err or something. */
#define RBUF_READCHAR(rbuf, store) \
((rbuf)->buffer_left \
? (--(rbuf)->buffer_left, \
*((char *) (store)) = *(rbuf)->buffer_pos++, 1) \
: ((rbuf)->buffer_pos = (rbuf)->buffer, \
((((rbuf)->internal_dont_touch_this \
= iread ((rbuf)->fd, (rbuf)->buffer, \
sizeof ((rbuf)->buffer))) <= 0) \
? (rbuf)->internal_dont_touch_this \
: ((rbuf)->buffer_left = (rbuf)->internal_dont_touch_this - 1, \
*((char *) (store)) = *(rbuf)->buffer_pos++, \
1))))
/* Return the file descriptor of RBUF. */
#define RBUF_FD(rbuf) ((rbuf)->fd)
/* Function declarations */
void rbuf_initialize PARAMS ((struct rbuf *, int));
int rbuf_initialized_p PARAMS ((struct rbuf *));
void rbuf_uninitialize PARAMS ((struct rbuf *));
int rbuf_readchar PARAMS ((struct rbuf *, char *));
int rbuf_peek PARAMS ((struct rbuf *, char *));
int rbuf_flush PARAMS ((struct rbuf *, char *, int));
void rbuf_discard PARAMS ((struct rbuf *));
#endif /* RBUF_H */

820
src/recur.c Normal file
View File

@ -0,0 +1,820 @@
/* Handling of recursive HTTP retrieving.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <sys/types.h>
#include "wget.h"
#include "url.h"
#include "recur.h"
#include "utils.h"
#include "retr.h"
#include "ftp.h"
#include "fnmatch.h"
#include "host.h"
extern char *version_string;
#define ROBOTS_FILENAME "robots.txt"
/* #### Many of these lists should really be hashtables! */
/* List of downloaded URLs. */
static urlpos *urls_downloaded;
/* List of HTML URLs. */
static slist *urls_html;
/* List of undesirable-to-load URLs. */
static slist *ulist;
/* List of forbidden locations. */
static char **forbidden = NULL;
/* Current recursion depth. */
static int depth;
/* Base directory we're recursing from (used by no_parent). */
static char *base_dir;
/* The host name for which we last checked robots. */
static char *robots_host;
static int first_time = 1;
/* Construct the robots URL. */
static struct urlinfo *robots_url PARAMS ((const char *, const char *));
static uerr_t retrieve_robots PARAMS ((const char *, const char *));
static char **parse_robots PARAMS ((const char *));
static int robots_match PARAMS ((struct urlinfo *, char **));
/* Cleanup the data structures associated with recursive retrieving
(the variables above). */
void
recursive_cleanup (void)
{
free_slist (ulist);
ulist = NULL;
free_vec (forbidden);
forbidden = NULL;
free_slist (urls_html);
urls_html = NULL;
free_urlpos (urls_downloaded);
urls_downloaded = NULL;
FREE_MAYBE (base_dir);
FREE_MAYBE (robots_host);
first_time = 1;
}
/* Reset FIRST_TIME to 1, so that some action can be taken in
recursive_retrieve(). */
void
recursive_reset (void)
{
first_time = 1;
}
/* The core of recursive retrieving. Endless recursion is avoided by
having all URL-s stored to a linked list of URL-s, which is checked
before loading any URL. That way no URL can get loaded twice.
The function also supports specification of maximum recursion depth
and a number of other goodies. */
uerr_t
recursive_retrieve (const char *file, const char *this_url)
{
char *constr, *filename, *newloc;
char *canon_this_url = NULL;
int dt, inl;
int this_url_ftp; /* See below the explanation */
uerr_t err;
struct urlinfo *rurl;
urlpos *url_list, *cur_url;
char *rfile; /* For robots */
struct urlinfo *u;
assert (this_url != NULL);
assert (file != NULL);
/* If quota was exceeded earlier, bail out. */
if (opt.quota && (opt.downloaded > opt.quota))
return QUOTEXC;
/* Cache the current URL in the list. */
if (first_time)
{
ulist = add_slist (ulist, this_url, 0);
urls_downloaded = NULL;
urls_html = NULL;
/* Enter this_url to the slist, in original and "enhanced" form. */
u = newurl ();
err = parseurl (this_url, u, 0);
if (err == URLOK)
{
ulist = add_slist (ulist, u->url, 0);
urls_downloaded = add_url (urls_downloaded, u->url, file);
urls_html = add_slist (urls_html, file, NOSORT);
if (opt.no_parent)
base_dir = xstrdup (u->dir); /* Set the base dir. */
/* Set the canonical this_url to be sent as referer. This
problem exists only when running the first time. */
canon_this_url = xstrdup (u->url);
}
else
{
DEBUGP (("Double yuck! The *base* URL is broken.\n"));
base_dir = NULL;
}
freeurl (u, 1);
depth = 1;
robots_host = NULL;
forbidden = NULL;
first_time = 0;
}
else
++depth;
/* Bail out if opt.reclevel is exceeded. */
if ((opt.reclevel != 0) && (depth > opt.reclevel))
{
DEBUGP (("Recursion depth %d exceeded max. depth %d.\n",
depth, opt.reclevel));
--depth;
return RECLEVELEXC;
}
/* Determine whether this_url is an FTP URL. If it is, it means
that the retrieval is done through proxy. In that case, FTP
links will be followed by default and recursion will not be
turned off when following them. */
this_url_ftp = (urlproto (this_url) == URLFTP);
/* Get the URL-s from an HTML file: */
url_list = get_urls_html (file,
canon_this_url ? canon_this_url : this_url, 0);
/* Decide what to do with each of the URLs. A URL will be loaded if
it meets several requirements, discussed later. */
for (cur_url = url_list; cur_url; cur_url = cur_url->next)
{
/* If quota was exceeded earlier, bail out. */
if (opt.quota && (opt.downloaded > opt.quota))
break;
/* Parse the URL for convenient use in other functions, as well
as to get the optimized form. It also checks URL integrity. */
u = newurl ();
if (parseurl (cur_url->url, u, 0) != URLOK)
{
DEBUGP (("Yuck! A bad URL.\n"));
freeurl (u, 1);
continue;
}
if (u->proto == URLFILE)
{
DEBUGP (("Nothing to do with file:// around here.\n"));
freeurl (u, 1);
continue;
}
assert (u->url != NULL);
constr = xstrdup (u->url);
/* Several checkings whether a file is acceptable to load:
1. check if URL is ftp, and we don't load it
2. check for relative links (if relative_only is set)
3. check for domain
4. check for no-parent
5. check for excludes && includes
6. check for suffix
7. check for same host (if spanhost is unset), with possible
gethostbyname baggage
8. check for robots.txt
Addendum: If the URL is FTP, and it is to be loaded, only the
domain and suffix settings are "stronger".
Note that .html and (yuck) .htm will get loaded
regardless of suffix rules (but that is remedied later with
unlink).
More time- and memory- consuming tests should be put later on
the list. */
/* inl is set if the URL we are working on (constr) is stored in
ulist. Using it is crucial to avoid the incessant calls to
in_slist, which is quite slow. */
inl = in_slist (ulist, constr);
/* If it is FTP, and FTP is not followed, chuck it out. */
if (!inl)
if (u->proto == URLFTP && !opt.follow_ftp && !this_url_ftp)
{
DEBUGP (("Uh, it is FTP but i'm not in the mood to follow FTP.\n"));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
/* If it is absolute link and they are not followed, chuck it
out. */
if (!inl && u->proto != URLFTP)
if (opt.relative_only && !(cur_url->flags & URELATIVE))
{
DEBUGP (("It doesn't really look like a relative link.\n"));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
/* If its domain is not to be accepted/looked-up, chuck it out. */
if (!inl)
if (!accept_domain (u))
{
DEBUGP (("I don't like the smell of that domain.\n"));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
/* Check for parent directory. */
if (!inl && opt.no_parent
/* If the new URL is FTP and the old was not, ignore
opt.no_parent. */
&& !(!this_url_ftp && u->proto == URLFTP))
{
/* Check for base_dir first. */
if (!(base_dir && frontcmp (base_dir, u->dir)))
{
/* Failing that, check for parent dir. */
struct urlinfo *ut = newurl ();
if (parseurl (this_url, ut, 0) != URLOK)
DEBUGP (("Double yuck! The *base* URL is broken.\n"));
else if (!frontcmp (ut->dir, u->dir))
{
/* Failing that too, kill the URL. */
DEBUGP (("Trying to escape parental guidance with no_parent on.\n"));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
freeurl (ut, 1);
}
}
/* If the file does not match the acceptance list, or is on the
rejection list, chuck it out. The same goes for the
directory exclude- and include- lists. */
if (!inl && (opt.includes || opt.excludes))
{
if (!accdir (u->dir, ALLABS))
{
DEBUGP (("%s (%s) is excluded/not-included.\n", constr, u->dir));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
}
if (!inl)
{
char *suf = NULL;
/* We check for acceptance/rejection rules only for non-HTML
documents. Since we don't know whether they really are
HTML, it will be deduced from (an OR-ed list):
1) u->file is "" (meaning it is a directory)
2) suffix exists, AND:
a) it is "html", OR
b) it is "htm"
If the file *is* supposed to be HTML, it will *not* be
subject to acc/rej rules. That's why the `!'. */
if (!
(!*u->file
|| (((suf = suffix (constr)) != NULL)
&& (!strcmp (suf, "html") || !strcmp (suf, "htm")))))
{
if (!acceptable (u->file))
{
DEBUGP (("%s (%s) does not match acc/rej rules.\n",
constr, u->file));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
}
FREE_MAYBE (suf);
}
/* Optimize the URL (which includes possible DNS lookup) only
after all other possibilities have been exhausted. */
if (!inl)
{
if (!opt.simple_check)
opt_url (u);
else
{
char *p;
/* Just lowercase the hostname. */
for (p = u->host; *p; p++)
*p = tolower (*p);
free (u->url);
u->url = str_url (u, 0);
}
free (constr);
constr = xstrdup (u->url);
inl = in_slist (ulist, constr);
if (!inl && !((u->proto == URLFTP) && !this_url_ftp))
if (!opt.spanhost && this_url && !same_host (this_url, constr))
{
DEBUGP (("This is not the same hostname as the parent's.\n"));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
}
/* What about robots.txt? */
if (!inl && opt.use_robots && u->proto == URLHTTP)
{
/* Since Wget knows about only one set of robot rules at a
time, /robots.txt must be reloaded whenever a new host is
accessed.
robots_host holds the host the current `forbid' variable
is assigned to. */
if (!robots_host || !same_host (robots_host, u->host))
{
FREE_MAYBE (robots_host);
/* Now make robots_host the new host, no matter what the
result will be. So if there is no /robots.txt on the
site, Wget will not retry getting robots all the
time. */
robots_host = xstrdup (u->host);
free_vec (forbidden);
forbidden = NULL;
err = retrieve_robots (constr, ROBOTS_FILENAME);
if (err == ROBOTSOK)
{
rurl = robots_url (constr, ROBOTS_FILENAME);
rfile = url_filename (rurl);
forbidden = parse_robots (rfile);
freeurl (rurl, 1);
free (rfile);
}
}
/* Now that we have (or don't have) robots, we can check for
them. */
if (!robots_match (u, forbidden))
{
DEBUGP (("Stuffing %s because %s forbids it.\n", this_url,
ROBOTS_FILENAME));
ulist = add_slist (ulist, constr, 0);
inl = 1;
}
}
filename = NULL;
/* If it wasn't chucked out, do something with it. */
if (!inl)
{
DEBUGP (("I've decided to load it -> "));
/* Add it to the list of already-loaded URL-s. */
ulist = add_slist (ulist, constr, 0);
/* Automatically followed FTPs will *not* be downloaded
recursively. */
if (u->proto == URLFTP)
{
/* Don't you adore side-effects? */
opt.recursive = 0;
}
/* Reset its type. */
dt = 0;
/* Retrieve it. */
retrieve_url (constr, &filename, &newloc,
canon_this_url ? canon_this_url : this_url, &dt);
if (u->proto == URLFTP)
{
/* Restore... */
opt.recursive = 1;
}
if (newloc)
{
free (constr);
constr = newloc;
}
/* In case of convert_links: If there was no error, add it to
the list of downloaded URLs. We might need it for
conversion. */
if (opt.convert_links && filename)
{
if (dt & RETROKF)
{
urls_downloaded = add_url (urls_downloaded, constr, filename);
/* If the URL is HTML, note it. */
if (dt & TEXTHTML)
urls_html = add_slist (urls_html, filename, NOSORT);
}
}
/* If there was no error, and the type is text/html, parse
it recursively. */
if (dt & TEXTHTML)
{
if (dt & RETROKF)
recursive_retrieve (filename, constr);
}
else
DEBUGP (("%s is not text/html so we don't chase.\n",
filename ? filename: "(null)"));
/* If an suffix-rejected file was loaded only because it was HTML,
undo the error now */
if (opt.delete_after || (filename && !acceptable (filename)))
{
logprintf (LOG_VERBOSE,
(opt.delete_after ? _("Removing %s.\n")
: _("Removing %s since it should be rejected.\n")),
filename);
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
dt &= ~RETROKF;
}
/* If everything was OK, and links are to be converted, let's
store the local filename. */
if (opt.convert_links && (dt & RETROKF) && (filename != NULL))
{
cur_url->flags |= UABS2REL;
cur_url->local_name = xstrdup (filename);
}
}
DEBUGP (("%s already in list, so we don't load.\n", constr));
/* Free filename and constr. */
FREE_MAYBE (filename);
FREE_MAYBE (constr);
freeurl (u, 1);
/* Increment the pbuf for the appropriate size. */
}
if (opt.convert_links)
convert_links (file, url_list);
/* Free the linked list of URL-s. */
free_urlpos (url_list);
/* Free the canonical this_url. */
FREE_MAYBE (canon_this_url);
/* Decrement the recursion depth. */
--depth;
if (opt.quota && (opt.downloaded > opt.quota))
return QUOTEXC;
else
return RETROK;
}
/* Simple calls to convert_links will often fail because only the
downloaded files are converted, and Wget cannot know which files
will be converted in the future. So, if we have file fileone.html
with:
<a href=/c/something.gif>
and /c/something.gif was not downloaded because it exceeded the
recursion depth, the reference will *not* be changed.
However, later we can encounter /c/something.gif from an "upper"
level HTML (let's call it filetwo.html), and it gets downloaded.
But now we have a problem because /c/something.gif will be
correctly transformed in filetwo.html, but not in fileone.html,
since Wget could not have known that /c/something.gif will be
downloaded in the future.
This is why Wget must, after the whole retrieval, call
convert_all_links to go once more through the entire list of
retrieved HTML-s, and re-convert them.
All the downloaded HTMLs are kept in urls_html, and downloaded URLs
in urls_downloaded. From these two lists information is
extracted. */
void
convert_all_links (void)
{
uerr_t res;
urlpos *l1, *l2, *urls;
struct urlinfo *u;
slist *html;
urlpos *urlhtml;
for (html = urls_html; html; html = html->next)
{
DEBUGP (("Rescanning %s\n", html->string));
/* Determine the URL of the HTML file. get_urls_html will need
it. */
for (urlhtml = urls_downloaded; urlhtml; urlhtml = urlhtml->next)
if (!strcmp (urlhtml->local_name, html->string))
break;
if (urlhtml)
DEBUGP (("It should correspond to %s.\n", urlhtml->url));
else
DEBUGP (("I cannot find the corresponding URL.\n"));
/* Parse the HTML file... */
urls = get_urls_html (html->string, urlhtml ? urlhtml->url : NULL, 1);
if (!urls)
continue;
for (l1 = urls; l1; l1 = l1->next)
{
/* The URL must be in canonical form to be compared. */
u = newurl ();
res = parseurl (l1->url, u, 0);
if (res != URLOK)
{
freeurl (u, 1);
continue;
}
/* We decide the direction of conversion according to whether
a URL was downloaded. Downloaded URLs will be converted
ABS2REL, whereas non-downloaded will be converted REL2ABS.
Note: not yet implemented; only ABS2REL works. */
for (l2 = urls_downloaded; l2; l2 = l2->next)
if (!strcmp (l2->url, u->url))
{
DEBUGP (("%s flagged for conversion, local %s\n",
l2->url, l2->local_name));
break;
}
/* Clear the flags. */
l1->flags &= ~ (UABS2REL | UREL2ABS);
/* Decide on the conversion direction. */
if (l2)
{
l1->flags |= UABS2REL;
l1->local_name = xstrdup (l2->local_name);
}
else
{
l1->flags |= UREL2ABS;
l1->local_name = NULL;
}
freeurl (u, 1);
}
/* Convert the links in the file. */
convert_links (html->string, urls);
/* Free the data. */
free_urlpos (urls);
}
}
/* Robots support. */
/* Construct the robots URL. */
static struct urlinfo *
robots_url (const char *url, const char *robots_filename)
{
struct urlinfo *u = newurl ();
uerr_t err;
err = parseurl (url, u, 0);
assert (err == URLOK && u->proto == URLHTTP);
free (u->file);
free (u->dir);
free (u->url);
u->dir = xstrdup ("");
u->file = xstrdup (robots_filename);
u->url = str_url (u, 0);
return u;
}
/* Retrieves the robots_filename from the root server directory, if
possible. Returns ROBOTSOK if robots were retrieved OK, and
NOROBOTS if robots could not be retrieved for any reason. */
static uerr_t
retrieve_robots (const char *url, const char *robots_filename)
{
int dt;
uerr_t err;
struct urlinfo *u;
u = robots_url (url, robots_filename);
logputs (LOG_VERBOSE, _("Loading robots.txt; please ignore errors.\n"));
err = retrieve_url (u->url, NULL, NULL, NULL, &dt);
freeurl (u, 1);
if (err == RETROK)
return ROBOTSOK;
else
return NOROBOTS;
}
/* Parse the robots_filename and return the disallowed path components
in a malloc-ed vector of character pointers.
It should be fully compliant with the syntax as described in the
file norobots.txt, adopted by the robots mailing list
(robots@webcrawler.com). */
static char **
parse_robots (const char *robots_filename)
{
FILE *fp;
char **entries;
char *line, *cmd, *str, *p;
char *base_version, *version;
int len, num, i;
int wget_matched; /* is the part meant for Wget? */
entries = NULL;
num = 0;
fp = fopen (robots_filename, "rb");
if (!fp)
return NULL;
/* Kill version number. */
if (opt.useragent)
{
STRDUP_ALLOCA (base_version, opt.useragent);
STRDUP_ALLOCA (version, opt.useragent);
}
else
{
int len = 10 + strlen (version_string);
base_version = (char *)alloca (len);
sprintf (base_version, "Wget/%s", version_string);
version = (char *)alloca (len);
sprintf (version, "Wget/%s", version_string);
}
for (p = version; *p; p++)
*p = tolower (*p);
for (p = base_version; *p && *p != '/'; p++)
*p = tolower (*p);
*p = '\0';
/* Setting this to 1 means that Wget considers itself under
restrictions by default, even if the User-Agent field is not
present. However, if it finds the user-agent set to anything
other than Wget, the rest will be ignored (up to the following
User-Agent field). Thus you may have something like:
Disallow: 1
Disallow: 2
User-Agent: stupid-robot
Disallow: 3
Disallow: 4
User-Agent: Wget*
Disallow: 5
Disallow: 6
User-Agent: *
Disallow: 7
In this case the 1, 2, 5, 6 and 7 disallow lines will be
stored. */
wget_matched = 1;
while ((line = read_whole_line (fp)))
{
len = strlen (line);
/* Destroy <CR> if there is one. */
if (len && line[len - 1] == '\r')
line[len - 1] = '\0';
/* According to specifications, optional space may be at the
end... */
DEBUGP (("Line: %s\n", line));
/* Skip spaces. */
for (cmd = line; *cmd && ISSPACE (*cmd); cmd++);
if (!*cmd)
{
free (line);
DEBUGP (("(chucked out)\n"));
continue;
}
/* Look for ':'. */
for (str = cmd; *str && *str != ':'; str++);
if (!*str)
{
free (line);
DEBUGP (("(chucked out)\n"));
continue;
}
/* Zero-terminate the command. */
*str++ = '\0';
/* Look for the string beginning... */
for (; *str && ISSPACE (*str); str++);
/* Look for comments and kill them off. */
for (p = str; *p; p++)
if (*p && ISSPACE (*p) && *(p + 1) == '#')
{
/* We have found a shell-style comment `<sp>+ #'. Now
rewind to the beginning of the spaces and place '\0'
there. */
while (p > str && ISSPACE (*p))
--p;
if (p == str)
*p = '\0';
else
*(p + 1) = '\0';
break;
}
if (!strcasecmp (cmd, "User-agent"))
{
int match = 0;
/* Lowercase the agent string. */
for (p = str; *p; p++)
*p = tolower (*p);
/* If the string is `*', it matches. */
if (*str == '*' && !*(str + 1))
match = 1;
else
{
/* If the string contains wildcards, we'll run it through
fnmatch(). */
if (has_wildcards_p (str))
{
/* If the string contains '/', compare with the full
version. Else, compare it to base_version. */
if (strchr (str, '/'))
match = !fnmatch (str, version, 0);
else
match = !fnmatch (str, base_version, 0);
}
else /* Substring search */
{
if (strstr (version, str))
match = 1;
else
match = 0;
}
}
/* If Wget is not matched, skip all the entries up to the
next User-agent field. */
wget_matched = match;
}
else if (!wget_matched)
{
free (line);
DEBUGP (("(chucking out since it is not applicable for Wget)\n"));
continue;
}
else if (!strcasecmp (cmd, "Disallow"))
{
/* If "Disallow" is empty, the robot is welcome. */
if (!*str)
{
free_vec (entries);
entries = (char **)xmalloc (sizeof (char *));
*entries = NULL;
num = 0;
}
else
{
entries = (char **)xrealloc (entries, (num + 2)* sizeof (char *));
entries[num] = xstrdup (str);
entries[++num] = NULL;
/* Strip trailing spaces, according to specifications. */
for (i = strlen (str); i >= 0 && ISSPACE (str[i]); i--)
if (ISSPACE (str[i]))
str[i] = '\0';
}
}
else
{
/* unknown command */
DEBUGP (("(chucked out)\n"));
}
free (line);
}
fclose (fp);
return entries;
}
/* May the URL url be loaded according to disallowing rules stored in
forbidden? */
static int
robots_match (struct urlinfo *u, char **forbidden)
{
int l;
if (!forbidden)
return 1;
DEBUGP (("Matching %s against: ", u->path));
for (; *forbidden; forbidden++)
{
DEBUGP (("%s ", *forbidden));
l = strlen (*forbidden);
/* If dir is forbidden, we may not load the file. */
if (strncmp (u->path, *forbidden, l) == 0)
{
DEBUGP (("matched.\n"));
return 0; /* Matches, i.e. does not load... */
}
}
DEBUGP (("not matched.\n"));
return 1;
}

29
src/recur.h Normal file
View File

@ -0,0 +1,29 @@
/* Declarations for recur.c.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef RECUR_H
#define RECUR_H
void recursive_cleanup PARAMS ((void));
void recursive_reset PARAMS ((void));
uerr_t recursive_retrieve PARAMS ((const char *, const char *));
void convert_all_links PARAMS ((void));
#endif /* RECUR_H */

484
src/retr.c Normal file
View File

@ -0,0 +1,484 @@
/* File retrieval.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <errno.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif /* HAVE_STRING_H */
#include <ctype.h>
#include <assert.h>
#include "wget.h"
#include "utils.h"
#include "retr.h"
#include "url.h"
#include "recur.h"
#include "ftp.h"
#include "host.h"
#include "connect.h"
/* Internal variables used by the timer. */
static long internal_secs, internal_msecs;
void logflush PARAMS ((void));
/* From http.c. */
uerr_t http_loop PARAMS ((struct urlinfo *, char **, int *));
/* Flags for show_progress(). */
enum spflags { SP_NONE, SP_INIT, SP_FINISH };
static int show_progress PARAMS ((long, long, enum spflags));
/* Reads the contents of file descriptor FD, until it is closed, or a
read error occurs. The data is read in 8K chunks, and stored to
stream fp, which should have been open for writing. If BUF is
non-NULL and its file descriptor is equal to FD, flush RBUF first.
This function will *not* use the rbuf_* functions!
The EXPECTED argument is passed to show_progress() unchanged, but
otherwise ignored.
If opt.verbose is set, the progress is also shown. RESTVAL
represents a value from which to start downloading (which will be
shown accordingly). If RESTVAL is non-zero, the stream should have
been open for appending.
The function exits and returns codes of 0, -1 and -2 if the
connection was closed, there was a read error, or if it could not
write to the output stream, respectively.
IMPORTANT: The function flushes the contents of the buffer in
rbuf_flush() before actually reading from fd. If you wish to read
from fd immediately, flush or discard the buffer. */
int
get_contents (int fd, FILE *fp, long *len, long restval, long expected,
struct rbuf *rbuf)
{
int res;
static char c[8192];
*len = restval;
if (opt.verbose)
show_progress (restval, expected, SP_INIT);
if (rbuf && RBUF_FD (rbuf) == fd)
{
while ((res = rbuf_flush (rbuf, c, sizeof (c))) != 0)
{
if (fwrite (c, sizeof (char), res, fp) < res)
return -2;
if (opt.verbose)
{
if (show_progress (res, expected, SP_NONE))
fflush (fp);
}
*len += res;
}
}
/* Read from fd while there is available data. */
do
{
res = iread (fd, c, sizeof (c));
if (res > 0)
{
if (fwrite (c, sizeof (char), res, fp) < res)
return -2;
if (opt.verbose)
{
if (show_progress (res, expected, SP_NONE))
fflush (fp);
}
*len += res;
}
} while (res > 0);
if (res < -1)
res = -1;
if (opt.verbose)
show_progress (0, expected, SP_FINISH);
return res;
}
static void
print_percentage (long bytes, long expected)
{
int percentage = (int)(100.0 * bytes / expected);
logprintf (LOG_VERBOSE, " [%3d%%]", percentage);
}
/* Show the dotted progress report of file loading. Called with
length and a flag to tell it whether to reset or not. It keeps the
offset information in static local variables.
Return value: 1 or 0, designating whether any dots have been drawn.
If the init argument is set, the routine will initialize.
If the res is non-zero, res/line_bytes lines are skipped
(meaning the appropriate number ok kilobytes), and the number of
"dots" fitting on the first line are drawn as ','. */
static int
show_progress (long res, long expected, enum spflags flags)
{
static long line_bytes;
static long offs;
static int ndot, nrow;
int any_output = 0;
if (flags == SP_FINISH)
{
if (expected)
{
int dot = ndot;
char *tmpstr = (char *)alloca (2 * opt.dots_in_line + 1);
char *tmpp = tmpstr;
for (; dot < opt.dots_in_line; dot++)
{
if (!(dot % opt.dot_spacing))
*tmpp++ = ' ';
*tmpp++ = ' ';
}
*tmpp = '\0';
logputs (LOG_VERBOSE, tmpstr);
print_percentage (nrow * line_bytes + ndot * opt.dot_bytes + offs,
expected);
}
logputs (LOG_VERBOSE, "\n\n");
return 0;
}
/* Temporarily disable flushing. */
opt.no_flush = 1;
/* init set means initialization. If res is set, it also means that
the retrieval is *not* done from the beginning. The part that
was already retrieved is not shown again. */
if (flags == SP_INIT)
{
/* Generic initialization of static variables. */
offs = 0L;
ndot = nrow = 0;
line_bytes = (long)opt.dots_in_line * opt.dot_bytes;
if (res)
{
if (res >= line_bytes)
{
nrow = res / line_bytes;
res %= line_bytes;
logprintf (LOG_VERBOSE,
_("\n [ skipping %dK ]"),
(int) ((nrow * line_bytes) / 1024));
ndot = 0;
}
}
logprintf (LOG_VERBOSE, "\n%5ldK ->", nrow * line_bytes / 1024);
}
/* Offset gets incremented by current value. */
offs += res;
/* While offset is >= opt.dot_bytes, print dots, taking care to
precede every 50th dot with a status message. */
for (; offs >= opt.dot_bytes; offs -= opt.dot_bytes)
{
if (!(ndot % opt.dot_spacing))
logputs (LOG_VERBOSE, " ");
any_output = 1;
logputs (LOG_VERBOSE, flags == SP_INIT ? "," : ".");
++ndot;
if (ndot == opt.dots_in_line)
{
ndot = 0;
++nrow;
if (expected)
print_percentage (nrow * line_bytes, expected);
logprintf (LOG_VERBOSE, "\n%5ldK ->", nrow * line_bytes / 1024);
}
}
/* Reenable flushing. */
opt.no_flush = 0;
if (any_output)
/* Force flush. #### Oh, what a kludge! */
logflush ();
return any_output;
}
/* Reset the internal timer. */
void
reset_timer (void)
{
#ifdef HAVE_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
internal_secs = t.tv_sec;
internal_msecs = t.tv_usec / 1000;
#else
internal_secs = time (NULL);
internal_msecs = 0;
#endif
}
/* Return the time elapsed from the last call to reset_timer(), in
milliseconds. */
long
elapsed_time (void)
{
#ifdef HAVE_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
return ((t.tv_sec - internal_secs) * 1000
+ (t.tv_usec / 1000 - internal_msecs));
#else
return 1000 * ((long)time (NULL) - internal_secs);
#endif
}
/* Print out the appropriate download rate. Appropriate means that if
rate is > 1024 bytes per second, kilobytes are used, and if rate >
1024 * 1024 bps, megabytes are used. */
char *
rate (long bytes, long msecs)
{
static char res[15];
double dlrate;
if (!msecs)
++msecs;
dlrate = (double)1000 * bytes / msecs;
/* #### Should these strings be translatable? */
if (dlrate < 1024.0)
sprintf (res, "%.2f B/s", dlrate);
else if (dlrate < 1024.0 * 1024.0)
sprintf (res, "%.2f KB/s", dlrate / 1024.0);
else
sprintf (res, "%.2f MB/s", dlrate / (1024.0 * 1024.0));
return res;
}
#define USE_PROXY_P(u) (opt.use_proxy && getproxy((u)->proto) \
&& no_proxy_match((u)->host, \
(const char **)opt.no_proxy))
/* Retrieve the given URL. Decides which loop to call -- HTTP, FTP,
or simply copy it with file:// (#### the latter not yet
implemented!). */
uerr_t
retrieve_url (const char *origurl, char **file, char **newloc,
const char *refurl, int *dt)
{
uerr_t result;
char *url;
int location_changed, already_redirected, dummy;
int local_use_proxy;
char *mynewloc, *proxy;
struct urlinfo *u;
/* If dt is NULL, just ignore it. */
if (!dt)
dt = &dummy;
url = xstrdup (origurl);
if (newloc)
*newloc = NULL;
if (file)
*file = NULL;
already_redirected = 0;
again:
u = newurl ();
/* Parse the URL. RFC2068 requires `Location' to contain an
absoluteURI, but many sites break this requirement. #### We
should be liberal and accept a relative location, too. */
result = parseurl (url, u, already_redirected);
if (result != URLOK)
{
freeurl (u, 1);
logprintf (LOG_NOTQUIET, "%s: %s.\n", url, uerrmsg (result));
return result;
}
/* Set the referer. */
if (refurl)
u->referer = xstrdup (refurl);
else
u->referer = NULL;
local_use_proxy = USE_PROXY_P (u);
if (local_use_proxy)
{
struct urlinfo *pu = newurl ();
/* Copy the original URL to new location. */
memcpy (pu, u, sizeof (*u));
pu->proxy = NULL; /* A minor correction :) */
/* Initialize u to nil. */
memset (u, 0, sizeof (*u));
u->proxy = pu;
/* Get the appropriate proxy server, appropriate for the
current protocol. */
proxy = getproxy (pu->proto);
if (!proxy)
{
logputs (LOG_NOTQUIET, _("Could not find proxy host.\n"));
freeurl (u, 1);
return PROXERR;
}
/* Parse the proxy URL. */
result = parseurl (proxy, u, 0);
if (result != URLOK || u->proto != URLHTTP)
{
if (u->proto == URLHTTP)
logprintf (LOG_NOTQUIET, "Proxy %s: %s.\n", proxy, uerrmsg (result));
else
logprintf (LOG_NOTQUIET, _("Proxy %s: Must be HTTP.\n"), proxy);
freeurl (u, 1);
return PROXERR;
}
u->proto = URLHTTP;
}
assert (u->proto != URLFILE); /* #### Implement me! */
mynewloc = NULL;
if (u->proto == URLHTTP)
result = http_loop (u, &mynewloc, dt);
else if (u->proto == URLFTP)
{
/* If this is a redirection, we must not allow recursive FTP
retrieval, so we save recursion to oldrec, and restore it
later. */
int oldrec = opt.recursive;
if (already_redirected)
opt.recursive = 0;
result = ftp_loop (u, dt);
opt.recursive = oldrec;
/* There is a possibility of having HTTP being redirected to
FTP. In these cases we must decide whether the text is HTML
according to the suffix. The HTML suffixes are `.html' and
`.htm', case-insensitive.
#### All of this is, of course, crap. These types should be
determined through mailcap. */
if (already_redirected && u->local && (u->proto == URLFTP ))
{
char *suf = suffix (u->local);
if (suf && (!strcasecmp (suf, "html") || !strcasecmp (suf, "htm")))
*dt |= TEXTHTML;
FREE_MAYBE (suf);
}
}
location_changed = (result == NEWLOCATION);
if (location_changed)
{
/* Check for redirection to oneself. */
if (url_equal (url, mynewloc))
{
logprintf (LOG_NOTQUIET, _("%s: Redirection to itself.\n"),
mynewloc);
return WRONGCODE;
}
if (mynewloc)
{
free (url);
url = mynewloc;
}
freeurl (u, 1);
already_redirected = 1;
goto again;
}
if (file)
{
if (u->local)
*file = xstrdup (u->local);
else
*file = NULL;
}
freeurl (u, 1);
if (newloc)
*newloc = url;
else
free (url);
return result;
}
/* Find the URL-s in the file and call retrieve_url() for each of
them. If HTML is non-zero, treat the file as HTML, and construct
the URL-s accordingly.
If opt.recursive is set, call recursive_retrieve() for each file. */
uerr_t
retrieve_from_file (const char *file, int html, int *count)
{
uerr_t status;
urlpos *url_list, *cur_url;
/* If spider-mode is on, we do not want get_urls_html barfing
errors on baseless links. */
url_list = (html ? get_urls_html (file, NULL, opt.spider)
: get_urls_file (file));
status = RETROK; /* Suppose everything is OK. */
*count = 0; /* Reset the URL count. */
recursive_reset ();
for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count)
{
char *filename, *new_file;
int dt;
if (opt.quota && opt.downloaded > opt.quota)
{
status = QUOTEXC;
break;
}
status = retrieve_url (cur_url->url, &filename, &new_file, NULL, &dt);
if (opt.recursive && status == RETROK && (dt & TEXTHTML))
status = recursive_retrieve (filename, new_file ? new_file : cur_url->url);
if (filename && opt.delete_after && file_exists_p (filename))
{
logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
dt &= ~RETROKF;
}
FREE_MAYBE (new_file);
FREE_MAYBE (filename);
}
/* Free the linked list of URL-s. */
free_urlpos (url_list);
return status;
}
/* Print `giving up', or `retrying', depending on the impending
action. N1 and N2 are the attempt number and the attempt limit. */
void
printwhat (int n1, int n2)
{
logputs (LOG_VERBOSE, (n1 == n2) ? _("Giving up.\n\n") : _("Retrying.\n\n"));
}

37
src/retr.h Normal file
View File

@ -0,0 +1,37 @@
/* Declarations for retr.c.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef RETR_H
#define RETR_H
#include "rbuf.h"
int get_contents PARAMS ((int, FILE *, long *, long, long, struct rbuf *));
uerr_t retrieve_url PARAMS ((const char *, char **, char **,
const char *, int *));
uerr_t retrieve_from_file PARAMS ((const char *, int, int *));
void reset_timer PARAMS ((void));
long elapsed_time PARAMS ((void));
char *rate PARAMS ((long, long));
void printwhat PARAMS ((int, int));
#endif /* RETR_H */

155
src/sysdep.h Normal file
View File

@ -0,0 +1,155 @@
/* Dirty system-dependent hacks.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file is included by wget.h. Random .c files need not include
it. */
#ifndef SYSDEP_H
#define SYSDEP_H
/* We need these to be playing with various stuff. */
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else /* not TIME_WITH_SYS_TIME_H */
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#else /* not HAVE_SYS_TIME_H */
# include <time.h>
#endif /* HAVE_SYS_TIME_H */
#endif /* TIME_WITH_SYS_TIME_H */
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WINDOWS
/* Windows doesn't have some functions. Include mswindows.h so we get
their declarations, as well as some additional declarations and
macros. This must come first, so it can set things up. */
#include <mswindows.h>
#endif /* WINDOWS */
/* Allegedly needed for compilation under OS/2: */
#ifdef EMXOS2
#ifndef S_ISLNK
# define S_ISLNK(m) 0
#endif
#ifndef lstat
# define lstat stat
#endif
#endif /* EMXOS2 */
/* Reportedly, stat() macros are broken on some old systems. Those
systems will have to fend for themselves, as I will not introduce
new code to handle it.
However, I will add code for *missing* macros, and the following
are missing from many systems. */
#ifndef S_ISLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & (_S_IFMT)) == (_S_IFDIR))
#endif
#ifndef S_ISREG
# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
/* Bletch! SPARC compiler doesn't define sparc (needed by
arpa/nameser.h) when in -Xc mode. Luckily, it always defines
__sparc. */
#ifdef __sparc
#ifndef sparc
#define sparc
#endif
#endif
/* mswindows.h defines these. */
#ifndef READ
# define READ(fd, buf, cnt) read ((fd), (buf), (cnt))
#endif
#ifndef WRITE
# define WRITE(fd, buf, cnt) write ((fd), (buf), (cnt))
#endif
#ifndef REALCLOSE
# define REALCLOSE(x) close (x)
#endif
#define CLOSE(x) \
do { \
REALCLOSE (x); \
DEBUGP (("Closing fd %d\n", x)); \
} while (0)
/* OK, now define a decent interface to ctype macros. The regular
ones misfire when you feed them chars >= 127, as they understand
them as "negative", which results in out-of-bound access at
table-lookup, yielding random results. This is, of course, totally
bogus. One way to "solve" this is to use `unsigned char'
everywhere, but it is nearly impossible to do that cleanly, because
all of the library functions and system calls accept `char'.
Thus we define our wrapper macros which simply cast the argument to
unsigned char before passing it to the <ctype.h> macro. These
versions are used consistently across the code. */
#define ISASCII(x) isascii ((unsigned char)(x))
#define ISALPHA(x) isalpha ((unsigned char)(x))
#define ISSPACE(x) isspace ((unsigned char)(x))
#define ISDIGIT(x) isdigit ((unsigned char)(x))
#define ISXDIGIT(x) isxdigit ((unsigned char)(x))
/* Defined in cmpt.c: */
#ifndef HAVE_STRERROR
char *strerror ();
#endif
#ifndef HAVE_STRCASECMP
int strcasecmp ();
#endif
#ifndef HAVE_STRNCASECMP
int strncasecmp ();
#endif
#ifndef HAVE_STRSTR
char *strstr ();
#endif
#ifndef HAVE_STRPTIME
char *strptime ();
#endif
/* SunOS brain damage -- for some reason, SunOS header files fail to
declare the functions below, which causes all kinds of problems
(compiling errors) with pointer arithmetic and similar.
This used to be only within `#ifdef STDC_HEADERS', but it got
tripped on other systems (AIX), thus causing havoc. Fortunately,
SunOS appears to be the only system braindamaged that badly, so I
added an extra `#ifdef sun' guard. */
#ifndef STDC_HEADERS
#ifdef sun
#ifndef __cplusplus
char *strstr ();
char *strchr ();
char *strrchr ();
char *strtok ();
char *strdup ();
void *memcpy ();
#endif /* not __cplusplus */
#endif /* sun */
#endif /* STDC_HEADERS */
#endif /* SYSDEP_H */

1500
src/url.c Normal file

File diff suppressed because it is too large Load Diff

98
src/url.h Normal file
View File

@ -0,0 +1,98 @@
/* Declarations for url.c.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef URL_H
#define URL_H
/* If the string contains unsafe characters, duplicate it with
encode_string, otherwise just copy it with strdup. */
#define CLEANDUP(x) (contains_unsafe (x) ? encode_string (x) : xstrdup (x))
/* Structure containing info on a URL. */
struct urlinfo
{
char *url; /* Unchanged URL */
uerr_t proto; /* URL protocol */
char *host; /* Extracted hostname */
unsigned short port;
char ftp_type;
char *path, *dir, *file; /* Path, as well as dir and file
(properly decoded) */
char *user, *passwd; /* Username and password */
struct urlinfo *proxy; /* The exact string to pass to proxy
server */
char *referer; /* The source from which the request
URI was obtained */
char *local; /* The local filename of the URL
document */
};
enum uflags
{
URELATIVE = 0x0001, /* Is URL relative? */
UNOPROTO = 0x0002, /* Is URL without a protocol? */
UABS2REL = 0x0004, /* Convert absolute to relative? */
UREL2ABS = 0x0008 /* Convert relative to absolute? */
};
/* A structure that defines the whereabouts of a URL, i.e. its
position in an HTML document, etc. */
typedef struct _urlpos
{
char *url; /* URL */
char *local_name; /* Local file to which it was saved */
enum uflags flags; /* Various flags */
int pos, size; /* Rekative position in the buffer */
struct _urlpos *next; /* Next struct in list */
} urlpos;
/* Function declarations */
int skip_url PARAMS ((const char *));
int contains_unsafe PARAMS ((const char *));
char *encode_string PARAMS ((const char *));
struct urlinfo *newurl PARAMS ((void));
void freeurl PARAMS ((struct urlinfo *, int));
uerr_t urlproto PARAMS ((const char *));
int skip_proto PARAMS ((const char *));
int skip_uname PARAMS ((const char *));
uerr_t parseurl PARAMS ((const char *, struct urlinfo *, int));
char *str_url PARAMS ((const struct urlinfo *, int));
int url_equal PARAMS ((const char *, const char *));
urlpos *get_urls_file PARAMS ((const char *));
urlpos *get_urls_html PARAMS ((const char *, const char *, int));
void free_urlpos PARAMS ((urlpos *));
void rotate_backups PARAMS ((const char *));
int mkalldirs PARAMS ((const char *));
char *url_filename PARAMS ((const struct urlinfo *));
void opt_url PARAMS ((struct urlinfo *));
char *getproxy PARAMS ((uerr_t));
int no_proxy_match PARAMS ((const char *, const char **));
void convert_links PARAMS ((const char *, urlpos *));
urlpos *add_url PARAMS ((urlpos *, const char *, const char *));
#endif /* URL_H */

978
src/utils.c Normal file
View File

@ -0,0 +1,978 @@
/* Various functions of utilitarian nature.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else /* not HAVE_STRING_H */
# include <strings.h>
#endif /* not HAVE_STRING_H */
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include <limits.h>
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
#ifdef HAVE_SYS_UTIME_H
# include <sys/utime.h>
#endif
#include <errno.h>
#ifdef NeXT
# include <libc.h> /* for access() */
#endif
#include "wget.h"
#include "utils.h"
#include "fnmatch.h"
#ifndef errno
extern int errno;
#endif
/* Croak the fatal memory error and bail out with non-zero exit
status. */
static void
memfatal (const char *s)
{
/* HACK: expose save_log_p from log.c, so we can turn it off in
order to prevent saving the log. Saving the log is dangerous
because logprintf() and logputs() can call malloc(), so this
could infloop. When logging is turned off, infloop can no longer
happen. */
extern int save_log_p;
save_log_p = 0;
logprintf (LOG_ALWAYS, _("%s: %s: Not enough memory.\n"), exec_name, s);
exit (1);
}
/* xmalloc, xrealloc and xstrdup exit the program if there is not
enough memory. xstrdup also implements strdup on systems that do
not have it. */
void *
xmalloc (size_t size)
{
void *res;
res = malloc (size);
if (!res)
memfatal ("malloc");
return res;
}
void *
xrealloc (void *obj, size_t size)
{
void *res;
/* Not all Un*xes have the feature of realloc() that calling it with
a NULL-pointer is the same as malloc(), but it is easy to
simulate. */
if (obj)
res = realloc (obj, size);
else
res = malloc (size);
if (!res)
memfatal ("realloc");
return res;
}
char *
xstrdup (const char *s)
{
#ifndef HAVE_STRDUP
int l = strlen (s);
char *s1 = malloc (l + 1);
if (!s1)
memfatal ("strdup");
memcpy (s1, s, l + 1);
return s1;
#else /* HAVE_STRDUP */
char *s1 = strdup (s);
if (!s1)
memfatal ("strdup");
return s1;
#endif /* HAVE_STRDUP */
}
/* Copy the string formed by two pointers (one on the beginning, other
on the char after the last char) to a new, malloc-ed location.
0-terminate it. */
char *
strdupdelim (const char *beg, const char *end)
{
char *res = (char *)xmalloc (end - beg + 1);
memcpy (res, beg, end - beg);
res[end - beg] = '\0';
return res;
}
/* Parse a string containing comma-separated elements, and return a
vector of char pointers with the elements. Spaces following the
commas are ignored. */
char **
sepstring (const char *s)
{
char **res;
const char *p;
int i = 0;
if (!s || !*s)
return NULL;
res = NULL;
p = s;
while (*s)
{
if (*s == ',')
{
res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
res[i] = strdupdelim (p, s);
res[++i] = NULL;
++s;
/* Skip the blanks following the ','. */
while (ISSPACE (*s))
++s;
p = s;
}
else
++s;
}
res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
res[i] = strdupdelim (p, s);
res[i + 1] = NULL;
return res;
}
/* Return pointer to a static char[] buffer in which zero-terminated
string-representation of TM (in form hh:mm:ss) is printed. It is
shamelessly non-reentrant, but it doesn't matter, really.
If TM is non-NULL, the time_t of the current time will be stored
there. */
char *
time_str (time_t *tm)
{
static char tms[15];
struct tm *ptm;
time_t tim;
*tms = '\0';
tim = time (tm);
if (tim == -1)
return tms;
ptm = localtime (&tim);
sprintf (tms, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return tms;
}
/* Returns an error message for ERRNUM. #### This requires more work.
This function, as well as the whole error system, is very
ill-conceived. */
const char *
uerrmsg (uerr_t errnum)
{
switch (errnum)
{
case URLUNKNOWN:
return _("Unknown/unsupported protocol");
break;
case URLBADPORT:
return _("Invalid port specification");
break;
case URLBADHOST:
return _("Invalid host name");
break;
default:
abort ();
/* $@#@#$ compiler. */
return NULL;
}
}
/* The Windows versions of the following two functions are defined in
mswindows.c. */
/* A cuserid() immitation using getpwuid(), to avoid hassling with
utmp. Besides, not all systems have cuesrid(). Under Windows, it
is defined in mswindows.c.
If WHERE is non-NULL, the username will be stored there.
Otherwise, it will be returned as a static buffer (as returned by
getpwuid()). In the latter case, the buffer should be copied
before calling getpwuid() or pwd_cuserid() again. */
#ifndef WINDOWS
char *
pwd_cuserid (char *where)
{
struct passwd *pwd;
if (!(pwd = getpwuid (getuid ())) || !pwd->pw_name)
return NULL;
if (where)
{
strcpy (where, pwd->pw_name);
return where;
}
else
return pwd->pw_name;
}
void
fork_to_background (void)
{
pid_t pid;
/* Whether we arrange our own version of opt.lfilename here. */
int changedp = 0;
if (!opt.lfilename)
{
opt.lfilename = unique_name (DEFAULT_LOGFILE);
changedp = 1;
}
pid = fork ();
if (pid < 0)
{
/* parent, error */
perror ("fork");
exit (1);
}
else if (pid != 0)
{
/* parent, no error */
printf (_("Continuing in background.\n"));
if (changedp)
printf (_("Output will be written to `%s'.\n"), opt.lfilename);
exit (0);
}
/* child: keep running */
}
#endif /* not WINDOWS */
/* Canonicalize PATH, and return a new path. The new path differs from PATH
in that:
Multple `/'s are collapsed to a single `/'.
Leading `./'s and trailing `/.'s are removed.
Trailing `/'s are removed.
Non-leading `../'s and trailing `..'s are handled by removing
portions of the path.
E.g. "a/b/c/./../d/.." will yield "a/b". This function originates
from GNU Bash.
Changes for Wget:
Always use '/' as stub_char.
Don't check for local things using canon_stat.
Change the original string instead of strdup-ing.
React correctly when beginning with `./' and `../'. */
void
path_simplify (char *path)
{
register int i, start, ddot;
char stub_char;
if (!*path)
return;
/*stub_char = (*path == '/') ? '/' : '.';*/
stub_char = '/';
/* Addition: Remove all `./'-s preceding the string. If `../'-s
precede, put `/' in front and remove them too. */
i = 0;
ddot = 0;
while (1)
{
if (path[i] == '.' && path[i + 1] == '/')
i += 2;
else if (path[i] == '.' && path[i + 1] == '.' && path[i + 2] == '/')
{
i += 3;
ddot = 1;
}
else
break;
}
if (i)
strcpy (path, path + i - ddot);
/* Replace single `.' or `..' with `/'. */
if ((path[0] == '.' && path[1] == '\0')
|| (path[0] == '.' && path[1] == '.' && path[2] == '\0'))
{
path[0] = stub_char;
path[1] = '\0';
return;
}
/* Walk along PATH looking for things to compact. */
i = 0;
while (1)
{
if (!path[i])
break;
while (path[i] && path[i] != '/')
i++;
start = i++;
/* If we didn't find any slashes, then there is nothing left to do. */
if (!path[start])
break;
/* Handle multiple `/'s in a row. */
while (path[i] == '/')
i++;
if ((start + 1) != i)
{
strcpy (path + start + 1, path + i);
i = start + 1;
}
/* Check for trailing `/'. */
if (start && !path[i])
{
zero_last:
path[--i] = '\0';
break;
}
/* Check for `../', `./' or trailing `.' by itself. */
if (path[i] == '.')
{
/* Handle trailing `.' by itself. */
if (!path[i + 1])
goto zero_last;
/* Handle `./'. */
if (path[i + 1] == '/')
{
strcpy (path + i, path + i + 1);
i = (start < 0) ? 0 : start;
continue;
}
/* Handle `../' or trailing `..' by itself. */
if (path[i + 1] == '.' &&
(path[i + 2] == '/' || !path[i + 2]))
{
while (--start > -1 && path[start] != '/');
strcpy (path + start + 1, path + i + 2);
i = (start < 0) ? 0 : start;
continue;
}
} /* path == '.' */
} /* while */
if (!*path)
{
*path = stub_char;
path[1] = '\0';
}
}
/* "Touch" FILE, i.e. make its atime and mtime equal to the time
specified with TM. */
void
touch (const char *file, time_t tm)
{
#ifdef HAVE_STRUCT_UTIMBUF
struct utimbuf times;
times.actime = times.modtime = tm;
#else
time_t times[2];
times[0] = times[1] = tm;
#endif
if (utime (file, &times) == -1)
logprintf (LOG_NOTQUIET, "utime: %s\n", strerror (errno));
}
/* Checks if FILE is a symbolic link, and removes it if it is. Does
nothing under MS-Windows. */
int
remove_link (const char *file)
{
int err = 0;
struct stat st;
if (lstat (file, &st) == 0 && S_ISLNK (st.st_mode))
{
DEBUGP (("Unlinking %s (symlink).\n", file));
err = unlink (file);
if (err != 0)
logprintf (LOG_VERBOSE, _("Failed to unlink symlink `%s': %s\n"),
file, strerror (errno));
}
return err;
}
/* Does FILENAME exist? This is quite a lousy implementation, since
it supplies no error codes -- only a yes-or-no answer. Thus it
will return that a file does not exist if, e.g., the directory is
unreadable. I don't mind it too much currently, though. The
proper way should, of course, be to have a third, error state,
other than true/false, but that would introduce uncalled-for
additional complexity to the callers. */
int
file_exists_p (const char *filename)
{
#ifdef HAVE_ACCESS
return access (filename, F_OK) >= 0;
#else
struct stat buf;
return stat (filename, &buf) >= 0;
#endif
}
/* Returns 0 if PATH is a directory, 1 otherwise (any kind of file).
Returns 0 on error. */
int
file_non_directory_p (const char *path)
{
struct stat buf;
/* Use lstat() rather than stat() so that symbolic links pointing to
directories can be identified correctly. */
if (lstat (path, &buf) != 0)
return 0;
return S_ISDIR (buf.st_mode) ? 0 : 1;
}
/* Return a unique filename, given a prefix and count */
static char *
unique_name_1 (const char *fileprefix, int count)
{
char *filename;
if (count)
{
filename = (char *)xmalloc (strlen (fileprefix) + numdigit (count) + 2);
sprintf (filename, "%s.%d", fileprefix, count);
}
else
filename = xstrdup (fileprefix);
if (!file_exists_p (filename))
return filename;
else
{
free (filename);
return NULL;
}
}
/* Return a unique file name, based on PREFIX. */
char *
unique_name (const char *prefix)
{
char *file = NULL;
int count = 0;
while (!file)
file = unique_name_1 (prefix, count++);
return file;
}
/* Create DIRECTORY. If some of the pathname components of DIRECTORY
are missing, create them first. In case any mkdir() call fails,
return its error status. Returns 0 on successful completion.
The behaviour of this function should be identical to the behaviour
of `mkdir -p' on systems where mkdir supports the `-p' option. */
int
make_directory (const char *directory)
{
int quit = 0;
int i;
char *dir;
/* Make a copy of dir, to be able to write to it. Otherwise, the
function is unsafe if called with a read-only char *argument. */
STRDUP_ALLOCA (dir, directory);
/* If the first character of dir is '/', skip it (and thus enable
creation of absolute-pathname directories. */
for (i = (*dir == '/'); 1; ++i)
{
for (; dir[i] && dir[i] != '/'; i++)
;
if (!dir[i])
quit = 1;
dir[i] = '\0';
/* Check whether the directory already exists. */
if (!file_exists_p (dir))
{
if (mkdir (dir, 0777) < 0)
return -1;
}
if (quit)
break;
else
dir[i] = '/';
}
return 0;
}
static int in_acclist PARAMS ((const char *const *, const char *, int));
/* Determine whether a file is acceptable to be followed, according to
lists of patterns to accept/reject. */
int
acceptable (const char *s)
{
int l = strlen (s);
while (l && s[l] != '/')
--l;
if (s[l] == '/')
s += (l + 1);
if (opt.accepts)
{
if (opt.rejects)
return (in_acclist ((const char *const *)opt.accepts, s, 1)
&& !in_acclist ((const char *const *)opt.rejects, s, 1));
else
return in_acclist ((const char *const *)opt.accepts, s, 1);
}
else if (opt.rejects)
return !in_acclist ((const char *const *)opt.rejects, s, 1);
return 1;
}
/* Compare S1 and S2 frontally; S2 must begin with S1. E.g. if S1 is
`/something', frontcmp() will return 1 only if S2 begins with
`/something'. Otherwise, 0 is returned. */
int
frontcmp (const char *s1, const char *s2)
{
for (; *s1 && *s2 && (*s1 == *s2); ++s1, ++s2);
return !*s1;
}
/* Iterate through STRLIST, and return the first element that matches
S, through wildcards or front comparison (as appropriate). */
static char *
proclist (char **strlist, const char *s, enum accd flags)
{
char **x;
for (x = strlist; *x; x++)
if (has_wildcards_p (*x))
{
if (fnmatch (*x, s, FNM_PATHNAME) == 0)
break;
}
else
{
char *p = *x + ((flags & ALLABS) && (**x == '/')); /* Remove '/' */
if (frontcmp (p, s))
break;
}
return *x;
}
/* Returns whether DIRECTORY is acceptable for download, wrt the
include/exclude lists.
If FLAGS is ALLABS, the leading `/' is ignored in paths; relative
and absolute paths may be freely intermixed. */
int
accdir (const char *directory, enum accd flags)
{
/* Remove starting '/'. */
if (flags & ALLABS && *directory == '/')
++directory;
if (opt.includes)
{
if (!proclist (opt.includes, directory, flags))
return 0;
}
if (opt.excludes)
{
if (proclist (opt.excludes, directory, flags))
return 0;
}
return 1;
}
/* Match the end of STRING against PATTERN. For instance:
match_backwards ("abc", "bc") -> 1
match_backwards ("abc", "ab") -> 0
match_backwards ("abc", "abc") -> 1 */
static int
match_backwards (const char *string, const char *pattern)
{
int i, j;
for (i = strlen (string), j = strlen (pattern); i >= 0 && j >= 0; i--, j--)
if (string[i] != pattern[j])
break;
/* If the pattern was exhausted, the match was succesful. */
if (j == -1)
return 1;
else
return 0;
}
/* Checks whether string S matches each element of ACCEPTS. A list
element are matched either with fnmatch() or match_backwards(),
according to whether the element contains wildcards or not.
If the BACKWARD is 0, don't do backward comparison -- just compare
them normally. */
static int
in_acclist (const char *const *accepts, const char *s, int backward)
{
for (; *accepts; accepts++)
{
if (has_wildcards_p (*accepts))
{
/* fnmatch returns 0 if the pattern *does* match the
string. */
if (fnmatch (*accepts, s, 0) == 0)
return 1;
}
else
{
if (backward)
{
if (match_backwards (s, *accepts))
return 1;
}
else
{
if (!strcmp (s, *accepts))
return 1;
}
}
}
return 0;
}
/* Return the malloc-ed suffix of STR. For instance:
suffix ("foo.bar") -> "bar"
suffix ("foo.bar.baz") -> "baz"
suffix ("/foo/bar") -> NULL
suffix ("/foo.bar/baz") -> NULL */
char *
suffix (const char *str)
{
int i;
for (i = strlen (str); i && str[i] != '/' && str[i] != '.'; i--);
if (str[i++] == '.')
return xstrdup (str + i);
else
return NULL;
}
/* Read a line from FP. The function reallocs the storage as needed
to accomodate for any length of the line. Reallocs are done
storage exponentially, doubling the storage after each overflow to
minimize the number of calls to realloc().
It is not an exemplary of correctness, since it kills off the
newline (and no, there is no way to know if there was a newline at
EOF). */
char *
read_whole_line (FILE *fp)
{
char *line;
int i, bufsize, c;
i = 0;
bufsize = 40;
line = (char *)xmalloc (bufsize);
/* Construct the line. */
while ((c = getc (fp)) != EOF && c != '\n')
{
if (i > bufsize - 1)
line = (char *)xrealloc (line, (bufsize <<= 1));
line[i++] = c;
}
if (c == EOF && !i)
{
free (line);
return NULL;
}
/* Check for overflow at zero-termination (no need to double the
buffer in this case. */
if (i == bufsize)
line = (char *)xrealloc (line, i + 1);
line[i] = '\0';
return line;
}
/* Load file pointed to by FP to memory and return the malloc-ed
buffer with the contents. *NREAD will contain the number of read
bytes. The file is loaded in chunks, allocated exponentially,
starting with FILE_BUFFER_SIZE bytes. */
void
load_file (FILE *fp, char **buf, long *nread)
{
long bufsize;
bufsize = 512;
*nread = 0;
*buf = NULL;
while (!feof (fp) && !ferror (fp))
{
*buf = (char *)xrealloc (*buf, bufsize + *nread);
*nread += fread (*buf + *nread, sizeof (char), bufsize, fp);
bufsize <<= 1;
}
/* #### No indication of encountered error?? */
}
/* Free the pointers in a NULL-terminated vector of pointers, then
free the pointer itself. */
void
free_vec (char **vec)
{
if (vec)
{
char **p = vec;
while (*p)
free (*p++);
free (vec);
}
}
/* Append vector V2 to vector V1. The function frees V2 and
reallocates V1 (thus you may not use the contents of neither
pointer after the call). If V1 is NULL, V2 is returned. */
char **
merge_vecs (char **v1, char **v2)
{
int i, j;
if (!v1)
return v2;
if (!v2)
return v1;
if (!*v2)
{
/* To avoid j == 0 */
free (v2);
return v1;
}
/* Count v1. */
for (i = 0; v1[i]; i++);
/* Count v2. */
for (j = 0; v2[j]; j++);
/* Reallocate v1. */
v1 = (char **)xrealloc (v1, (i + j + 1) * sizeof (char **));
memcpy (v1 + i, v2, (j + 1) * sizeof (char *));
free (v2);
return v1;
}
/* A set of simple-minded routines to store and search for strings in
a linked list. You may add a string to the slist, and peek whether
it's still in there at any time later. */
/* Add an element to the list. If flags is NOSORT, the list will not
be sorted. */
slist *
add_slist (slist *l, const char *s, int flags)
{
slist *t, *old, *beg;
int cmp;
if (flags & NOSORT)
{
if (!l)
{
t = (slist *)xmalloc (sizeof (slist));
t->string = xstrdup (s);
t->next = NULL;
return t;
}
beg = l;
/* Find the last element. */
while (l->next)
l = l->next;
t = (slist *)xmalloc (sizeof (slist));
l->next = t;
t->string = xstrdup (s);
t->next = NULL;
return beg;
}
/* Empty list or changing the first element. */
if (!l || (cmp = strcmp (l->string, s)) > 0)
{
t = (slist *)xmalloc (sizeof (slist));
t->string = xstrdup (s);
t->next = l;
return t;
}
beg = l;
if (cmp == 0)
return beg;
/* Second two one-before-the-last element. */
while (l->next)
{
old = l;
l = l->next;
cmp = strcmp (s, l->string);
if (cmp == 0) /* no repeating in the list */
return beg;
else if (cmp > 0)
continue;
/* If the next list element is greater than s, put s between the
current and the next list element. */
t = (slist *)xmalloc (sizeof (slist));
old->next = t;
t->next = l;
t->string = xstrdup (s);
return beg;
}
t = (slist *)xmalloc (sizeof (slist));
t->string = xstrdup (s);
/* Insert the new element after the last element. */
l->next = t;
t->next = NULL;
return beg;
}
/* Is there a specific entry in the list? */
int
in_slist (slist *l, const char *s)
{
int cmp;
while (l)
{
cmp = strcmp (l->string, s);
if (cmp == 0)
return 1;
else if (cmp > 0) /* the list is ordered! */
return 0;
l = l->next;
}
return 0;
}
/* Free the whole slist. */
void
free_slist (slist *l)
{
slist *n;
while (l)
{
n = l->next;
free (l->string);
free (l);
l = n;
}
}
/* Legible -- return a static pointer to the legibly printed long. */
char *
legible (long l)
{
static char outbuf[20];
char inbuf[20];
int i, i1, mod;
char *outptr, *inptr;
/* Print the number into the buffer. */
long_to_string (inbuf, l);
/* Reset the pointers. */
outptr = outbuf;
inptr = inbuf;
/* If the number is negative, shift the pointers. */
if (*inptr == '-')
{
*outptr++ = '-';
++inptr;
}
/* How many digits before the first separator? */
mod = strlen (inptr) % 3;
/* Insert them. */
for (i = 0; i < mod; i++)
*outptr++ = inptr[i];
/* Now insert the rest of them, putting separator before every
third digit. */
for (i1 = i, i = 0; inptr[i1]; i++, i1++)
{
if (i % 3 == 0 && i1 != 0)
*outptr++ = ',';
*outptr++ = inptr[i1];
}
/* Zero-terminate the string. */
*outptr = '\0';
return outbuf;
}
/* Count the digits in a (long) integer. */
int
numdigit (long a)
{
int res = 1;
while ((a /= 10) != 0)
++res;
return res;
}
/* Print NUMBER to BUFFER. The digits are first written in reverse
order (the least significant digit first), and are then reversed. */
void
long_to_string (char *buffer, long number)
{
char *p;
int i, l;
if (number < 0)
{
*buffer++ = '-';
number = -number;
}
p = buffer;
/* Print the digits to the string. */
do
{
*p++ = number % 10 + '0';
number /= 10;
}
while (number);
/* And reverse them. */
l = p - buffer - 1;
for (i = l/2; i >= 0; i--)
{
char c = buffer[i];
buffer[i] = buffer[l - i];
buffer[l - i] = c;
}
buffer[l + 1] = '\0';
}

73
src/utils.h Normal file
View File

@ -0,0 +1,73 @@
/* Declarations for utils.c.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef UTILS_H
#define UTILS_H
/* Flags for slist. */
enum {
NOSORT = 1
};
enum accd {
ALLABS = 1
};
/* A linked list of strings. The list is ordered alphabetically. */
typedef struct _slist
{
char *string;
struct _slist *next;
} slist;
char *time_str PARAMS ((time_t *));
const char *uerrmsg PARAMS ((uerr_t));
char *strdupdelim PARAMS ((const char *, const char *));
char **sepstring PARAMS ((const char *));
int frontcmp PARAMS ((const char *, const char *));
char *pwd_cuserid PARAMS ((char *));
void fork_to_background PARAMS ((void));
void path_simplify PARAMS ((char *));
void touch PARAMS ((const char *, time_t));
int remove_link PARAMS ((const char *));
int file_exists_p PARAMS ((const char *));
int file_non_directory_p PARAMS ((const char *));
int make_directory PARAMS ((const char *));
char *unique_name PARAMS ((const char *));
int acceptable PARAMS ((const char *));
int accdir PARAMS ((const char *s, enum accd));
char *suffix PARAMS ((const char *s));
char *read_whole_line PARAMS ((FILE *));
void load_file PARAMS ((FILE *, char **, long *));
void free_vec PARAMS ((char **));
char **merge_vecs PARAMS ((char **, char **));
slist *add_slist PARAMS ((slist *, const char *, int));
int in_slist PARAMS ((slist *, const char *));
void free_slist PARAMS ((slist *));
char *legible PARAMS ((long));
int numdigit PARAMS ((long));
void long_to_string PARAMS ((char *, long));
#endif /* UTILS_H */

1
src/version.c Normal file
View File

@ -0,0 +1 @@
char *version_string = "1.5.3";

201
src/wget.h Normal file
View File

@ -0,0 +1,201 @@
/* Miscellaneous declarations.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of Wget.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file contains some declarations that don't fit anywhere else.
It also contains some useful includes, like the obnoxious TIME_H
inclusion. */
#ifndef WGET_H
#define WGET_H
#ifndef DEBUG
# define NDEBUG /* To kill off assertions */
#endif /* not DEBUG */
#ifndef PARAMS
# if PROTOTYPES
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
/* `gettext (FOO)' is long to write, so we use `_(FOO)'. If NLS is
unavailable, _(STRING) simply returns STRING. */
#ifdef HAVE_NLS
# define _(string) gettext (string)
# ifdef HAVE_LIBINTL_H
# include <libintl.h>
# endif /* HAVE_LIBINTL_H */
#else /* not HAVE_NLS */
# define _(string) string
#endif /* not HAVE_NLS */
/* I18N NOTE: You will notice that none of the DEBUG messages are
marked as translatable. This is intentional, for a few reasons:
1) The debug messages are not meant for the users to look at, but
for the developers; as such, they should be considered more like
source comments than real program output.
2) The messages are numerous, and yet they are random and frivolous
("double yuck!" and such). There would be a lot of work with no
gain.
3) Finally, the debug messages are meant to be a clue for me to
debug problems with Wget. If I get them in a language I don't
understand, debugging will become a new challenge of its own! :-) */
/* Include these, so random files need not include them. */
#include "sysdep.h"
#include "options.h"
#define DO_NOTHING do {} while (0)
/* Print X if debugging is enabled; a no-op otherwise. */
#ifdef DEBUG
# define DEBUGP(x) do { debug_logprintf x; } while (0)
#else /* not DEBUG */
# define DEBUGP(x) DO_NOTHING
#endif /* not DEBUG */
/* Make gcc check for the format of logmsg() and debug_logmsg(). */
#ifdef __GNUC__
# define GCC_FORMAT_ATTR(a, b) __attribute__ ((format (printf, a, b)))
#else /* not __GNUC__ */
# define GCC_FORMAT_ATTR(a, b)
#endif /* not __GNUC__ */
/* These are from log.c, but they are used everywhere, so we declare
them here. */
enum log_options { LOG_VERBOSE, LOG_NOTQUIET, LOG_NONVERBOSE, LOG_ALWAYS };
void logprintf PARAMS ((enum log_options, const char *, ...))
GCC_FORMAT_ATTR (2, 3);
void debug_logprintf PARAMS ((const char *, ...)) GCC_FORMAT_ATTR (1, 2);
void logputs PARAMS ((enum log_options, const char *));
/* Defined in `utils.c', but used literally everywhere. */
void *xmalloc PARAMS ((size_t));
void *xrealloc PARAMS ((void *, size_t));
char *xstrdup PARAMS ((const char *));
/* #### Find a better place for this. */
/* The log file to which Wget writes to after HUP. */
#define DEFAULT_LOGFILE "wget-log"
#define MD5_HASHLEN 16
/* Useful macros used across the code: */
/* Is the string a hpyhen-only? */
#define HYPHENP(x) (*(x) == '-' && !*((x) + 1))
/* The smaller value of the two. */
#define MINVAL(x, y) ((x) < (y) ? (x) : (y))
/* ASCII char -> HEX digit */
#define ASC2HEXD(x) (((x) >= '0' && (x) <= '9') ? \
((x) - '0') : (toupper(x) - 'A' + 10))
/* HEX digit -> ASCII char */
#define HEXD2ASC(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'A'))
#define ARRAY_SIZE(array) (sizeof (array) / sizeof (*(array)))
/* Note that this much more elegant definition cannot be used:
#define STRDUP_ALLOCA(str) (strcpy ((char *)alloca (strlen (str) + 1), str))
This is because some compilers don't handle alloca() as argument to
function correctly. Gcc under Intel has been reported to offend in
this case. */
#define STRDUP_ALLOCA(ptr, str) do { \
(ptr) = (char *)alloca (strlen (str) + 1); \
strcpy (ptr, str); \
} while (0)
#define ALLOCA_ARRAY(type, len) ((type *) alloca ((len) * sizeof (type)))
#define XREALLOC_ARRAY(ptr, type, len) \
((void) (ptr = (type *) xrealloc (ptr, (len) * sizeof (type))))
/* Generally useful if you want to avoid arbitrary size limits but
don't need a full dynamic array. Assumes that BASEVAR points to a
malloced array of TYPE objects (or possibly a NULL pointer, if
SIZEVAR is 0), with the total size stored in SIZEVAR. This macro
will realloc BASEVAR as necessary so that it can hold at least
NEEDED_SIZE objects. The reallocing is done by doubling, which
ensures constant amortized time per element. */
#define DO_REALLOC(basevar, sizevar, needed_size, type) do \
{ \
/* Avoid side-effectualness. */ \
long do_realloc_needed_size = (needed_size); \
long do_realloc_newsize = 0; \
while ((sizevar) < (do_realloc_needed_size)) { \
do_realloc_newsize = 2*(sizevar); \
if (do_realloc_newsize < 32) \
do_realloc_newsize = 32; \
(sizevar) = do_realloc_newsize; \
} \
if (do_realloc_newsize) \
XREALLOC_ARRAY (basevar, type, do_realloc_newsize); \
} while (0)
/* Free FOO if it is non-NULL. */
#define FREE_MAYBE(foo) do { if (foo) free (foo); } while (0)
/* #### Hack: OPTIONS_DEFINED_HERE is defined in main.c. */
#ifndef OPTIONS_DEFINED_HERE
extern const char *exec_name;
#endif
/* Document-type flags */
enum
{
TEXTHTML = 0x0001, /* document is of type text/html */
RETROKF = 0x0002, /* retrieval was OK */
HEAD_ONLY = 0x0004, /* only send the HEAD request */
SEND_NOCACHE = 0x0008, /* send Pragma: no-cache directive */
ACCEPTRANGES = 0x0010 /* Accept-ranges header was found */
};
/* Universal error type -- used almost everywhere.
This is, of course, utter crock. */
typedef enum
{
NOCONERROR, HOSTERR, CONSOCKERR, CONERROR,
CONREFUSED, NEWLOCATION, NOTENOUGHMEM, CONPORTERR,
BINDERR, BINDOK, LISTENERR, ACCEPTERR, ACCEPTOK,
CONCLOSED, FTPOK, FTPLOGINC, FTPLOGREFUSED, FTPPORTERR,
FTPNSFOD, FTPRETROK, FTPUNKNOWNTYPE, FTPRERR,
FTPREXC, FTPSRVERR, FTPRETRINT, FTPRESTFAIL,
URLOK, URLHTTP, URLFTP, URLFILE, URLUNKNOWN, URLBADPORT,
URLBADHOST, FOPENERR, FWRITEERR, HOK, HLEXC, HEOF,
HERR, RETROK, RECLEVELEXC, FTPACCDENIED, WRONGCODE,
FTPINVPASV, FTPNOPASV,
RETRFINISHED, READERR, TRYLIMEXC, URLBADPATTERN,
FILEBADFILE, RANGEERR, RETRBADPATTERN, RETNOTSUP,
ROBOTSOK, NOROBOTS, PROXERR, AUTHFAILED, QUOTEXC, WRITEFAILED
} uerr_t;
#endif /* WGET_H */

1
stamp-h.in Normal file
View File

@ -0,0 +1 @@
timestamp

37
util/Makefile.in Normal file
View File

@ -0,0 +1,37 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: @VERSION@
#
SHELL = /bin/sh
srcdir = @srcdir@
VPATH = @srcdir@
RM = rm -f
all:
clean:
distclean: clean
$(RM) Makefile
realclean: distclean

28
util/README Normal file
View File

@ -0,0 +1,28 @@
-*- text -*-
This directory contains various optional utilities to help you use
Wget.
Socks:
======
Antonio Rosella <antonio.rosella@agip.it> has written a sample HTML
frontend and a Perl script to demonstrate usage of socksified Wget as
web retriever.
To configure Wget to use socks, do a
$ ./configure --with-sox.
download.html and download-netscape.html are examples of how you can
use socksified Wget to schedule the WWW requests. wget.cgi is a
CGI Perl script used in conjunction with download.html, which
schedules request using the "at" command.
To get the script, contact Antonino.
rmold.pl
========
This Perl script is used to check which local files are no longer on
the remote server. You can use it to get the list of files, or
$ rmold.pl [dir] | xargs rm

114
util/download-netscape.html Normal file
View File

@ -0,0 +1,114 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Wget Gateway</title>
<link rev="made" href="mailto:Antonio.Rosella@agip.it">
</head>
<body>
<center>
<h1>Wget Gateway</h1>
</center>
<p>
Welcome to Wget Gateway, a simple page showing the usage of
socksified wget behind a firewall. In my configuration it is
very useful because:
<ul>
<li>Only few users can exit from firewall
<li>A lot of users need information that can be reached in Internet
<li>I cannot dowload big files during my job time, so, I
have to schedule the requests after the normal work time
</ul>
<p>
With the combination of a socksified wget and a simple cgi
that schedules the requests can I reach the aim. All you need
is:
<ul>
<li> A socksified copy of
<a href="ftp://gnjilux.cc.fer.hr/pub/unix/util/wget/wget.tar.gz">
wget</a>
<li> Perl (available on all the GNU mirroring sites)
<li> cgi-lib.pl (available at
<a href="ftp://ftp.switch.ch/mirror/CPAN/ROADMAP.html">CPAN</a>)
<li> A customized copy of this html
<li> A customized copy of socks.cgi
</ul>
This is my h/s configuration:
<pre>
+----------+ +----------------------------------+ +---------------------+
| Firewall | | Host that can exit from firewall | | Intranet www server |
+----------+ | htceff | +---------------------+
+----------------------------------+ | Wget.html |
| socksified wget | +---------------------+
| cgi-lib.pl |
| perl |
| wget.cgi |
+----------------------------------+
</pre>
<p>
wget.cgi, wget and cgi-lib.pl are located in the usual
cgi-bin directory. The customization of wget.cgi and
wget.html has to reflect you installation, i.e.:
<ul>
<li> download-netscape.html requires wget.cgi
<li> wget.cgi requires Perl, cgi-lib.pl and wget
<li>
wget.cgi has to download the files to a directory writable
by the user submitting the request. At the moment I have an
anonymous ftp installed on <em>htceff</em>, and wget puts
dowloaded files to /pub/incoming directory (if you look at
wget.cgi, it sets the destdir to "/u/ftp/pub/incoming" if
the user leaves it blank).
</ul>
<p>
You can also add other parameters that you want to pass to wget,
but in this case you will also have to modify wget.cgi
<hr>
<form method="get" action="http://localhost/cgi-bin/wget.cgi">
<center>
<table border=1>
<td>Recursive Download
<td><select name=Recursion>
<Option selected value=N>No</Option>
<Option value=Y>Yes</Option>
</select>
</table>
<hr>
<table border=1>
<td>Depth
<td><input type="radio" name=depth value=1 checked> 1
<td><input type="radio" name=depth value=2 > 2
<td><input type="radio" name=depth value=3 > 3
<td><input type="radio" name=depth value=4 > 4
<td><input type="radio" name=depth value=5 > 5
</table>
<hr>
<table>
<td>Url to download: <td><input name="url" size=50><TR>
<td>Destination directory: <td><input name="destdir" size=50><TR>
</table>
<hr>
Now you can
<font color=yellow><input type="submit" value="download"></font>
the requested URL or
<font color=yellow><input type="reset" value="reset"></font>
the form.
</form>
<hr>
Feedback is always useful! Please contact me at
<address>
<a href="mailto:Antonio.Rosella@agip.it">Antonio Rosella&lt;Antonio.Rosella@agip.it&gt;</a>.
</address>
You can send your suggestions or bug reports for Wget to
<address>
<a href="mailto:hniksic@srce.hr">Hrvoje Niksic &lt;hniksic@srce.hr&gt;</a>.
</address>
<!-- hhmts start -->
Last modified: Thu Mar 26 16:26:36 MET 1998
<!-- hhmts end -->
</body>
</html>

106
util/download.html Normal file
View File

@ -0,0 +1,106 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>Wget Gateway</title>
<link rev="made" href="mailto:Antonio.Rosella@agip.it">
</head>
<body>
<h1>Wget Gateway</h1>
<p>
Welcome to Wget Gateway, a simple page showing the usage of
socksified wget behind a firewall. In my configuration it is
very useful because:
<ul>
<li>Only few users can exit from firewall
<li>A lot of users need information that can be reached in Internet
<li>I cannot dowload big files during my job time, so, I
have to schedule the requests after the normal work time
</ul>
<p>
With the combination of a socksified wget and a simple cgi
that schedules the requests can I reach the aim. All you need
is:
<ul>
<li> A socksified copy of
<a href="ftp://gnjilux.cc.fer.hr/pub/unix/util/wget/wget.tar.gz">
wget</a>
<li> Perl (available on all the GNU mirroring sites)
<li> cgi-lib.pl (available at
<a href="ftp://ftp.switch.ch/mirror/CPAN/ROADMAP.html">CPAN</a>)
<li> A customized copy of this html
<li> A customized copy of socks.cgi
</ul>
This is my h/s configuration:
<pre>
+----------+ +----------------------------------+ +---------------------+
| Firewall | | Host that can exit from firewall | | Intranet www server |
+----------+ | htceff | +---------------------+
+----------------------------------+ | Wget.html |
| socksified wget | +---------------------+
| cgi-lib.pl |
| perl |
| wget.cgi |
+----------------------------------+
</pre>
<p>
wget.cgi, wget and cgi-lib.pl are located in the usual
cgi-bin directory. The customization of wget.cgi and
wget.html has to reflect you installation, i.e.:
<ul>
<li> download.html requires wget.cgi
<li> wget.cgi requires Perl, cgi-lib.pl and wget
<li>
wget.cgi has to download the files to a directory writable
by the user submitting the request. At the moment I have an
anonymous ftp installed on <em>htceff</em>, and wget puts
dowloaded files to /pub/incoming directory (if you look at
wget.cgi, it sets the destdir to "/u/ftp/pub/incoming" if
the user leaves it blank).
</ul>
<p>
You can also add other parameters that you want to pass to wget,
but in this case you will also have to modify wget.cgi
<hr>
<form method="get" action="http://localhost/cgi-bin/wget.cgi">
<h3>Downloading (optionally recursive)</h3>
<ul>
<li>
Recursion:
<Select name=Recursion>
<Option selected value=N>No</Option>
<Option value=Y>Yes</Option>
</Select>
<li>
Depth:
<input type="radio" name=depth value=1 checked>1
<input type="radio" name=depth value=2 >2
<input type="radio" name=depth value=3 >3
<input type="radio" name=depth value=4 >4
<input type="radio" name=depth value=5 >5
<li>
Url to download: <input name="url" size=50>
<li>
Destination directory: <input name="destdir" size=50>
</ul>
Now you can <input type="submit" value="download"> the
requested URL or <input type="reset" value="reset"> the form.
</form>
<hr>
Feedback is always useful! Please contact me at
<address>
<a href="mailto:Antonio.Rosella@agip.it">Antonio Rosella&lt;Antonio.Rosella@agip.it&gt;</a>.
</address>
You can send your suggestions or bug reports for Wget to
<address>
<a href="mailto:hniksic@srce.hr">Hrvoje Niksic &lt;hniksic@srce.hr&gt;</a>.
</address>
<!-- hhmts start -->
Last modified: Thu Mar 26 16:26:39 MET 1998
<!-- hhmts end -->
</body>
</html>

92
util/rmold.pl Executable file
View File

@ -0,0 +1,92 @@
#! /usr/bin/perl -w
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# This script is a very lame hack to remove local files, until the
# time when Wget proper will have this functionality.
# Use with utmost care!
# If the remote server supports BSD-style listings, set this to 0.
$sysvlisting = 1;
$verbose = 0;
if (@ARGV && ($ARGV[0] eq '-v')) {
shift;
$verbose = 1;
}
defined($dirs[0] = shift) || ($dirs[0] = '.');
while (defined($_ = shift)) {
@dirs = (@dirs, $_);
}
foreach $_ (@dirs) {
&procdir($_);
}
# End here
sub procdir
{
local($dir = $_[0]);
local(@lcfiles, @lcdirs, %files, @fl);
print STDERR "Processing directory '$dir':\n" if $verbose;
opendir(DH, $dir) || die("Cannot open $dir: $!\n");
@lcfiles = ();
@lcdirs = ();
# Read local files and directories.
foreach $_ (readdir(DH)) {
/^(\.listing|\.\.?)$/ && next;
if (-d "$dir/$_" || -l "$dir/$_") {
@lcdirs = (@lcdirs, $_);
}
else {
@lcfiles = (@lcfiles, $_);
}
}
closedir(DH);
# Parse .listing
if (open(FD, "<$dir/.listing")) {
@files = ();
while (<FD>)
{
# Weed out the line beginning with 'total'
/^total/ && next;
# Weed out everything but plain files and symlinks.
/^[-l]/ || next;
@fl = split;
$files{$fl[7 + $sysvlisting]} = 1;
}
close FD;
foreach $_ (@lcfiles) {
if (!$files{$_}) {
print "$dir/$_\n";
}
}
}
else {
print STDERR "Warning: $dir/.listing: $!\n";
}
foreach $_ (@lcdirs) {
&procdir("$dir/$_");
}
}

57
util/wget.spec Normal file
View File

@ -0,0 +1,57 @@
Summary: A command-line client to download WWW/FTP documents with optional recursion.
Name: wget
%define version 1.4.5
Version: %{version}
Release: 3
Source: ftp://prep.ai.mit.edu/pub/gnu/wget-1.4.5.tar.gz
Group: Applications/Networking
Copyright: GPL
Buildroot: /var/tmp/wget-root
Packager: Jeff Johnson <jbj@jbj.org>
%description
GNU Wget is a freely available network utility to retrieve files from
the World Wide Web, using HTTP (Hyper Text Transfer Protocol) and
FTP (File Transfer Protocol), the two most widely used Internet
protocols.
%prep
%setup
%build
./configure --prefix=/usr --sysconfdir=/etc
make
%install
rm -rf $RPM_BUILD_ROOT
make prefix=$RPM_BUILD_ROOT/usr sysconfdir=$RPM_BUILD_ROOT/etc INSTALL_PROGRAM="install -s" install
gzip -9nf $RPM_BUILD_ROOT/usr/info/wget*
%post
/sbin/install-info /usr/info/wget.info.gz /usr/info/dir --entry="* wget: (wget). GNU Wget Manual."
%preun
if [ $1 = 0 ]; then
/sbin/install-info --delete /usr/info/wget.info.gz /usr/info/dir --entry="* wget: (wget). GNU Wget Manual."
fi
%clean
rm -rf $RPM_BUILD_ROOT
%files
%doc README NEWS AUTHORS COPYING INSTALL MACHINES MAILING-LIST
/usr/bin/wget
/etc/wgetrc
/usr/info/wget*
/usr/man/man1/wget.1
%changelog
* Thu Feb 26 1998 Jeff Johnson <jbj@jbj.org>
- Simplify previous contrib version.

42
windows/Makefile.doc Normal file
View File

@ -0,0 +1,42 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
RM = del
all: wget.hlp
# You probably need makeinfo utility
# wget it from URL:http://www.sunsite.auc.dk/wget/makeinfo.zip
.IGNORE:
wget.hlp: wget.texi
makeinfo --no-validate --no-warn --force \
--hpj wget.hpj --output wget.rtf wget.texi
hcrtf -xn wget.hpj
clean:
$(RM) *.bak
$(RM) *.hpj
$(RM) *.rtf
$(RM) *.ph
distclean: clean
$(RM) wget.hlp
$(RM) Makefile
realclean: distclean

91
windows/Makefile.src Normal file
View File

@ -0,0 +1,91 @@
# Makefile for `wget' utility for MSVC 4.0
# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: 1.4.4
#
SHELL = command
VPATH = .
o = .obj
OUTDIR = .
CC = cl
LD = link
CFLAGS = /nologo /MT /W0 /O2
#DEBUGCF = /DDEBUG /Zi /Od #/Fd /FR
CPPFLAGS =
DEFS = /DWINDOWS /D_CONSOLE /DHAVE_CONFIG_H /DSYSTEM_WGETRC=\"wgetrc\"
LDFLAGS = /subsystem:console /incremental:no /warn:3
#DEBUGLF = /pdb:wget.pdb /debug /debugtype:cv /map:wget.map /opt:noref
LIBS = kernel32.lib advapi32.lib wsock32.lib user32.lib
INCLUDES = /I.
COMPILE = $(CC) $(INCLUDES) $(CPPFLAGS) $(DEBUGCF) $(DEFS) $(CFLAGS)
LINK = $(LD) $(LDFLAGS) $(DEBUGLF) /out:$@
#INSTALL = @INSTALL@
#INSTALL_PROGRAM = @INSTALL_PROGRAM@
RM = del
SRC = alloca.c cmpt.c connect.c host.c http.c netrc.c ftp-basic.c ftp.c ftp-ls.c \
ftp-opie.c getopt.c headers.c html.c retr.c recur.c url.c init.c utils.c main.c \
version.c mswindows.c fnmatch.c md5.c rbuf.c log.c
OBJ = alloca$o cmpt$o connect$o host$o http$o netrc$o ftp-basic$o ftp$o ftp-ls$o \
ftp-opie$o headers$o html$o retr$o recur$o url$o init$o utils$o main$o \
getopt$o version$o mswindows$o fnmatch$o md5$o rbuf$o log$o
.SUFFIXES: .c .obj
.c.obj:
$(COMPILE) /c $<
# Dependencies for building
wget: wget.exe
wget.exe: $(OBJ)
$(LD) @<< $(LDFLAGS) $(DEBUGLF) /out:$@ $(LIBS) $(OBJ)
<<
ren wget.exe WGET.EXE
#
# Dependencies for cleanup
#
clean:
$(RM) *.obj
$(RM) *.exe
$(RM) *.bak
$(RM) *.pdb
$(RM) *.map
distclean: clean
$(RM) Makefile
realclean: distclean
$(RM) TAGS
# Dependencies:
!include "..\windows\wget.dep"

Some files were not shown because too many files have changed in this diff Show More