]> sjero.net Git - wget/blob - src/init.c
[svn] Doc typo fix.
[wget] / src / init.c
1 /* Reading/parsing the initialization file.
2    Copyright (C) 2005 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
9 (at 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 <sys/types.h>
34 #include <stdlib.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # include <strings.h>
42 #endif
43 #include <errno.h>
44
45 #ifdef HAVE_PWD_H
46 # include <pwd.h>
47 #endif
48 #include <assert.h>
49
50 #include "wget.h"
51 #include "utils.h"
52 #include "init.h"
53 #include "host.h"
54 #include "netrc.h"
55 #include "progress.h"
56 #include "recur.h"              /* for INFINITE_RECURSION */
57 #include "convert.h"            /* for convert_cleanup */
58 #include "res.h"                /* for res_cleanup */
59
60 #ifndef errno
61 extern int errno;
62 #endif
63
64 /* We want tilde expansion enabled only when reading `.wgetrc' lines;
65    otherwise, it will be performed by the shell.  This variable will
66    be set by the wgetrc-reading function.  */
67
68 static int enable_tilde_expansion;
69
70
71 #define CMD_DECLARE(func) static int func \
72   PARAMS ((const char *, const char *, void *))
73
74 CMD_DECLARE (cmd_boolean);
75 CMD_DECLARE (cmd_bytes);
76 CMD_DECLARE (cmd_bytes_large);
77 CMD_DECLARE (cmd_directory_vector);
78 CMD_DECLARE (cmd_lockable_boolean);
79 CMD_DECLARE (cmd_number);
80 CMD_DECLARE (cmd_number_inf);
81 CMD_DECLARE (cmd_string);
82 CMD_DECLARE (cmd_file);
83 CMD_DECLARE (cmd_directory);
84 CMD_DECLARE (cmd_time);
85 CMD_DECLARE (cmd_vector);
86
87 #ifdef HAVE_SSL
88 CMD_DECLARE (cmd_spec_cert_type);
89 #endif
90 CMD_DECLARE (cmd_spec_dirstruct);
91 CMD_DECLARE (cmd_spec_header);
92 CMD_DECLARE (cmd_spec_htmlify);
93 CMD_DECLARE (cmd_spec_mirror);
94 CMD_DECLARE (cmd_spec_prefer_family);
95 CMD_DECLARE (cmd_spec_progress);
96 CMD_DECLARE (cmd_spec_recursive);
97 CMD_DECLARE (cmd_spec_restrict_file_names);
98 #ifdef HAVE_SSL
99 CMD_DECLARE (cmd_spec_secure_protocol);
100 #endif
101 CMD_DECLARE (cmd_spec_timeout);
102 CMD_DECLARE (cmd_spec_useragent);
103
104 /* List of recognized commands, each consisting of name, place and
105    function.  When adding a new command, simply add it to the list,
106    but be sure to keep the list sorted alphabetically, as
107    command_by_name depends on it.  Also, be sure to add any entries
108    that allocate memory (e.g. cmd_string and cmd_vector guys) to the
109    cleanup() function below. */
110
111 static struct {
112   const char *name;
113   void *place;
114   int (*action) PARAMS ((const char *, const char *, void *));
115 } commands[] = {
116   { "accept",           &opt.accepts,           cmd_vector },
117   { "addhostdir",       &opt.add_hostdir,       cmd_boolean },
118   { "alwaysrest",       &opt.always_rest,       cmd_boolean }, /* deprecated */
119   { "background",       &opt.background,        cmd_boolean },
120   { "backupconverted",  &opt.backup_converted,  cmd_boolean },
121   { "backups",          &opt.backups,           cmd_number },
122   { "base",             &opt.base_href,         cmd_string },
123   { "bindaddress",      &opt.bind_address,      cmd_string },
124 #ifdef HAVE_SSL
125   { "cacertificate",    &opt.ca_cert,           cmd_file },
126 #endif
127   { "cache",            &opt.allow_cache,       cmd_boolean },
128 #ifdef HAVE_SSL
129   { "cadirectory",      &opt.ca_directory,      cmd_directory },
130   { "certificate",      &opt.cert_file,         cmd_file },
131   { "certificatekey",   &opt.cert_key,          cmd_file },
132   { "certificatetype",  &opt.cert_type,         cmd_spec_cert_type },
133   { "checkcertificate", &opt.check_cert,        cmd_boolean },
134 #endif
135   { "connecttimeout",   &opt.connect_timeout,   cmd_time },
136   { "continue",         &opt.always_rest,       cmd_boolean },
137   { "convertlinks",     &opt.convert_links,     cmd_boolean },
138   { "cookies",          &opt.cookies,           cmd_boolean },
139   { "cutdirs",          &opt.cut_dirs,          cmd_number },
140 #ifdef ENABLE_DEBUG
141   { "debug",            &opt.debug,             cmd_boolean },
142 #endif
143   { "deleteafter",      &opt.delete_after,      cmd_boolean },
144   { "dirprefix",        &opt.dir_prefix,        cmd_directory },
145   { "dirstruct",        NULL,                   cmd_spec_dirstruct },
146   { "dnscache",         &opt.dns_cache,         cmd_boolean },
147   { "dnstimeout",       &opt.dns_timeout,       cmd_time },
148   { "domains",          &opt.domains,           cmd_vector },
149   { "dotbytes",         &opt.dot_bytes,         cmd_bytes },
150   { "dotsinline",       &opt.dots_in_line,      cmd_number },
151   { "dotspacing",       &opt.dot_spacing,       cmd_number },
152   { "dotstyle",         &opt.dot_style,         cmd_string },
153 #ifdef HAVE_SSL
154   { "egdfile",          &opt.egd_file,          cmd_file },
155 #endif
156   { "excludedirectories", &opt.excludes,        cmd_directory_vector },
157   { "excludedomains",   &opt.exclude_domains,   cmd_vector },
158   { "followftp",        &opt.follow_ftp,        cmd_boolean },
159   { "followtags",       &opt.follow_tags,       cmd_vector },
160   { "forcehtml",        &opt.force_html,        cmd_boolean },
161   { "ftppasswd",        &opt.ftp_pass,          cmd_string },
162   { "ftpproxy",         &opt.ftp_proxy,         cmd_string },
163   { "glob",             &opt.ftp_glob,          cmd_boolean },
164   { "header",           &opt.user_headers,      cmd_spec_header },
165   { "htmlextension",    &opt.html_extension,    cmd_boolean },
166   { "htmlify",          NULL,                   cmd_spec_htmlify },
167   { "httpkeepalive",    &opt.http_keep_alive,   cmd_boolean },
168   { "httppasswd",       &opt.http_passwd,       cmd_string },
169   { "httpproxy",        &opt.http_proxy,        cmd_string },
170   { "httpsproxy",       &opt.https_proxy,       cmd_string },
171   { "httpuser",         &opt.http_user,         cmd_string },
172   { "ignorelength",     &opt.ignore_length,     cmd_boolean },
173   { "ignoretags",       &opt.ignore_tags,       cmd_vector },
174   { "includedirectories", &opt.includes,        cmd_directory_vector },
175 #ifdef ENABLE_IPV6
176   { "inet4only",        &opt.ipv4_only,         cmd_boolean },
177   { "inet6only",        &opt.ipv6_only,         cmd_boolean },
178 #endif
179   { "input",            &opt.input_filename,    cmd_file },
180   { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
181   { "killlonger",       &opt.kill_longer,       cmd_boolean },
182   { "limitrate",        &opt.limit_rate,        cmd_bytes },
183   { "loadcookies",      &opt.cookies_input,     cmd_file },
184   { "logfile",          &opt.lfilename,         cmd_file },
185   { "login",            &opt.ftp_acc,           cmd_string },
186   { "mirror",           NULL,                   cmd_spec_mirror },
187   { "netrc",            &opt.netrc,             cmd_boolean },
188   { "noclobber",        &opt.noclobber,         cmd_boolean },
189   { "noparent",         &opt.no_parent,         cmd_boolean },
190   { "noproxy",          &opt.no_proxy,          cmd_vector },
191   { "numtries",         &opt.ntry,              cmd_number_inf },/* deprecated*/
192   { "outputdocument",   &opt.output_document,   cmd_file },
193   { "pagerequisites",   &opt.page_requisites,   cmd_boolean },
194   { "passiveftp",       &opt.ftp_pasv,          cmd_lockable_boolean },
195   { "postdata",         &opt.post_data,         cmd_string },
196   { "postfile",         &opt.post_file_name,    cmd_file },
197   { "preferfamily",     NULL,                   cmd_spec_prefer_family },
198   { "preservepermissions", &opt.preserve_perm,  cmd_boolean },
199   { "progress",         &opt.progress_type,     cmd_spec_progress },
200   { "protocoldirectories", &opt.protocol_directories, cmd_boolean },
201   { "proxypasswd",      &opt.proxy_passwd,      cmd_string },
202   { "proxyuser",        &opt.proxy_user,        cmd_string },
203   { "quiet",            &opt.quiet,             cmd_boolean },
204   { "quota",            &opt.quota,             cmd_bytes_large },
205   { "randomwait",       &opt.random_wait,       cmd_boolean },
206   { "readtimeout",      &opt.read_timeout,      cmd_time },
207   { "reclevel",         &opt.reclevel,          cmd_number_inf },
208   { "recursive",        NULL,                   cmd_spec_recursive },
209   { "referer",          &opt.referer,           cmd_string },
210   { "reject",           &opt.rejects,           cmd_vector },
211   { "relativeonly",     &opt.relative_only,     cmd_boolean },
212   { "removelisting",    &opt.remove_listing,    cmd_boolean },
213   { "restrictfilenames", NULL,                  cmd_spec_restrict_file_names },
214   { "retrsymlinks",     &opt.retr_symlinks,     cmd_boolean },
215   { "retryconnrefused", &opt.retry_connrefused, cmd_boolean },
216   { "robots",           &opt.use_robots,        cmd_boolean },
217   { "savecookies",      &opt.cookies_output,    cmd_file },
218   { "saveheaders",      &opt.save_headers,      cmd_boolean },
219 #ifdef HAVE_SSL
220   { "secureprotocol",   &opt.secure_protocol,   cmd_spec_secure_protocol },
221 #endif
222   { "serverresponse",   &opt.server_response,   cmd_boolean },
223   { "spanhosts",        &opt.spanhost,          cmd_boolean },
224   { "spider",           &opt.spider,            cmd_boolean },
225   { "strictcomments",   &opt.strict_comments,   cmd_boolean },
226   { "timeout",          NULL,                   cmd_spec_timeout },
227   { "timestamping",     &opt.timestamping,      cmd_boolean },
228   { "tries",            &opt.ntry,              cmd_number_inf },
229   { "useproxy",         &opt.use_proxy,         cmd_boolean },
230   { "useragent",        NULL,                   cmd_spec_useragent },
231   { "verbose",          &opt.verbose,           cmd_boolean },
232   { "wait",             &opt.wait,              cmd_time },
233   { "waitretry",        &opt.waitretry,         cmd_time }
234 };
235
236 /* Look up CMDNAME in the commands[] and return its position in the
237    array.  If CMDNAME is not found, return -1.  */
238
239 static int
240 command_by_name (const char *cmdname)
241 {
242   /* Use binary search for speed.  Wget has ~100 commands, which
243      guarantees a worst case performance of 7 string comparisons.  */
244   int lo = 0, hi = countof (commands) - 1;
245
246   while (lo <= hi)
247     {
248       int mid = (lo + hi) >> 1;
249       int cmp = strcasecmp (cmdname, commands[mid].name);
250       if (cmp < 0)
251         hi = mid - 1;
252       else if (cmp > 0)
253         lo = mid + 1;
254       else
255         return mid;
256     }
257   return -1;
258 }
259 \f
260 /* Reset the variables to default values.  */
261 static void
262 defaults (void)
263 {
264   char *tmp;
265
266   /* Most of the default values are 0.  Just reset everything, and
267      fill in the non-zero values.  Note that initializing pointers to
268      NULL this way is technically illegal, but porting Wget to a
269      machine where NULL is not all-zero bit pattern will be the least
270      of the implementors' worries.  */
271   xzero (opt);
272
273   opt.cookies = 1;
274   opt.verbose = -1;
275   opt.ntry = 20;
276   opt.reclevel = 5;
277   opt.add_hostdir = 1;
278   opt.ftp_acc  = xstrdup ("anonymous");
279   opt.ftp_pass = xstrdup ("-wget@");
280   opt.netrc = 1;
281   opt.ftp_glob = 1;
282   opt.htmlify = 1;
283   opt.http_keep_alive = 1;
284   opt.use_proxy = 1;
285   tmp = getenv ("no_proxy");
286   if (tmp)
287     opt.no_proxy = sepstring (tmp);
288   opt.allow_cache = 1;
289
290   opt.read_timeout = 900;
291   opt.use_robots = 1;
292
293   opt.remove_listing = 1;
294
295   opt.dot_bytes = 1024;
296   opt.dot_spacing = 10;
297   opt.dots_in_line = 50;
298
299   opt.dns_cache = 1;
300   opt.ftp_pasv = 1;
301
302 #ifdef HAVE_SSL
303   opt.check_cert = 1;
304 #endif
305
306   /* The default for file name restriction defaults to the OS type. */
307 #if !defined(WINDOWS) && !defined(__CYGWIN__)
308   opt.restrict_files_os = restrict_unix;
309 #else
310   opt.restrict_files_os = restrict_windows;
311 #endif
312   opt.restrict_files_ctrl = 1;
313 }
314 \f
315 /* Return the user's home directory (strdup-ed), or NULL if none is
316    found.  */
317 char *
318 home_dir (void)
319 {
320   char *home = getenv ("HOME");
321
322   if (!home)
323     {
324 #ifndef WINDOWS
325       /* If HOME is not defined, try getting it from the password
326          file.  */
327       struct passwd *pwd = getpwuid (getuid ());
328       if (!pwd || !pwd->pw_dir)
329         return NULL;
330       home = pwd->pw_dir;
331 #else  /* WINDOWS */
332       /* Under Windows, if $HOME isn't defined, use the directory where
333          `wget.exe' resides.  */
334       home = ws_mypath ();
335 #endif /* WINDOWS */
336     }
337
338   return home ? xstrdup (home) : NULL;
339 }
340
341 /* Return the path to the user's .wgetrc.  This is either the value of
342    `WGETRC' environment variable, or `$HOME/.wgetrc'.
343
344    If the `WGETRC' variable exists but the file does not exist, the
345    function will exit().  */
346 static char *
347 wgetrc_file_name (void)
348 {
349   char *env, *home;
350   char *file = NULL;
351
352   /* Try the environment.  */
353   env = getenv ("WGETRC");
354   if (env && *env)
355     {
356       if (!file_exists_p (env))
357         {
358           fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"),
359                    exec_name, env);
360           exit (1);
361         }
362       return xstrdup (env);
363     }
364
365   /* If that failed, try $HOME/.wgetrc.  */
366   home = home_dir ();
367   if (home)
368     file = aprintf ("%s/.wgetrc", home);
369   xfree_null (home);
370
371 #ifdef WINDOWS
372   /* Under Windows, if we still haven't found .wgetrc, look for the file
373      `wget.ini' in the directory where `wget.exe' resides; we do this for
374      backward compatibility with previous versions of Wget.
375      SYSTEM_WGETRC should not be defined under WINDOWS.  */
376   if (!file || !file_exists_p (file))
377     {
378       xfree_null (file);
379       file = NULL;
380       home = ws_mypath ();
381       if (home)
382         file = aprintf ("%s/wget.ini", home);
383     }
384 #endif /* WINDOWS */
385
386   if (!file)
387     return NULL;
388   if (!file_exists_p (file))
389     {
390       xfree (file);
391       return NULL;
392     }
393   return file;
394 }
395
396 static int parse_line PARAMS ((const char *, char **, char **, int *));
397 static int setval_internal PARAMS ((int, const char *, const char *));
398
399 /* Initialize variables from a wgetrc file.  */
400
401 static void
402 run_wgetrc (const char *file)
403 {
404   FILE *fp;
405   char *line;
406   int ln;
407
408   fp = fopen (file, "rb");
409   if (!fp)
410     {
411       fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
412                file, strerror (errno));
413       return;
414     }
415   enable_tilde_expansion = 1;
416   ln = 1;
417   while ((line = read_whole_line (fp)) != NULL)
418     {
419       char *com, *val;
420       int comind, status;
421
422       /* Parse the line.  */
423       status = parse_line (line, &com, &val, &comind);
424       xfree (line);
425       /* If everything is OK, set the value.  */
426       if (status == 1)
427         {
428           if (!setval_internal (comind, com, val))
429             fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
430                      file, ln);
431           xfree (com);
432           xfree (val);
433         }
434       else if (status == 0)
435         fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
436                  file, ln);
437       ++ln;
438     }
439   enable_tilde_expansion = 0;
440   fclose (fp);
441 }
442
443 /* Initialize the defaults and run the system wgetrc and user's own
444    wgetrc.  */
445 void
446 initialize (void)
447 {
448   char *file;
449
450   /* Load the hard-coded defaults.  */
451   defaults ();
452
453   /* If SYSTEM_WGETRC is defined, use it.  */
454 #ifdef SYSTEM_WGETRC
455   if (file_exists_p (SYSTEM_WGETRC))
456     run_wgetrc (SYSTEM_WGETRC);
457 #endif
458   /* Override it with your own, if one exists.  */
459   file = wgetrc_file_name ();
460   if (!file)
461     return;
462   /* #### We should canonicalize `file' and SYSTEM_WGETRC with
463      something like realpath() before comparing them with `strcmp'  */
464 #ifdef SYSTEM_WGETRC
465   if (!strcmp (file, SYSTEM_WGETRC))
466     {
467       fprintf (stderr, _("\
468 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
469                exec_name, file);
470     }
471   else
472 #endif
473     run_wgetrc (file);
474   xfree (file);
475   return;
476 }
477 \f
478 /* Remove dashes and underscores from S, modifying S in the
479    process. */
480
481 static void
482 dehyphen (char *s)
483 {
484   char *t = s;                  /* t - tortoise */
485   char *h = s;                  /* h - hare     */
486   while (*h)
487     if (*h == '_' || *h == '-')
488       ++h;
489     else
490       *t++ = *h++;
491   *t = '\0';
492 }
493
494 /* Parse the line pointed by line, with the syntax:
495    <sp>* command <sp>* = <sp>* value <sp>*
496    Uses malloc to allocate space for command and value.
497    If the line is invalid, data is freed and 0 is returned.
498
499    Return values:
500     1 - success
501     0 - error
502    -1 - empty
503
504    In case of success, *COM and *VAL point to freshly allocated
505    strings, and *COMIND points to com's index.  In case of error or
506    empty line, those values are unaffected.  */
507
508 static int
509 parse_line (const char *line, char **com, char **val, int *comind)
510 {
511   const char *p;
512   const char *end = line + strlen (line);
513   const char *cmdstart, *cmdend;
514   const char *valstart, *valend;
515
516   char *cmdcopy;
517   int ind;
518
519   /* Skip leading and trailing whitespace.  */
520   while (*line && ISSPACE (*line))
521     ++line;
522   while (end > line && ISSPACE (end[-1]))
523     --end;
524
525   /* Skip empty lines and comments.  */
526   if (!*line || *line == '#')
527     return -1;
528
529   p = line;
530
531   cmdstart = p;
532   while (p < end && (ISALPHA (*p) || *p == '_' || *p == '-'))
533     ++p;
534   cmdend = p;
535
536   /* Skip '=', as well as any space before or after it. */
537   while (p < end && ISSPACE (*p))
538     ++p;
539   if (p == end || *p != '=')
540     return 0;
541   ++p;
542   while (p < end && ISSPACE (*p))
543     ++p;
544
545   valstart = p;
546   valend   = end;
547
548   /* The line now known to be syntactically correct.  Check whether
549      the command is valid.  */
550   BOUNDED_TO_ALLOCA (cmdstart, cmdend, cmdcopy);
551   dehyphen (cmdcopy);
552   ind = command_by_name (cmdcopy);
553   if (ind == -1)
554     return 0;
555
556   /* The command is valid.  Now fill in the values and report success
557      to the caller.  */
558   *comind = ind;
559   *com = strdupdelim (cmdstart, cmdend);
560   *val = strdupdelim (valstart, valend);
561   return 1;
562 }
563
564 /* Run commands[comind].action. */
565
566 static int
567 setval_internal (int comind, const char *com, const char *val)
568 {
569   assert (0 <= comind && comind < countof (commands));
570   DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
571   return ((*commands[comind].action) (com, val, commands[comind].place));
572 }
573
574 /* Run command COM with value VAL.  If running the command produces an
575    error, report the error and exit.
576
577    This is intended to be called from main() to modify Wget's behavior
578    through command-line switches.  Since COM is hard-coded in main(),
579    it is not canonicalized, and this aborts when COM is not found.
580
581    If COMIND's are exported to init.h, this function will be changed
582    to accept COMIND directly.  */
583
584 void
585 setoptval (const char *com, const char *val)
586 {
587   assert (val != NULL);
588   if (!setval_internal (command_by_name (com), com, val))
589     exit (2);
590 }
591
592 /* Parse OPT into command and value and run it.  For example,
593    run_command("foo=bar") is equivalent to setoptval("foo", "bar").
594    This is used by the `--execute' flag in main.c.  */
595
596 void
597 run_command (const char *opt)
598 {
599   char *com, *val;
600   int comind;
601   int status = parse_line (opt, &com, &val, &comind);
602   if (status == 1)
603     {
604       if (!setval_internal (comind, com, val))
605         exit (2);
606       xfree (com);
607       xfree (val);
608     }
609   else if (status == 0)
610     {
611       fprintf (stderr, _("%s: Invalid --execute command `%s'\n"),
612                exec_name, opt);
613       exit (2);
614     }
615 }
616 \f
617 /* Generic helper functions, for use with `commands'. */
618
619 #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0')
620
621 #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0)        \
622                          && TOLOWER((p)[1]) == (c1)     \
623                          && (p)[2] == '\0')
624
625 #define CMP3(p, c0, c1, c2) (TOLOWER((p)[0]) == (c0)    \
626                      && TOLOWER((p)[1]) == (c1)         \
627                      && TOLOWER((p)[2]) == (c2)         \
628                      && (p)[3] == '\0')
629
630
631 /* Store the boolean value from VAL to PLACE.  COM is ignored,
632    except for error messages.  */
633 static int
634 cmd_boolean (const char *com, const char *val, void *place)
635 {
636   int bool_value;
637
638   if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
639     /* "on", "yes" and "1" mean true. */
640     bool_value = 1;
641   else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
642     /* "off", "no" and "0" mean false. */
643     bool_value = 0;
644   else
645     {
646       fprintf (stderr,
647                _("%s: %s: Invalid boolean `%s', use `on' or `off'.\n"),
648                exec_name, com, val);
649       return 0;
650     }
651
652   *(int *)place = bool_value;
653   return 1;
654 }
655
656 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to PLACE.
657    COM is ignored, except for error messages.  Values 2 and -1
658    indicate that once defined, the value may not be changed by
659    successive wgetrc files or command-line arguments.
660
661    Values: 2 - Enable a particular option for good ("always")
662            1 - Enable an option ("on")
663            0 - Disable an option ("off")
664           -1 - Disable an option for good ("never") */
665 static int
666 cmd_lockable_boolean (const char *com, const char *val, void *place)
667 {
668   int lockable_boolean_value;
669
670   int oldval = *(int *)place;
671
672   /*
673    * If a config file said "always" or "never", don't allow command line
674    * arguments to override the config file.
675    */
676   if (oldval == -1 || oldval == 2)
677     return 1;
678
679   if (0 == strcasecmp (val, "always") || CMP1 (val, '2'))
680     lockable_boolean_value = 2;
681   else if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
682     lockable_boolean_value = 1;
683   else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
684     lockable_boolean_value = 0;
685   else if (0 == strcasecmp (val, "never") || CMP2 (val, '-', '1'))
686     lockable_boolean_value = -1;
687   else
688     {
689       fprintf (stderr,
690                _("%s: %s: Invalid boolean `%s', use always, on, off, or never.\n"),
691                exec_name, com, val);
692       return 0;
693     }
694
695   *(int *)place = lockable_boolean_value;
696   return 1;
697 }
698
699 static int simple_atoi PARAMS ((const char *, const char *, int *));
700
701 /* Set the non-negative integer value from VAL to PLACE.  With
702    incorrect specification, the number remains unchanged.  */
703 static int
704 cmd_number (const char *com, const char *val, void *place)
705 {
706   if (!simple_atoi (val, val + strlen (val), place)
707       || *(int *) place < 0)
708     {
709       fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
710                exec_name, com, val);
711       return 0;
712     }
713   return 1;
714 }
715
716 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0.  */
717 static int
718 cmd_number_inf (const char *com, const char *val, void *place)
719 {
720   if (!strcasecmp (val, "inf"))
721     {
722       *(int *)place = 0;
723       return 1;
724     }
725   return cmd_number (com, val, place);
726 }
727
728 /* Copy (strdup) the string at COM to a new location and place a
729    pointer to *PLACE.  */
730 static int
731 cmd_string (const char *com, const char *val, void *place)
732 {
733   char **pstring = (char **)place;
734
735   xfree_null (*pstring);
736   *pstring = xstrdup (val);
737   return 1;
738 }
739
740 #ifndef WINDOWS
741 # define ISSEP(c) ((c) == '/')
742 #else
743 # define ISSEP(c) ((c) == '/' || (c) == '\\')
744 #endif
745
746 /* Like the above, but handles tilde-expansion when reading a user's
747    `.wgetrc'.  In that case, and if VAL begins with `~', the tilde
748    gets expanded to the user's home directory.  */
749 static int
750 cmd_file (const char *com, const char *val, void *place)
751 {
752   char **pstring = (char **)place;
753
754   xfree_null (*pstring);
755
756   /* #### If VAL is empty, perhaps should set *PLACE to NULL.  */
757
758   if (!enable_tilde_expansion || !(*val == '~' && ISSEP (val[1])))
759     {
760     noexpand:
761       *pstring = xstrdup (val);
762     }
763   else
764     {
765       int homelen;
766       char *home = home_dir ();
767       if (!home)
768         goto noexpand;
769
770       homelen = strlen (home);
771       while (homelen && ISSEP (home[homelen - 1]))
772         home[--homelen] = '\0';
773
774       /* Skip the leading "~/". */
775       for (++val; ISSEP (*val); val++)
776         ;
777
778       *pstring = concat_strings (home, "/", val, (char *) 0);
779     }
780
781 #ifdef WINDOWS
782   /* Convert "\" to "/". */
783   {
784     char *s;
785     for (s = *pstring; *s; s++)
786       if (*s == '\\')
787         *s = '/';
788   }
789 #endif
790   return 1;
791 }
792
793 /* Like cmd_file, but strips trailing '/' characters.  */
794 static int
795 cmd_directory (const char *com, const char *val, void *place)
796 {
797   char *s, *t;
798
799   /* Call cmd_file() for tilde expansion and separator
800      canonicalization (backslash -> slash under Windows).  These
801      things should perhaps be in a separate function.  */
802   if (!cmd_file (com, val, place))
803     return 0;
804
805   s = *(char **)place;
806   t = s + strlen (s);
807   while (t > s && *--t == '/')
808     *t = '\0';
809
810   return 1;
811 }
812
813 /* Split VAL by space to a vector of values, and append those values
814    to vector pointed to by the PLACE argument.  If VAL is empty, the
815    PLACE vector is cleared instead.  */
816
817 static int
818 cmd_vector (const char *com, const char *val, void *place)
819 {
820   char ***pvec = (char ***)place;
821
822   if (*val)
823     *pvec = merge_vecs (*pvec, sepstring (val));
824   else
825     {
826       free_vec (*pvec);
827       *pvec = NULL;
828     }
829   return 1;
830 }
831
832 static int
833 cmd_directory_vector (const char *com, const char *val, void *place)
834 {
835   char ***pvec = (char ***)place;
836
837   if (*val)
838     {
839       /* Strip the trailing slashes from directories.  */
840       char **t, **seps;
841
842       seps = sepstring (val);
843       for (t = seps; t && *t; t++)
844         {
845           int len = strlen (*t);
846           /* Skip degenerate case of root directory.  */
847           if (len > 1)
848             {
849               if ((*t)[len - 1] == '/')
850                 (*t)[len - 1] = '\0';
851             }
852         }
853       *pvec = merge_vecs (*pvec, seps);
854     }
855   else
856     {
857       free_vec (*pvec);
858       *pvec = NULL;
859     }
860   return 1;
861 }
862
863 static int simple_atof PARAMS ((const char *, const char *, double *));
864
865 /* Engine for cmd_bytes and cmd_bytes_large: converts a string such as
866    "100k" or "2.5G" to a floating point number.  */
867
868 static int
869 parse_bytes_helper (const char *val, double *result)
870 {
871   double number, mult;
872   const char *end = val + strlen (val);
873
874   /* Check for "inf".  */
875   if (0 == strcmp (val, "inf"))
876     {
877       *result = 0;
878       return 1;
879     }
880
881   /* Strip trailing whitespace.  */
882   while (val < end && ISSPACE (end[-1]))
883     --end;
884   if (val == end)
885     return 0;
886
887   switch (TOLOWER (end[-1]))
888     {
889     case 'k':
890       --end, mult = 1024.0;
891       break;
892     case 'm':
893       --end, mult = 1048576.0;
894       break;
895     case 'g':
896       --end, mult = 1073741824.0;
897       break;
898     case 't':
899       --end, mult = 1099511627776.0;
900       break;
901     default:
902       /* Not a recognized suffix: assume it's a digit.  (If not,
903          simple_atof will raise an error.)  */
904       mult = 1;
905     }
906
907   /* Skip leading and trailing whitespace. */
908   while (val < end && ISSPACE (*val))
909     ++val;
910   while (val < end && ISSPACE (end[-1]))
911     --end;
912   if (val == end)
913     return 0;
914
915   if (!simple_atof (val, end, &number) || number < 0)
916     return 0;
917
918   *result = number * mult;
919   return 1;
920 }
921
922 /* Parse VAL as a number and set its value to PLACE (which should
923    point to a wgint).
924
925    By default, the value is assumed to be in bytes.  If "K", "M", or
926    "G" are appended, the value is multiplied with 1<<10, 1<<20, or
927    1<<30, respectively.  Floating point values are allowed and are
928    cast to integer before use.  The idea is to be able to use things
929    like 1.5k instead of "1536".
930
931    The string "inf" is returned as 0.
932
933    In case of error, 0 is returned and memory pointed to by PLACE
934    remains unmodified.  */
935
936 static int
937 cmd_bytes (const char *com, const char *val, void *place)
938 {
939   double byte_value;
940   if (!parse_bytes_helper (val, &byte_value))
941     {
942       fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
943                exec_name, com, val);
944       return 0;
945     }
946   *(wgint *)place = (wgint)byte_value;
947   return 1;
948 }
949
950 /* Like cmd_bytes, but PLACE is interpreted as a pointer to
951    LARGE_INT.  It works by converting the string to double, therefore
952    working with values up to 2^53-1 without loss of precision.  This
953    value (8192 TB) is large enough to serve for a while.  */
954
955 static int
956 cmd_bytes_large (const char *com, const char *val, void *place)
957 {
958   double byte_value;
959   if (!parse_bytes_helper (val, &byte_value))
960     {
961       fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
962                exec_name, com, val);
963       return 0;
964     }
965   *(LARGE_INT *)place = (LARGE_INT)byte_value;
966   return 1;
967 }
968
969 /* Store the value of VAL to *OUT.  The value is a time period, by
970    default expressed in seconds, but also accepting suffixes "m", "h",
971    "d", and "w" for minutes, hours, days, and weeks respectively.  */
972
973 static int
974 cmd_time (const char *com, const char *val, void *place)
975 {
976   double number, mult;
977   const char *end = val + strlen (val);
978
979   /* Strip trailing whitespace.  */
980   while (val < end && ISSPACE (end[-1]))
981     --end;
982
983   if (val == end)
984     {
985     err:
986       fprintf (stderr, _("%s: %s: Invalid time period `%s'\n"),
987                exec_name, com, val);
988       return 0;
989     }
990
991   switch (TOLOWER (end[-1]))
992     {
993     case 's':
994       --end, mult = 1;          /* seconds */
995       break;
996     case 'm':
997       --end, mult = 60;         /* minutes */
998       break;
999     case 'h':
1000       --end, mult = 3600;       /* hours */
1001       break;
1002     case 'd':
1003       --end, mult = 86400.0;    /* days */
1004       break;
1005     case 'w':
1006       --end, mult = 604800.0;   /* weeks */
1007       break;
1008     default:
1009       /* Not a recognized suffix: assume it belongs to the number.
1010          (If not, simple_atof will raise an error.)  */
1011       mult = 1;
1012     }
1013
1014   /* Skip leading and trailing whitespace. */
1015   while (val < end && ISSPACE (*val))
1016     ++val;
1017   while (val < end && ISSPACE (end[-1]))
1018     --end;
1019   if (val == end)
1020     goto err;
1021
1022   if (!simple_atof (val, end, &number))
1023     goto err;
1024
1025   *(double *)place = number * mult;
1026   return 1;
1027 }
1028 \f
1029 /* Specialized helper functions, used by `commands' to handle some
1030    options specially.  */
1031
1032 static int check_user_specified_header PARAMS ((const char *));
1033 /* Forward decl */
1034 struct decode_item {
1035   const char *name;
1036   int code;
1037 };
1038 static int decode_string PARAMS ((const char *, const struct decode_item *,
1039                                   int, int *));
1040
1041 #ifdef HAVE_SSL
1042 static int
1043 cmd_spec_cert_type (const char *com, const char *val, void *place)
1044 {
1045   static const struct decode_item choices[] = {
1046     { "pem", cert_type_pem },
1047     { "asn1", cert_type_asn1 },
1048   };
1049   int ok = decode_string (val, choices, countof (choices), place);
1050   if (!ok)
1051     fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1052   return ok;
1053 }
1054 #endif
1055
1056 static int
1057 cmd_spec_dirstruct (const char *com, const char *val, void *place_ignored)
1058 {
1059   if (!cmd_boolean (com, val, &opt.dirstruct))
1060     return 0;
1061   /* Since dirstruct behaviour is explicitly changed, no_dirstruct
1062      must be affected inversely.  */
1063   if (opt.dirstruct)
1064     opt.no_dirstruct = 0;
1065   else
1066     opt.no_dirstruct = 1;
1067   return 1;
1068 }
1069
1070 static int
1071 cmd_spec_header (const char *com, const char *val, void *place)
1072 {
1073   if (!check_user_specified_header (val))
1074     {
1075       fprintf (stderr, _("%s: %s: Invalid header `%s'.\n"),
1076                exec_name, com, val);
1077       return 0;
1078     }
1079   return cmd_vector (com, val, place);
1080 }
1081
1082 static int
1083 cmd_spec_htmlify (const char *com, const char *val, void *place_ignored)
1084 {
1085   int flag = cmd_boolean (com, val, &opt.htmlify);
1086   if (flag && !opt.htmlify)
1087     opt.remove_listing = 0;
1088   return flag;
1089 }
1090
1091 /* Set the "mirror" mode.  It means: recursive download, timestamping,
1092    no limit on max. recursion depth, and don't remove listings.  */
1093
1094 static int
1095 cmd_spec_mirror (const char *com, const char *val, void *place_ignored)
1096 {
1097   int mirror;
1098
1099   if (!cmd_boolean (com, val, &mirror))
1100     return 0;
1101   if (mirror)
1102     {
1103       opt.recursive = 1;
1104       if (!opt.no_dirstruct)
1105         opt.dirstruct = 1;
1106       opt.timestamping = 1;
1107       opt.reclevel = INFINITE_RECURSION;
1108       opt.remove_listing = 0;
1109     }
1110   return 1;
1111 }
1112
1113 /* Validate --prefer-family and set the choice.  Allowed values are
1114    "IPv4", "IPv6", and "none".  */
1115
1116 static int
1117 cmd_spec_prefer_family (const char *com, const char *val, void *place_ignored)
1118 {
1119   static const struct decode_item choices[] = {
1120     { "IPv4", prefer_ipv4 },
1121     { "IPv6", prefer_ipv6 },
1122     { "none", prefer_none },
1123   };
1124   int ok = decode_string (val, choices, countof (choices),
1125                           (int *) &opt.prefer_family);
1126   if (!ok)
1127     fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1128   return ok;
1129 }
1130
1131 /* Set progress.type to VAL, but verify that it's a valid progress
1132    implementation before that.  */
1133
1134 static int
1135 cmd_spec_progress (const char *com, const char *val, void *place_ignored)
1136 {
1137   if (!valid_progress_implementation_p (val))
1138     {
1139       fprintf (stderr, _("%s: %s: Invalid progress type `%s'.\n"),
1140                exec_name, com, val);
1141       return 0;
1142     }
1143   xfree_null (opt.progress_type);
1144
1145   /* Don't call set_progress_implementation here.  It will be called
1146      in main() when it becomes clear what the log output is.  */
1147   opt.progress_type = xstrdup (val);
1148   return 1;
1149 }
1150
1151 /* Set opt.recursive to VAL as with cmd_boolean.  If opt.recursive is
1152    set to true, also set opt.dirstruct to 1, unless opt.no_dirstruct
1153    is specified.  */
1154
1155 static int
1156 cmd_spec_recursive (const char *com, const char *val, void *place_ignored)
1157 {
1158   if (!cmd_boolean (com, val, &opt.recursive))
1159     return 0;
1160   else
1161     {
1162       if (opt.recursive && !opt.no_dirstruct)
1163         opt.dirstruct = 1;
1164     }
1165   return 1;
1166 }
1167
1168 static int
1169 cmd_spec_restrict_file_names (const char *com, const char *val, void *place_ignored)
1170 {
1171   int restrict_os = opt.restrict_files_os;
1172   int restrict_ctrl = opt.restrict_files_ctrl;
1173
1174   const char *end = strchr (val, ',');
1175   if (!end)
1176     end = val + strlen (val);
1177
1178 #define VAL_IS(string_literal) BOUNDED_EQUAL (val, end, string_literal)
1179
1180   if (VAL_IS ("unix"))
1181     restrict_os = restrict_unix;
1182   else if (VAL_IS ("windows"))
1183     restrict_os = restrict_windows;
1184   else if (VAL_IS ("nocontrol"))
1185     restrict_ctrl = 0;
1186   else
1187     {
1188     err:
1189       fprintf (stderr,
1190                _("%s: %s: Invalid restriction `%s', use `unix' or `windows'.\n"),
1191                exec_name, com, val);
1192       return 0;
1193     }
1194
1195 #undef VAL_IS
1196
1197   if (*end)
1198     {
1199       if (!strcmp (end + 1, "nocontrol"))
1200         restrict_ctrl = 0;
1201       else
1202         goto err;
1203     }
1204
1205   opt.restrict_files_os = restrict_os;
1206   opt.restrict_files_ctrl = restrict_ctrl;
1207   return 1;
1208 }
1209
1210 #ifdef HAVE_SSL
1211 static int
1212 cmd_spec_secure_protocol (const char *com, const char *val, void *place)
1213 {
1214   static const struct decode_item choices[] = {
1215     { "auto", secure_protocol_auto },
1216     { "sslv2", secure_protocol_sslv2 },
1217     { "sslv3", secure_protocol_sslv3 },
1218     { "tlsv1", secure_protocol_tlsv1 },
1219   };
1220   int ok = decode_string (val, choices, countof (choices), place);
1221   if (!ok)
1222     fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1223   return ok;
1224 }
1225 #endif
1226
1227 /* Set all three timeout values. */
1228
1229 static int
1230 cmd_spec_timeout (const char *com, const char *val, void *place_ignored)
1231 {
1232   double value;
1233   if (!cmd_time (com, val, &value))
1234     return 0;
1235   opt.read_timeout = value;
1236   opt.connect_timeout = value;
1237   opt.dns_timeout = value;
1238   return 1;
1239 }
1240
1241 static int
1242 cmd_spec_useragent (const char *com, const char *val, void *place_ignored)
1243 {
1244   /* Just check for empty string and newline, so we don't throw total
1245      junk to the server.  */
1246   if (!*val || strchr (val, '\n'))
1247     {
1248       fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"),
1249                exec_name, com, val);
1250       return 0;
1251     }
1252   opt.useragent = xstrdup (val);
1253   return 1;
1254 }
1255 \f
1256 /* Miscellaneous useful routines.  */
1257
1258 /* A very simple atoi clone, more useful than atoi because it works on
1259    delimited strings, and has error reportage.  Returns 1 on success,
1260    0 on failure.  If successful, stores result to *DEST.  */
1261
1262 static int
1263 simple_atoi (const char *beg, const char *end, int *dest)
1264 {
1265   int result = 0;
1266   int negative = 0;
1267   const char *p = beg;
1268
1269   while (p < end && ISSPACE (*p))
1270     ++p;
1271   if (p < end && (*p == '-' || *p == '+'))
1272     {
1273       negative = (*p == '-');
1274       ++p;
1275     }
1276   if (p == end)
1277     return 0;
1278
1279   /* Read negative numbers in a separate loop because the most
1280      negative integer cannot be represented as a positive number.  */
1281
1282   if (!negative)
1283     for (; p < end && ISDIGIT (*p); p++)
1284       {
1285         int next = (10 * result) + (*p - '0');
1286         if (next < result)
1287           return 0;             /* overflow */
1288         result = next;
1289       }
1290   else
1291     for (; p < end && ISDIGIT (*p); p++)
1292       {
1293         int next = (10 * result) - (*p - '0');
1294         if (next > result)
1295           return 0;             /* underflow */
1296         result = next;
1297       }
1298
1299   if (p != end)
1300     return 0;
1301
1302   *dest = result;
1303   return 1;
1304 }
1305
1306 /* Trivial atof, with error reporting.  Handles "<digits>[.<digits>]",
1307    doesn't handle exponential notation.  Returns 1 on success, 0 on
1308    failure.  In case of success, stores its result to *DEST.  */
1309
1310 static int
1311 simple_atof (const char *beg, const char *end, double *dest)
1312 {
1313   double result = 0;
1314
1315   int negative = 0;
1316   int seen_dot = 0;
1317   int seen_digit = 0;
1318   double divider = 1;
1319
1320   const char *p = beg;
1321
1322   while (p < end && ISSPACE (*p))
1323     ++p;
1324   if (p < end && (*p == '-' || *p == '+'))
1325     {
1326       negative = (*p == '-');
1327       ++p;
1328     }
1329
1330   for (; p < end; p++)
1331     {
1332       char ch = *p;
1333       if (ISDIGIT (ch))
1334         {
1335           if (!seen_dot)
1336             result = (10 * result) + (ch - '0');
1337           else
1338             result += (ch - '0') / (divider *= 10);
1339           seen_digit = 1;
1340         }
1341       else if (ch == '.')
1342         {
1343           if (!seen_dot)
1344             seen_dot = 1;
1345           else
1346             return 0;
1347         }
1348       else
1349         return 0;
1350     }
1351   if (!seen_digit)
1352     return 0;
1353   if (negative)
1354     result = -result;
1355
1356   *dest = result;
1357   return 1;
1358 }
1359
1360 /* Verify that the user-specified header in S is valid.  It must
1361    contain a colon preceded by non-white-space characters and must not
1362    contain newlines.  */
1363
1364 static int
1365 check_user_specified_header (const char *s)
1366 {
1367   const char *p;
1368
1369   for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1370   /* The header MUST contain `:' preceded by at least one
1371      non-whitespace character.  */
1372   if (*p != ':' || p == s)
1373     return 0;
1374   /* The header MUST NOT contain newlines.  */
1375   if (strchr (s, '\n'))
1376     return 0;
1377   return 1;
1378 }
1379
1380 /* Decode VAL into a number, according to ITEMS. */
1381
1382 static int
1383 decode_string (const char *val, const struct decode_item *items, int itemcount,
1384                int *place)
1385 {
1386   int i;
1387   for (i = 0; i < itemcount; i++)
1388     if (0 == strcasecmp (val, items[i].name))
1389       {
1390         *place = items[i].code;
1391         return 1;
1392       }
1393   return 0;
1394 }
1395
1396 \f
1397 void cleanup_html_url PARAMS ((void));
1398 void http_cleanup PARAMS ((void));
1399
1400
1401 /* Free the memory allocated by global variables.  */
1402 void
1403 cleanup (void)
1404 {
1405   /* Free external resources, close files, etc. */
1406
1407   {
1408     extern FILE *output_stream;
1409     if (output_stream)
1410       fclose (output_stream);
1411     /* No need to check for error because Wget flushes its output (and
1412        checks for errors) after any data arrives.  */
1413   }
1414
1415   /* We're exiting anyway so there's no real need to call free()
1416      hundreds of times.  Skipping the frees will make Wget exit
1417      faster.
1418
1419      However, when detecting leaks, it's crucial to free() everything
1420      because then you can find the real leaks, i.e. the allocated
1421      memory which grows with the size of the program.  */
1422
1423 #ifdef DEBUG_MALLOC
1424   convert_cleanup ();
1425   res_cleanup ();
1426   http_cleanup ();
1427   cleanup_html_url ();
1428   host_cleanup ();
1429   log_cleanup ();
1430
1431   {
1432     extern acc_t *netrc_list;
1433     free_netrc (netrc_list);
1434   }
1435   xfree_null (opt.lfilename);
1436   xfree_null (opt.dir_prefix);
1437   xfree_null (opt.input_filename);
1438   xfree_null (opt.output_document);
1439   free_vec (opt.accepts);
1440   free_vec (opt.rejects);
1441   free_vec (opt.excludes);
1442   free_vec (opt.includes);
1443   free_vec (opt.domains);
1444   free_vec (opt.follow_tags);
1445   free_vec (opt.ignore_tags);
1446   xfree_null (opt.progress_type);
1447   xfree (opt.ftp_acc);
1448   xfree_null (opt.ftp_pass);
1449   xfree_null (opt.ftp_proxy);
1450   xfree_null (opt.https_proxy);
1451   xfree_null (opt.http_proxy);
1452   free_vec (opt.no_proxy);
1453   xfree_null (opt.useragent);
1454   xfree_null (opt.referer);
1455   xfree_null (opt.http_user);
1456   xfree_null (opt.http_passwd);
1457   free_vec (opt.user_headers);
1458 #ifdef HAVE_SSL
1459   xfree_null (opt.sslcertkey);
1460   xfree_null (opt.sslcertfile);
1461 #endif /* HAVE_SSL */
1462   xfree_null (opt.bind_address);
1463   xfree_null (opt.cookies_input);
1464   xfree_null (opt.cookies_output);
1465 #endif
1466 }