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