1
/* Get the contents of an URL.
2
Copyright (C) 2001-2003, 2005-2007 Free Software Foundation, Inc.
3
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 3 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>. */
34
#include "error-progname.h"
36
#include "relocatable.h"
38
#include "full-write.h"
41
#include "binary-io.h"
42
#include "propername.h"
45
#define _(str) gettext (str)
48
# define STDOUT_FILENO 1
52
/* Only high-level toolkits, written in languages with exception handling,
53
have an URL datatype and operations to fetch an URL's contents. Such
54
toolkits are Java (class java.net.URL), Qt (classes QUrl and QUrlOperator).
55
We use the Java toolkit.
56
Note that this program doesn't handle redirection pages; programs which
57
wish to process HTML redirection tags need to include a HTML parser,
58
and only full-fledged browsers like w3m, lynx, links have have both
59
an URL fetcher (which covers at least the protocols "http", "ftp", "file")
64
static const struct option long_options[] =
66
{ "help", no_argument, NULL, 'h' },
67
{ "version", no_argument, NULL, 'V' },
72
/* Forward declaration of local functions. */
73
static void usage (int status)
74
#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
75
__attribute__ ((noreturn))
78
static void fetch (const char *url, const char *file);
82
main (int argc, char *argv[])
88
/* Set program name for messages. */
89
set_program_name (argv[0]);
90
error_print_progname = maybe_print_progname;
93
/* Set locale via LC_ALL. */
94
setlocale (LC_ALL, "");
97
/* Set the text message domain. */
98
bindtextdomain (PACKAGE, relocate (LOCALEDIR));
101
/* Ensure that write errors on stdout are detected. */
102
atexit (close_stdout);
104
/* Set default values for variables. */
108
/* Parse command line options. */
109
while ((optchar = getopt_long (argc, argv, "hV", long_options, NULL)) != EOF)
112
case '\0': /* Long option. */
121
usage (EXIT_FAILURE);
125
/* Version information requested. */
128
printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
129
/* xgettext: no-wrap */
130
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
131
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
132
This is free software: you are free to change and redistribute it.\n\
133
There is NO WARRANTY, to the extent permitted by law.\n\
135
"2001-2003, 2005-2007");
136
printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
140
/* Help is requested. */
142
usage (EXIT_SUCCESS);
144
/* Test argument count. */
145
if (optind + 2 != argc)
146
error (EXIT_FAILURE, 0, _("expected two arguments"));
148
/* Fetch the contents. */
149
fetch (argv[optind], argv[optind + 1]);
154
/* Display usage information and exit. */
158
if (status != EXIT_SUCCESS)
159
fprintf (stderr, _("Try `%s --help' for more information.\n"),
164
Usage: %s [OPTION] URL FILE\n\
167
/* xgettext: no-wrap */
169
Fetches and outputs the contents of an URL. If the URL cannot be accessed,\n\
170
the locally accessible FILE is used instead.\n\
174
Informative output:\n"));
176
-h, --help display this help and exit\n"));
178
-V, --version output version information and exit\n"));
180
/* TRANSLATORS: The placeholder indicates the bug-reporting address
181
for this package. Please add _another line_ saying
182
"Report translation bugs to <...>\n" with the address for translation
183
bugs (typically your translation team's web or email address). */
184
fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
191
/* Copy a file's contents to stdout. */
193
cat_file (const char *src_filename)
197
const int buf_size = sizeof (buf);
199
src_fd = open (src_filename, O_RDONLY | O_BINARY);
201
error (EXIT_FAILURE, errno, _("error while opening \"%s\" for reading"),
206
ssize_t n_read = read (src_fd, buf, buf_size);
213
error (EXIT_FAILURE, errno, _("error reading \"%s\""), src_filename);
218
if (full_write (STDOUT_FILENO, buf, n_read) < n_read)
219
error (EXIT_FAILURE, errno, _("error writing stdout"));
222
if (close (src_fd) < 0)
223
error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename);
227
execute_it (const char *progname,
228
const char *prog_path, char **prog_argv,
233
return execute (progname, prog_path, prog_argv, true, true, false, false,
238
/* Fetch the URL. Upon error, use the FILE as fallback. */
240
fetch (const char *url, const char *file)
242
/* First try: using Java. */
244
const char *class_name = "gnu.gettext.GetURL";
245
const char *gettextjexedir;
246
const char *gettextjar;
250
/* Make it possible to override the executable's location. This is
251
necessary for running the testsuite before "make install". */
252
gettextjexedir = getenv ("GETTEXTJEXEDIR");
253
if (gettextjexedir == NULL || gettextjexedir[0] == '\0')
254
gettextjexedir = relocate (GETTEXTJEXEDIR);
256
gettextjexedir = NULL;
259
/* Make it possible to override the gettext.jar location. This is
260
necessary for running the testsuite before "make install". */
261
gettextjar = getenv ("GETTEXTJAR");
262
if (gettextjar == NULL || gettextjar[0] == '\0')
263
gettextjar = relocate (GETTEXTJAR);
265
/* Prepare arguments. */
269
/* Fetch the URL's contents. */
270
if (execute_java_class (class_name, &gettextjar, 1, true, gettextjexedir,
273
execute_it, NULL) == 0)
277
/* Second try: using "wget -q -O - url". */
279
static bool wget_tested;
280
static bool wget_present;
284
/* Test for presence of wget: "wget --version > /dev/null" */
289
argv[1] = "--version";
291
exitstatus = execute ("wget", "wget", argv, false, false, true, true,
293
wget_present = (exitstatus == 0);
304
argv[2] = "-O"; argv[3] = "-";
305
argv[4] = "-T"; argv[5] = "30";
306
argv[6] = (char *) url;
308
exitstatus = execute ("wget", "wget", argv, true, false, false, false,
310
if (exitstatus != 127)
313
/* Use the file as fallback. */
320
/* Third try: using "lynx -source url". */
322
static bool lynx_tested;
323
static bool lynx_present;
327
/* Test for presence of lynx: "lynx --version > /dev/null" */
332
argv[1] = "--version";
334
exitstatus = execute ("lynx", "lynx", argv, false, false, true, true,
336
lynx_present = (exitstatus == 0);
347
argv[2] = (char *) url;
349
exitstatus = execute ("lynx", "lynx", argv, true, false, false, false,
351
if (exitstatus != 127)
354
/* Use the file as fallback. */
361
/* Fourth try: using "curl --silent url". */
363
static bool curl_tested;
364
static bool curl_present;
368
/* Test for presence of curl: "curl --version > /dev/null" */
373
argv[1] = "--version";
375
exitstatus = execute ("curl", "curl", argv, false, false, true, true,
377
curl_present = (exitstatus == 0 || exitstatus == 2);
387
argv[1] = "--silent";
388
argv[2] = (char *) url;
390
exitstatus = execute ("curl", "curl", argv, true, false, false, false,
392
if (exitstatus != 127)
395
/* Use the file as fallback. */
402
/* Use the file as fallback. */