]> sjero.net Git - wget/blob - src/retr.c
c0b439e8f79255ae92d22d17cc02aaf9b11fc3b3
[wget] / src / retr.c
1 /* File retrieval.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif /* HAVE_UNISTD_H */
38 #include <errno.h>
39 #ifdef HAVE_STRING_H
40 # include <string.h>
41 #else
42 # include <strings.h>
43 #endif /* HAVE_STRING_H */
44 #include <assert.h>
45
46 #include "wget.h"
47 #include "utils.h"
48 #include "retr.h"
49 #include "progress.h"
50 #include "url.h"
51 #include "recur.h"
52 #include "ftp.h"
53 #include "host.h"
54 #include "connect.h"
55 #include "hash.h"
56 #include "convert.h"
57
58 #ifdef HAVE_SSL
59 # include "gen_sslfunc.h"       /* for ssl_iread */
60 #endif
61
62 #ifndef errno
63 extern int errno;
64 #endif
65
66 /* See the comment in gethttp() why this is needed. */
67 int global_download_count;
68
69 \f
70 static struct {
71   long chunk_bytes;
72   double chunk_start;
73   double sleep_adjust;
74 } limit_data;
75
76 static void
77 limit_bandwidth_reset (void)
78 {
79   limit_data.chunk_bytes = 0;
80   limit_data.chunk_start = 0;
81 }
82
83 /* Limit the bandwidth by pausing the download for an amount of time.
84    BYTES is the number of bytes received from the network, and DELTA
85    is the number of milliseconds it took to receive them.  */
86
87 static void
88 limit_bandwidth (long bytes, double *dltime, struct wget_timer *timer)
89 {
90   double delta_t = *dltime - limit_data.chunk_start;
91   double expected;
92
93   limit_data.chunk_bytes += bytes;
94
95   /* Calculate the amount of time we expect downloading the chunk
96      should take.  If in reality it took less time, sleep to
97      compensate for the difference.  */
98   expected = 1000.0 * limit_data.chunk_bytes / opt.limit_rate;
99
100   if (expected > delta_t)
101     {
102       double slp = expected - delta_t + limit_data.sleep_adjust;
103       double t0, t1;
104       if (slp < 200)
105         {
106           DEBUGP (("deferring a %.2f ms sleep (%ld/%.2f).\n",
107                    slp, limit_data.chunk_bytes, delta_t));
108           return;
109         }
110       DEBUGP (("\nsleeping %.2f ms for %ld bytes, adjust %.2f ms\n",
111                slp, limit_data.chunk_bytes, limit_data.sleep_adjust));
112
113       t0 = *dltime;
114       usleep ((unsigned long) (1000 * slp));
115       t1 = wtimer_elapsed (timer);
116
117       /* Due to scheduling, we probably slept slightly longer (or
118          shorter) than desired.  Calculate the difference between the
119          desired and the actual sleep, and adjust the next sleep by
120          that amount.  */
121       limit_data.sleep_adjust = slp - (t1 - t0);
122
123       /* Since we've called wtimer_elapsed, we might as well update
124          the caller's dltime. */
125       *dltime = t1;
126     }
127
128   limit_data.chunk_bytes = 0;
129   limit_data.chunk_start = *dltime;
130 }
131
132 #define MIN(i, j) ((i) <= (j) ? (i) : (j))
133
134 /* Reads the contents of file descriptor FD, until it is closed, or a
135    read error occurs.  The data is read in 8K chunks, and stored to
136    stream fp, which should have been open for writing.  If BUF is
137    non-NULL and its file descriptor is equal to FD, flush RBUF first.
138    This function will *not* use the rbuf_* functions!
139
140    The EXPECTED argument is passed to show_progress() unchanged, but
141    otherwise ignored.
142
143    If opt.verbose is set, the progress is also shown.  RESTVAL
144    represents a value from which to start downloading (which will be
145    shown accordingly).  If RESTVAL is non-zero, the stream should have
146    been open for appending.
147
148    The function exits and returns codes of 0, -1 and -2 if the
149    connection was closed, there was a read error, or if it could not
150    write to the output stream, respectively.
151
152    IMPORTANT: The function flushes the contents of the buffer in
153    rbuf_flush() before actually reading from fd.  If you wish to read
154    from fd immediately, flush or discard the buffer.  */
155 int
156 get_contents (int fd, FILE *fp, long *len, long restval, long expected,
157               struct rbuf *rbuf, int use_expected, double *elapsed)
158 {
159   int res = 0;
160
161   static char dlbuf[16384];
162   int dlbufsize = sizeof (dlbuf);
163
164   void *progress = NULL;
165   struct wget_timer *timer = wtimer_allocate ();
166   double dltime = 0;
167
168   *len = restval;
169
170   if (opt.verbose)
171     progress = progress_create (restval, expected);
172
173   if (rbuf && RBUF_FD (rbuf) == fd)
174     {
175       int sz = 0;
176       while ((res = rbuf_flush (rbuf, dlbuf, sizeof (dlbuf))) != 0)
177         {
178           fwrite (dlbuf, 1, res, fp);
179           *len += res;
180           sz += res;
181         }
182       if (sz)
183         fflush (fp);
184       if (ferror (fp))
185         {
186           res = -2;
187           goto out;
188         }
189       if (progress)
190         progress_update (progress, sz, 0);
191     }
192
193   if (opt.limit_rate)
194     limit_bandwidth_reset ();
195   wtimer_reset (timer);
196
197   /* Use a smaller buffer for low requested bandwidths.  For example,
198      with --limit-rate=2k, it doesn't make sense to slurp in 16K of
199      data and then sleep for 8s.  With buffer size equal to the limit,
200      we never have to sleep for more than one second.  */
201   if (opt.limit_rate && opt.limit_rate < dlbufsize)
202     dlbufsize = opt.limit_rate;
203
204   /* Read from fd while there is available data.
205
206      Normally, if expected is 0, it means that it is not known how
207      much data is expected.  However, if use_expected is specified,
208      then expected being zero means exactly that.  */
209   while (!use_expected || (*len < expected))
210     {
211       int amount_to_read = (use_expected
212                             ? MIN (expected - *len, dlbufsize) : dlbufsize);
213 #ifdef HAVE_SSL
214       if (rbuf->ssl!=NULL)
215         res = ssl_iread (rbuf->ssl, dlbuf, amount_to_read);
216       else
217 #endif /* HAVE_SSL */
218         res = iread (fd, dlbuf, amount_to_read);
219
220       if (res <= 0)
221         break;
222
223       fwrite (dlbuf, 1, res, fp);
224       /* Always flush the contents of the network packet.  This should
225          not hinder performance: fast downloads will be received in
226          16K chunks (which stdio would write out anyway), and slow
227          downloads won't be limited with disk performance.  */
228       fflush (fp);
229       if (ferror (fp))
230         {
231           res = -2;
232           goto out;
233         }
234
235       dltime = wtimer_elapsed (timer);
236       if (opt.limit_rate)
237         limit_bandwidth (res, &dltime, timer);
238
239       *len += res;
240       if (progress)
241         progress_update (progress, res, dltime);
242 #ifdef WINDOWS
243       if (use_expected && expected > 0)
244         ws_percenttitle (100.0 * (double)(*len) / (double)expected);
245 #endif
246     }
247   if (res < -1)
248     res = -1;
249
250  out:
251   if (progress)
252     progress_finish (progress, dltime);
253   if (elapsed)
254     *elapsed = dltime;
255   wtimer_delete (timer);
256
257   return res;
258 }
259 \f
260 /* Return a printed representation of the download rate, as
261    appropriate for the speed.  If PAD is non-zero, strings will be
262    padded to the width of 7 characters (xxxx.xx).  */
263 char *
264 retr_rate (long bytes, double msecs, int pad)
265 {
266   static char res[20];
267   static char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" };
268   int units = 0;
269
270   double dlrate = calc_rate (bytes, msecs, &units);
271   sprintf (res, pad ? "%7.2f %s" : "%.2f %s", dlrate, rate_names[units]);
272
273   return res;
274 }
275
276 /* Calculate the download rate and trim it as appropriate for the
277    speed.  Appropriate means that if rate is greater than 1K/s,
278    kilobytes are used, and if rate is greater than 1MB/s, megabytes
279    are used.
280
281    UNITS is zero for B/s, one for KB/s, two for MB/s, and three for
282    GB/s.  */
283 double
284 calc_rate (long bytes, double msecs, int *units)
285 {
286   double dlrate;
287
288   assert (msecs >= 0);
289   assert (bytes >= 0);
290
291   if (msecs == 0)
292     /* If elapsed time is exactly zero, it means we're under the
293        granularity of the timer.  This often happens on systems that
294        use time() for the timer.  */
295     msecs = wtimer_granularity ();
296
297   dlrate = (double)1000 * bytes / msecs;
298   if (dlrate < 1024.0)
299     *units = 0;
300   else if (dlrate < 1024.0 * 1024.0)
301     *units = 1, dlrate /= 1024.0;
302   else if (dlrate < 1024.0 * 1024.0 * 1024.0)
303     *units = 2, dlrate /= (1024.0 * 1024.0);
304   else
305     /* Maybe someone will need this, one day. */
306     *units = 3, dlrate /= (1024.0 * 1024.0 * 1024.0);
307
308   return dlrate;
309 }
310 \f
311 /* Maximum number of allowed redirections.  20 was chosen as a
312    "reasonable" value, which is low enough to not cause havoc, yet
313    high enough to guarantee that normal retrievals will not be hurt by
314    the check.  */
315
316 #define MAX_REDIRECTIONS 20
317
318 #define SUSPEND_POST_DATA do {                  \
319   post_data_suspended = 1;                      \
320   saved_post_data = opt.post_data;              \
321   saved_post_file_name = opt.post_file_name;    \
322   opt.post_data = NULL;                         \
323   opt.post_file_name = NULL;                    \
324 } while (0)
325
326 #define RESTORE_POST_DATA do {                          \
327   if (post_data_suspended)                              \
328     {                                                   \
329       opt.post_data = saved_post_data;                  \
330       opt.post_file_name = saved_post_file_name;        \
331       post_data_suspended = 0;                          \
332     }                                                   \
333 } while (0)
334
335 static char *getproxy PARAMS ((struct url *));
336
337 /* Retrieve the given URL.  Decides which loop to call -- HTTP, FTP,
338    FTP, proxy, etc.  */
339
340 /* #### This function should be rewritten so it doesn't return from
341    multiple points. */
342
343 uerr_t
344 retrieve_url (const char *origurl, char **file, char **newloc,
345               const char *refurl, int *dt)
346 {
347   uerr_t result;
348   char *url;
349   int location_changed, dummy;
350   char *mynewloc, *proxy;
351   struct url *u, *proxy_url;
352   int up_error_code;            /* url parse error code */
353   char *local_file;
354   int redirection_count = 0;
355
356   int post_data_suspended = 0;
357   char *saved_post_data = NULL;
358   char *saved_post_file_name = NULL;
359
360   /* If dt is NULL, use local storage.  */
361   if (!dt)
362     {
363       dt = &dummy;
364       dummy = 0;
365     }
366   url = xstrdup (origurl);
367   if (newloc)
368     *newloc = NULL;
369   if (file)
370     *file = NULL;
371
372   u = url_parse (url, &up_error_code);
373   if (!u)
374     {
375       logprintf (LOG_NOTQUIET, "%s: %s.\n", url, url_error (up_error_code));
376       xfree (url);
377       return URLERROR;
378     }
379
380   if (!refurl)
381     refurl = opt.referer;
382
383  redirected:
384
385   result = NOCONERROR;
386   mynewloc = NULL;
387   local_file = NULL;
388   proxy_url = NULL;
389
390   proxy = getproxy (u);
391   if (proxy)
392     {
393       /* Parse the proxy URL.  */
394       proxy_url = url_parse (proxy, &up_error_code);
395       if (!proxy_url)
396         {
397           logprintf (LOG_NOTQUIET, _("Error parsing proxy URL %s: %s.\n"),
398                      proxy, url_error (up_error_code));
399           xfree (url);
400           RESTORE_POST_DATA;
401           return PROXERR;
402         }
403       if (proxy_url->scheme != SCHEME_HTTP && proxy_url->scheme != u->scheme)
404         {
405           logprintf (LOG_NOTQUIET, _("Error in proxy URL %s: Must be HTTP.\n"), proxy);
406           url_free (proxy_url);
407           xfree (url);
408           RESTORE_POST_DATA;
409           return PROXERR;
410         }
411     }
412
413   if (u->scheme == SCHEME_HTTP
414 #ifdef HAVE_SSL
415       || u->scheme == SCHEME_HTTPS
416 #endif
417       || (proxy_url && proxy_url->scheme == SCHEME_HTTP))
418     {
419       result = http_loop (u, &mynewloc, &local_file, refurl, dt, proxy_url);
420     }
421   else if (u->scheme == SCHEME_FTP)
422     {
423       /* If this is a redirection, we must not allow recursive FTP
424          retrieval, so we save recursion to oldrec, and restore it
425          later.  */
426       int oldrec = opt.recursive;
427       if (redirection_count)
428         opt.recursive = 0;
429       result = ftp_loop (u, dt, proxy_url);
430       opt.recursive = oldrec;
431
432       /* There is a possibility of having HTTP being redirected to
433          FTP.  In these cases we must decide whether the text is HTML
434          according to the suffix.  The HTML suffixes are `.html',
435          `.htm' and a few others, case-insensitive.  */
436       if (redirection_count && local_file && u->scheme == SCHEME_FTP)
437         {
438           if (has_html_suffix_p (local_file))
439             *dt |= TEXTHTML;
440         }
441     }
442
443   if (proxy_url)
444     {
445       url_free (proxy_url);
446       proxy_url = NULL;
447     }
448
449   location_changed = (result == NEWLOCATION);
450   if (location_changed)
451     {
452       char *construced_newloc;
453       struct url *newloc_parsed;
454
455       assert (mynewloc != NULL);
456
457       if (local_file)
458         xfree (local_file);
459
460       /* The HTTP specs only allow absolute URLs to appear in
461          redirects, but a ton of boneheaded webservers and CGIs out
462          there break the rules and use relative URLs, and popular
463          browsers are lenient about this, so wget should be too. */
464       construced_newloc = uri_merge (url, mynewloc);
465       xfree (mynewloc);
466       mynewloc = construced_newloc;
467
468       /* Now, see if this new location makes sense. */
469       newloc_parsed = url_parse (mynewloc, &up_error_code);
470       if (!newloc_parsed)
471         {
472           logprintf (LOG_NOTQUIET, "%s: %s.\n", mynewloc,
473                      url_error (up_error_code));
474           url_free (u);
475           xfree (url);
476           xfree (mynewloc);
477           RESTORE_POST_DATA;
478           return result;
479         }
480
481       /* Now mynewloc will become newloc_parsed->url, because if the
482          Location contained relative paths like .././something, we
483          don't want that propagating as url.  */
484       xfree (mynewloc);
485       mynewloc = xstrdup (newloc_parsed->url);
486
487       /* Check for max. number of redirections.  */
488       if (++redirection_count > MAX_REDIRECTIONS)
489         {
490           logprintf (LOG_NOTQUIET, _("%d redirections exceeded.\n"),
491                      MAX_REDIRECTIONS);
492           url_free (newloc_parsed);
493           url_free (u);
494           xfree (url);
495           xfree (mynewloc);
496           RESTORE_POST_DATA;
497           return WRONGCODE;
498         }
499
500       xfree (url);
501       url = mynewloc;
502       url_free (u);
503       u = newloc_parsed;
504
505       /* If we're being redirected from POST, we don't want to POST
506          again.  Many requests answer POST with a redirection to an
507          index page; that redirection is clearly a GET.  We "suspend"
508          POST data for the duration of the redirections, and restore
509          it when we're done. */
510       if (!post_data_suspended)
511         SUSPEND_POST_DATA;
512
513       goto redirected;
514     }
515
516   if (local_file)
517     {
518       if (*dt & RETROKF)
519         {
520           register_download (u->url, local_file);
521           if (redirection_count && 0 != strcmp (origurl, u->url))
522             register_redirection (origurl, u->url);
523           if (*dt & TEXTHTML)
524             register_html (u->url, local_file);
525         }
526     }
527
528   if (file)
529     *file = local_file ? local_file : NULL;
530   else
531     FREE_MAYBE (local_file);
532
533   url_free (u);
534
535   if (redirection_count)
536     {
537       if (newloc)
538         *newloc = url;
539       else
540         xfree (url);
541     }
542   else
543     {
544       if (newloc)
545         *newloc = NULL;
546       xfree (url);
547     }
548
549   ++global_download_count;
550   RESTORE_POST_DATA;
551
552   return result;
553 }
554
555 /* Find the URLs in the file and call retrieve_url() for each of
556    them.  If HTML is non-zero, treat the file as HTML, and construct
557    the URLs accordingly.
558
559    If opt.recursive is set, call recursive_retrieve() for each file.  */
560 uerr_t
561 retrieve_from_file (const char *file, int html, int *count)
562 {
563   uerr_t status;
564   struct urlpos *url_list, *cur_url;
565
566   url_list = (html ? get_urls_html (file, NULL, NULL)
567               : get_urls_file (file));
568   status = RETROK;             /* Suppose everything is OK.  */
569   *count = 0;                  /* Reset the URL count.  */
570
571   for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count)
572     {
573       char *filename = NULL, *new_file = NULL;
574       int dt;
575
576       if (cur_url->ignore_when_downloading)
577         continue;
578
579       if (downloaded_exceeds_quota ())
580         {
581           status = QUOTEXC;
582           break;
583         }
584       if (opt.recursive && cur_url->url->scheme != SCHEME_FTP)
585         status = retrieve_tree (cur_url->url->url);
586       else
587         status = retrieve_url (cur_url->url->url, &filename, &new_file, NULL, &dt);
588
589       if (filename && opt.delete_after && file_exists_p (filename))
590         {
591           DEBUGP (("Removing file due to --delete-after in"
592                    " retrieve_from_file():\n"));
593           logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
594           if (unlink (filename))
595             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
596           dt &= ~RETROKF;
597         }
598
599       FREE_MAYBE (new_file);
600       FREE_MAYBE (filename);
601     }
602
603   /* Free the linked list of URL-s.  */
604   free_urlpos (url_list);
605
606   return status;
607 }
608
609 /* Print `giving up', or `retrying', depending on the impending
610    action.  N1 and N2 are the attempt number and the attempt limit.  */
611 void
612 printwhat (int n1, int n2)
613 {
614   logputs (LOG_VERBOSE, (n1 == n2) ? _("Giving up.\n\n") : _("Retrying.\n\n"));
615 }
616
617 /* Increment opt.downloaded by BY_HOW_MUCH.  If an overflow occurs,
618    set opt.downloaded_overflow to 1. */
619 void
620 downloaded_increase (unsigned long by_how_much)
621 {
622   VERY_LONG_TYPE old;
623   if (opt.downloaded_overflow)
624     return;
625   old = opt.downloaded;
626   opt.downloaded += by_how_much;
627   if (opt.downloaded < old)     /* carry flag, where are you when I
628                                    need you? */
629     {
630       /* Overflow. */
631       opt.downloaded_overflow = 1;
632       opt.downloaded = ~((VERY_LONG_TYPE)0);
633     }
634 }
635
636 /* Return non-zero if the downloaded amount of bytes exceeds the
637    desired quota.  If quota is not set or if the amount overflowed, 0
638    is returned. */
639 int
640 downloaded_exceeds_quota (void)
641 {
642   if (!opt.quota)
643     return 0;
644   if (opt.downloaded_overflow)
645     /* We don't really know.  (Wildly) assume not. */
646     return 0;
647
648   return opt.downloaded > opt.quota;
649 }
650
651 /* If opt.wait or opt.waitretry are specified, and if certain
652    conditions are met, sleep the appropriate number of seconds.  See
653    the documentation of --wait and --waitretry for more information.
654
655    COUNT is the count of current retrieval, beginning with 1. */
656
657 void
658 sleep_between_retrievals (int count)
659 {
660   static int first_retrieval = 1;
661
662   if (first_retrieval)
663     {
664       /* Don't sleep before the very first retrieval. */
665       first_retrieval = 0;
666       return;
667     }
668
669   if (opt.waitretry && count > 1)
670     {
671       /* If opt.waitretry is specified and this is a retry, wait for
672          COUNT-1 number of seconds, or for opt.waitretry seconds.  */
673       if (count <= opt.waitretry)
674         sleep (count - 1);
675       else
676         usleep (1000000L * opt.waitretry);
677     }
678   else if (opt.wait)
679     {
680       if (!opt.random_wait || count > 1)
681         /* If random-wait is not specified, or if we are sleeping
682            between retries of the same download, sleep the fixed
683            interval.  */
684         usleep (1000000L * opt.wait);
685       else
686         {
687           /* Sleep a random amount of time averaging in opt.wait
688              seconds.  The sleeping amount ranges from 0 to
689              opt.wait*2, inclusive.  */
690           double waitsecs = 2 * opt.wait * random_float ();
691           DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n",
692                    opt.wait, waitsecs));
693           usleep (1000000L * waitsecs);
694         }
695     }
696 }
697
698 /* Free the linked list of urlpos.  */
699 void
700 free_urlpos (struct urlpos *l)
701 {
702   while (l)
703     {
704       struct urlpos *next = l->next;
705       if (l->url)
706         url_free (l->url);
707       FREE_MAYBE (l->local_name);
708       xfree (l);
709       l = next;
710     }
711 }
712
713 /* Rotate FNAME opt.backups times */
714 void
715 rotate_backups(const char *fname)
716 {
717   int maxlen = strlen (fname) + 1 + numdigit (opt.backups) + 1;
718   char *from = (char *)alloca (maxlen);
719   char *to = (char *)alloca (maxlen);
720   struct stat sb;
721   int i;
722
723   if (stat (fname, &sb) == 0)
724     if (S_ISREG (sb.st_mode) == 0)
725       return;
726
727   for (i = opt.backups; i > 1; i--)
728     {
729       sprintf (from, "%s.%d", fname, i - 1);
730       sprintf (to, "%s.%d", fname, i);
731       rename (from, to);
732     }
733
734   sprintf (to, "%s.%d", fname, 1);
735   rename(fname, to);
736 }
737
738 static int no_proxy_match PARAMS ((const char *, const char **));
739
740 /* Return the URL of the proxy appropriate for url U.  */
741
742 static char *
743 getproxy (struct url *u)
744 {
745   char *proxy = NULL;
746   char *rewritten_url;
747   static char rewritten_storage[1024];
748
749   if (!opt.use_proxy)
750     return NULL;
751   if (!no_proxy_match (u->host, (const char **)opt.no_proxy))
752     return NULL;
753
754   switch (u->scheme)
755     {
756     case SCHEME_HTTP:
757       proxy = opt.http_proxy ? opt.http_proxy : getenv ("http_proxy");
758       break;
759 #ifdef HAVE_SSL
760     case SCHEME_HTTPS:
761       proxy = opt.https_proxy ? opt.https_proxy : getenv ("https_proxy");
762       break;
763 #endif
764     case SCHEME_FTP:
765       proxy = opt.ftp_proxy ? opt.ftp_proxy : getenv ("ftp_proxy");
766       break;
767     case SCHEME_INVALID:
768       break;
769     }
770   if (!proxy || !*proxy)
771     return NULL;
772
773   /* Handle shorthands.  `rewritten_storage' is a kludge to allow
774      getproxy() to return static storage. */
775   rewritten_url = rewrite_shorthand_url (proxy);
776   if (rewritten_url)
777     {
778       strncpy (rewritten_storage, rewritten_url, sizeof(rewritten_storage));
779       rewritten_storage[sizeof (rewritten_storage) - 1] = '\0';
780       proxy = rewritten_storage;
781     }
782
783   return proxy;
784 }
785
786 /* Should a host be accessed through proxy, concerning no_proxy?  */
787 int
788 no_proxy_match (const char *host, const char **no_proxy)
789 {
790   if (!no_proxy)
791     return 1;
792   else
793     return !sufmatch (no_proxy, host);
794 }