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