1 /* Get the contents of an URL.
2 Copyright (C) 2001-2003, 2005 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 2, or (at your option)
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, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
38 #include "error-progname.h"
40 #include "relocatable.h"
42 #include "full-write.h"
46 #include "binary-io.h"
49 #define _(str) gettext (str)
52 # define STDOUT_FILENO 1
56 /* Only high-level toolkits, written in languages with exception handling,
57 have an URL datatype and operations to fetch an URL's contents. Such
58 toolkits are Java (class java.net.URL), Qt (classes QUrl and QUrlOperator).
59 We use the Java toolkit.
60 Note that this program doesn't handle redirection pages; programs which
61 wish to process HTML redirection tags need to include a HTML parser,
62 and only full-fledged browsers like w3m, lynx, links have have both
63 an URL fetcher (which covers at least the protocols "http", "ftp", "file")
68 static const struct option long_options
[] =
70 { "help", no_argument
, NULL
, 'h' },
71 { "version", no_argument
, NULL
, 'V' },
76 /* Forward declaration of local functions. */
77 static void usage (int status
)
78 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
79 __attribute__ ((noreturn
))
82 static void fetch (const char *url
, const char *file
);
86 main (int argc
, char *argv
[])
92 /* Set program name for messages. */
93 set_program_name (argv
[0]);
94 error_print_progname
= maybe_print_progname
;
97 /* Set locale via LC_ALL. */
98 setlocale (LC_ALL
, "");
101 /* Set the text message domain. */
102 bindtextdomain (PACKAGE
, relocate (LOCALEDIR
));
103 textdomain (PACKAGE
);
105 /* Ensure that write errors on stdout are detected. */
106 atexit (close_stdout
);
108 /* Set default values for variables. */
112 /* Parse command line options. */
113 while ((optchar
= getopt_long (argc
, argv
, "hV", long_options
, NULL
)) != EOF
)
116 case '\0': /* Long option. */
125 usage (EXIT_FAILURE
);
129 /* Version information requested. */
132 printf ("%s (GNU %s) %s\n", basename (program_name
), PACKAGE
, VERSION
);
133 /* xgettext: no-wrap */
134 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
135 This is free software; see the source for copying conditions. There is NO\n\
136 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
139 printf (_("Written by %s.\n"), "Bruno Haible");
143 /* Help is requested. */
145 usage (EXIT_SUCCESS
);
147 /* Test argument count. */
148 if (optind
+ 2 != argc
)
149 error (EXIT_FAILURE
, 0, _("expected two arguments"));
151 /* Fetch the contents. */
152 fetch (argv
[optind
], argv
[optind
+ 1]);
157 /* Display usage information and exit. */
161 if (status
!= EXIT_SUCCESS
)
162 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
167 Usage: %s [OPTION] URL FILE\n\
170 /* xgettext: no-wrap */
172 Fetches and outputs the contents of an URL. If the URL cannot be accessed,\n\
173 the locally accessible FILE is used instead.\n\
177 Informative output:\n"));
179 -h, --help display this help and exit\n"));
181 -V, --version output version information and exit\n"));
183 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
190 /* Copy a file's contents to stdout. */
192 cat_file (const char *src_filename
)
196 const int buf_size
= sizeof (buf
);
198 src_fd
= open (src_filename
, O_RDONLY
| O_BINARY
);
200 error (EXIT_FAILURE
, errno
, _("error while opening \"%s\" for reading"),
205 ssize_t n_read
= read (src_fd
, buf
, buf_size
);
212 error (EXIT_FAILURE
, errno
, _("error reading \"%s\""), src_filename
);
217 if (full_write (STDOUT_FILENO
, buf
, n_read
) < n_read
)
218 error (EXIT_FAILURE
, errno
, _("error writing stdout"));
221 if (close (src_fd
) < 0)
222 error (EXIT_FAILURE
, errno
, _("error after reading \"%s\""), src_filename
);
226 execute_it (const char *progname
,
227 const char *prog_path
, char **prog_argv
,
232 return execute (progname
, prog_path
, prog_argv
, true, true, false, false,
237 /* Fetch the URL. Upon error, use the FILE as fallback. */
239 fetch (const char *url
, const char *file
)
241 /* First try: using Java. */
243 const char *class_name
= "gnu.gettext.GetURL";
244 const char *gettextjexedir
;
245 const char *gettextjar
;
249 /* Make it possible to override the executable's location. This is
250 necessary for running the testsuite before "make install". */
251 gettextjexedir
= getenv ("GETTEXTJEXEDIR");
252 if (gettextjexedir
== NULL
|| gettextjexedir
[0] == '\0')
253 gettextjexedir
= relocate (GETTEXTJEXEDIR
);
255 gettextjexedir
= NULL
;
258 /* Make it possible to override the gettext.jar location. This is
259 necessary for running the testsuite before "make install". */
260 gettextjar
= getenv ("GETTEXTJAR");
261 if (gettextjar
== NULL
|| gettextjar
[0] == '\0')
262 gettextjar
= relocate (GETTEXTJAR
);
264 /* Prepare arguments. */
268 /* Fetch the URL's contents. */
269 if (execute_java_class (class_name
, &gettextjar
, 1, true, gettextjexedir
,
272 execute_it
, NULL
) == 0)
276 /* Second try: using "wget -q -O - url". */
278 static bool wget_tested
;
279 static bool wget_present
;
283 /* Test for presence of wget: "wget --version > /dev/null" */
288 argv
[1] = "--version";
290 exitstatus
= execute ("wget", "wget", argv
, false, false, true, true,
292 wget_present
= (exitstatus
== 0);
303 argv
[2] = "-O"; argv
[3] = "-";
304 argv
[4] = "-T"; argv
[5] = "30";
305 argv
[6] = (char *) url
;
307 exitstatus
= execute ("wget", "wget", argv
, true, false, false, false,
309 if (exitstatus
!= 127)
312 /* Use the file as fallback. */
319 /* Third try: using "lynx -source url". */
321 static bool lynx_tested
;
322 static bool lynx_present
;
326 /* Test for presence of lynx: "lynx --version > /dev/null" */
331 argv
[1] = "--version";
333 exitstatus
= execute ("lynx", "lynx", argv
, false, false, true, true,
335 lynx_present
= (exitstatus
== 0);
346 argv
[2] = (char *) url
;
348 exitstatus
= execute ("lynx", "lynx", argv
, true, false, false, false,
350 if (exitstatus
!= 127)
353 /* Use the file as fallback. */
360 /* Fourth try: using "curl --silent url". */
362 static bool curl_tested
;
363 static bool curl_present
;
367 /* Test for presence of curl: "curl --version > /dev/null" */
372 argv
[1] = "--version";
374 exitstatus
= execute ("curl", "curl", argv
, false, false, true, true,
376 curl_present
= (exitstatus
== 0 || exitstatus
== 2);
386 argv
[1] = "--silent";
387 argv
[2] = (char *) url
;
389 exitstatus
= execute ("curl", "curl", argv
, true, false, false, false,
391 if (exitstatus
!= 127)
394 /* Use the file as fallback. */
401 /* Use the file as fallback. */