]> sjero.net Git - wget/blob - src/init.c
[svn] Wrap private key commands in #ifdef HAVE_SSL.
[wget] / src / init.c
1 /* Reading/parsing the initialization file.
2    Copyright (C) 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <stdlib.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # include <strings.h>
42 #endif
43 #include <errno.h>
44
45 #ifdef HAVE_PWD_H
46 # include <pwd.h>
47 #endif
48 #include <assert.h>
49
50 #include "wget.h"
51 #include "utils.h"
52 #include "init.h"
53 #include "host.h"
54 #include "netrc.h"
55 #include "progress.h"
56 #include "recur.h"              /* for INFINITE_RECURSION */
57 #include "convert.h"            /* for convert_cleanup */
58 #include "res.h"                /* for res_cleanup */
59
60 #ifndef errno
61 extern int errno;
62 #endif
63
64 /* We want tilde expansion enabled only when reading `.wgetrc' lines;
65    otherwise, it will be performed by the shell.  This variable will
66    be set by the wgetrc-reading function.  */
67
68 static int enable_tilde_expansion;
69
70
71 #define CMD_DECLARE(func) static int func \
72   PARAMS ((const char *, const char *, void *))
73
74 CMD_DECLARE (cmd_boolean);
75 CMD_DECLARE (cmd_bytes);
76 CMD_DECLARE (cmd_bytes_large);
77 #ifdef HAVE_SSL
78 CMD_DECLARE (cmd_cert_type);
79 #endif
80 CMD_DECLARE (cmd_directory_vector);
81 CMD_DECLARE (cmd_lockable_boolean);
82 CMD_DECLARE (cmd_number);
83 CMD_DECLARE (cmd_number_inf);
84 CMD_DECLARE (cmd_string);
85 CMD_DECLARE (cmd_file);
86 CMD_DECLARE (cmd_directory);
87 CMD_DECLARE (cmd_time);
88 CMD_DECLARE (cmd_vector);
89
90 CMD_DECLARE (cmd_spec_dirstruct);
91 CMD_DECLARE (cmd_spec_header);
92 CMD_DECLARE (cmd_spec_htmlify);
93 CMD_DECLARE (cmd_spec_mirror);
94 CMD_DECLARE (cmd_spec_prefer_family);
95 CMD_DECLARE (cmd_spec_progress);
96 CMD_DECLARE (cmd_spec_recursive);
97 CMD_DECLARE (cmd_spec_restrict_file_names);
98 #ifdef HAVE_SSL
99 CMD_DECLARE (cmd_spec_secure_protocol);
100 #endif
101 CMD_DECLARE (cmd_spec_timeout);
102 CMD_DECLARE (cmd_spec_useragent);
103
104 /* List of recognized commands, each consisting of name, place and
105    function.  When adding a new command, simply add it to the list,
106    but be sure to keep the list sorted alphabetically, as
107    command_by_name depends on it.  Also, be sure to add any entries
108    that allocate memory (e.g. cmd_string and cmd_vector guys) to the
109    cleanup() function below. */
110
111 static struct {
112   const char *name;
113   void *place;
114   int (*action) PARAMS ((const char *, const char *, void *));
115 } commands[] = {
116   { "accept",           &opt.accepts,           cmd_vector },
117   { "addhostdir",       &opt.add_hostdir,       cmd_boolean },
118   { "alwaysrest",       &opt.always_rest,       cmd_boolean }, /* deprecated */
119   { "background",       &opt.background,        cmd_boolean },
120   { "backupconverted",  &opt.backup_converted,  cmd_boolean },
121   { "backups",          &opt.backups,           cmd_number },
122   { "base",             &opt.base_href,         cmd_string },
123   { "bindaddress",      &opt.bind_address,      cmd_string },
124 #ifdef HAVE_SSL
125   { "cacertificate",    &opt.ca_cert,           cmd_file },
126 #endif
127   { "cache",            &opt.allow_cache,       cmd_boolean },
128 #ifdef HAVE_SSL
129   { "cadirectory",      &opt.ca_directory,      cmd_directory },
130   { "certificate",      &opt.cert_file,         cmd_file },
131   { "certificatetype",  &opt.cert_type,         cmd_cert_type },
132   { "checkcertificate", &opt.check_cert,        cmd_boolean },
133 #endif
134   { "connecttimeout",   &opt.connect_timeout,   cmd_time },
135   { "continue",         &opt.always_rest,       cmd_boolean },
136   { "convertlinks",     &opt.convert_links,     cmd_boolean },
137   { "cookies",          &opt.cookies,           cmd_boolean },
138   { "cutdirs",          &opt.cut_dirs,          cmd_number },
139 #ifdef ENABLE_DEBUG
140   { "debug",            &opt.debug,             cmd_boolean },
141 #endif
142   { "deleteafter",      &opt.delete_after,      cmd_boolean },
143   { "dirprefix",        &opt.dir_prefix,        cmd_directory },
144   { "dirstruct",        NULL,                   cmd_spec_dirstruct },
145   { "dnscache",         &opt.dns_cache,         cmd_boolean },
146   { "dnstimeout",       &opt.dns_timeout,       cmd_time },
147   { "domains",          &opt.domains,           cmd_vector },
148   { "dotbytes",         &opt.dot_bytes,         cmd_bytes },
149   { "dotsinline",       &opt.dots_in_line,      cmd_number },
150   { "dotspacing",       &opt.dot_spacing,       cmd_number },
151   { "dotstyle",         &opt.dot_style,         cmd_string },
152 #ifdef HAVE_SSL
153   { "egdfile",          &opt.egd_file,          cmd_file },
154 #endif
155   { "excludedirectories", &opt.excludes,        cmd_directory_vector },
156   { "excludedomains",   &opt.exclude_domains,   cmd_vector },
157   { "followftp",        &opt.follow_ftp,        cmd_boolean },
158   { "followtags",       &opt.follow_tags,       cmd_vector },
159   { "forcehtml",        &opt.force_html,        cmd_boolean },
160   { "ftppasswd",        &opt.ftp_pass,          cmd_string },
161   { "ftpproxy",         &opt.ftp_proxy,         cmd_string },
162   { "glob",             &opt.ftp_glob,          cmd_boolean },
163   { "header",           &opt.user_headers,      cmd_spec_header },
164   { "htmlextension",    &opt.html_extension,    cmd_boolean },
165   { "htmlify",          NULL,                   cmd_spec_htmlify },
166   { "httpkeepalive",    &opt.http_keep_alive,   cmd_boolean },
167   { "httppasswd",       &opt.http_passwd,       cmd_string },
168   { "httpproxy",        &opt.http_proxy,        cmd_string },
169   { "httpsproxy",       &opt.https_proxy,       cmd_string },
170   { "httpuser",         &opt.http_user,         cmd_string },
171   { "ignorelength",     &opt.ignore_length,     cmd_boolean },
172   { "ignoretags",       &opt.ignore_tags,       cmd_vector },
173   { "includedirectories", &opt.includes,        cmd_directory_vector },
174 #ifdef ENABLE_IPV6
175   { "inet4only",        &opt.ipv4_only,         cmd_boolean },
176   { "inet6only",        &opt.ipv6_only,         cmd_boolean },
177 #endif
178   { "input",            &opt.input_filename,    cmd_file },
179   { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
180   { "killlonger",       &opt.kill_longer,       cmd_boolean },
181   { "limitrate",        &opt.limit_rate,        cmd_bytes },
182   { "loadcookies",      &opt.cookies_input,     cmd_file },
183   { "logfile",          &opt.lfilename,         cmd_file },
184   { "login",            &opt.ftp_acc,           cmd_string },
185   { "mirror",           NULL,                   cmd_spec_mirror },
186   { "netrc",            &opt.netrc,             cmd_boolean },
187   { "noclobber",        &opt.noclobber,         cmd_boolean },
188   { "noparent",         &opt.no_parent,         cmd_boolean },
189   { "noproxy",          &opt.no_proxy,          cmd_vector },
190   { "numtries",         &opt.ntry,              cmd_number_inf },/* deprecated*/
191   { "outputdocument",   &opt.output_document,   cmd_file },
192   { "pagerequisites",   &opt.page_requisites,   cmd_boolean },
193   { "passiveftp",       &opt.ftp_pasv,          cmd_lockable_boolean },
194   { "postdata",         &opt.post_data,         cmd_string },
195   { "postfile",         &opt.post_file_name,    cmd_file },
196   { "preferfamily",     NULL,                   cmd_spec_prefer_family },
197   { "preservepermissions", &opt.preserve_perm,  cmd_boolean },
198 #ifdef HAVE_SSL
199   { "privatekey",       &opt.private_key,       cmd_file },
200   { "privatekeytype",   &opt.private_key_type,  cmd_cert_type },
201 #endif
202   { "progress",         &opt.progress_type,     cmd_spec_progress },
203   { "protocoldirectories", &opt.protocol_directories, cmd_boolean },
204   { "proxypasswd",      &opt.proxy_passwd,      cmd_string },
205   { "proxyuser",        &opt.proxy_user,        cmd_string },
206   { "quiet",            &opt.quiet,             cmd_boolean },
207   { "quota",            &opt.quota,             cmd_bytes_large },
208   { "randomwait",       &opt.random_wait,       cmd_boolean },
209   { "readtimeout",      &opt.read_timeout,      cmd_time },
210   { "reclevel",         &opt.reclevel,          cmd_number_inf },
211   { "recursive",        NULL,                   cmd_spec_recursive },
212   { "referer",          &opt.referer,           cmd_string },
213   { "reject",           &opt.rejects,           cmd_vector },
214   { "relativeonly",     &opt.relative_only,     cmd_boolean },
215   { "removelisting",    &opt.remove_listing,    cmd_boolean },
216   { "restrictfilenames", NULL,                  cmd_spec_restrict_file_names },
217   { "retrsymlinks",     &opt.retr_symlinks,     cmd_boolean },
218   { "retryconnrefused", &opt.retry_connrefused, cmd_boolean },
219   { "robots",           &opt.use_robots,        cmd_boolean },
220   { "savecookies",      &opt.cookies_output,    cmd_file },
221   { "saveheaders",      &opt.save_headers,      cmd_boolean },
222 #ifdef HAVE_SSL
223   { "secureprotocol",   &opt.secure_protocol,   cmd_spec_secure_protocol },
224 #endif
225   { "serverresponse",   &opt.server_response,   cmd_boolean },
226   { "spanhosts",        &opt.spanhost,          cmd_boolean },
227   { "spider",           &opt.spider,            cmd_boolean },
228   { "strictcomments",   &opt.strict_comments,   cmd_boolean },
229   { "timeout",          NULL,                   cmd_spec_timeout },
230   { "timestamping",     &opt.timestamping,      cmd_boolean },
231   { "tries",            &opt.ntry,              cmd_number_inf },
232   { "useproxy",         &opt.use_proxy,         cmd_boolean },
233   { "useragent",        NULL,                   cmd_spec_useragent },
234   { "verbose",          &opt.verbose,           cmd_boolean },
235   { "wait",             &opt.wait,              cmd_time },
236   { "waitretry",        &opt.waitretry,         cmd_time }
237 };
238
239 /* Look up CMDNAME in the commands[] and return its position in the
240    array.  If CMDNAME is not found, return -1.  */
241
242 static int
243 command_by_name (const char *cmdname)
244 {
245   /* Use binary search for speed.  Wget has ~100 commands, which
246      guarantees a worst case performance of 7 string comparisons.  */
247   int lo = 0, hi = countof (commands) - 1;
248
249   while (lo <= hi)
250     {
251       int mid = (lo + hi) >> 1;
252       int cmp = strcasecmp (cmdname, commands[mid].name);
253       if (cmp < 0)
254         hi = mid - 1;
255       else if (cmp > 0)
256         lo = mid + 1;
257       else
258         return mid;
259     }
260   return -1;
261 }
262 \f
263 /* Reset the variables to default values.  */
264 static void
265 defaults (void)
266 {
267   char *tmp;
268
269   /* Most of the default values are 0.  Just reset everything, and
270      fill in the non-zero values.  Note that initializing pointers to
271      NULL this way is technically illegal, but porting Wget to a
272      machine where NULL is not all-zero bit pattern will be the least
273      of the implementors' worries.  */
274   xzero (opt);
275
276   opt.cookies = 1;
277   opt.verbose = -1;
278   opt.ntry = 20;
279   opt.reclevel = 5;
280   opt.add_hostdir = 1;
281   opt.ftp_acc  = xstrdup ("anonymous");
282   opt.ftp_pass = xstrdup ("-wget@");
283   opt.netrc = 1;
284   opt.ftp_glob = 1;
285   opt.htmlify = 1;
286   opt.http_keep_alive = 1;
287   opt.use_proxy = 1;
288   tmp = getenv ("no_proxy");
289   if (tmp)
290     opt.no_proxy = sepstring (tmp);
291   opt.allow_cache = 1;
292
293   opt.read_timeout = 900;
294   opt.use_robots = 1;
295
296   opt.remove_listing = 1;
297
298   opt.dot_bytes = 1024;
299   opt.dot_spacing = 10;
300   opt.dots_in_line = 50;
301
302   opt.dns_cache = 1;
303   opt.ftp_pasv = 1;
304
305 #ifdef HAVE_SSL
306   opt.check_cert = 1;
307 #endif
308
309   /* The default for file name restriction defaults to the OS type. */
310 #if !defined(WINDOWS) && !defined(__CYGWIN__)
311   opt.restrict_files_os = restrict_unix;
312 #else
313   opt.restrict_files_os = restrict_windows;
314 #endif
315   opt.restrict_files_ctrl = 1;
316 }
317 \f
318 /* Return the user's home directory (strdup-ed), or NULL if none is
319    found.  */
320 char *
321 home_dir (void)
322 {
323   char *home = getenv ("HOME");
324
325   if (!home)
326     {
327 #ifndef WINDOWS
328       /* If HOME is not defined, try getting it from the password
329          file.  */
330       struct passwd *pwd = getpwuid (getuid ());
331       if (!pwd || !pwd->pw_dir)
332         return NULL;
333       home = pwd->pw_dir;
334 #else  /* WINDOWS */
335       /* Under Windows, if $HOME isn't defined, use the directory where
336          `wget.exe' resides.  */
337       home = ws_mypath ();
338 #endif /* WINDOWS */
339     }
340
341   return home ? xstrdup (home) : NULL;
342 }
343
344 /* Return the path to the user's .wgetrc.  This is either the value of
345    `WGETRC' environment variable, or `$HOME/.wgetrc'.
346
347    If the `WGETRC' variable exists but the file does not exist, the
348    function will exit().  */
349 static char *
350 wgetrc_file_name (void)
351 {
352   char *env, *home;
353   char *file = NULL;
354
355   /* Try the environment.  */
356   env = getenv ("WGETRC");
357   if (env && *env)
358     {
359       if (!file_exists_p (env))
360         {
361           fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"),
362                    exec_name, env);
363           exit (1);
364         }
365       return xstrdup (env);
366     }
367
368   /* If that failed, try $HOME/.wgetrc.  */
369   home = home_dir ();
370   if (home)
371     file = aprintf ("%s/.wgetrc", home);
372   xfree_null (home);
373
374 #ifdef WINDOWS
375   /* Under Windows, if we still haven't found .wgetrc, look for the file
376      `wget.ini' in the directory where `wget.exe' resides; we do this for
377      backward compatibility with previous versions of Wget.
378      SYSTEM_WGETRC should not be defined under WINDOWS.  */
379   if (!file || !file_exists_p (file))
380     {
381       xfree_null (file);
382       file = NULL;
383       home = ws_mypath ();
384       if (home)
385         file = aprintf ("%s/wget.ini", home);
386     }
387 #endif /* WINDOWS */
388
389   if (!file)
390     return NULL;
391   if (!file_exists_p (file))
392     {
393       xfree (file);
394       return NULL;
395     }
396   return file;
397 }
398
399 static int parse_line PARAMS ((const char *, char **, char **, int *));
400 static int setval_internal PARAMS ((int, const char *, const char *));
401
402 /* Initialize variables from a wgetrc file.  */
403
404 static void
405 run_wgetrc (const char *file)
406 {
407   FILE *fp;
408   char *line;
409   int ln;
410
411   fp = fopen (file, "rb");
412   if (!fp)
413     {
414       fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
415                file, strerror (errno));
416       return;
417     }
418   enable_tilde_expansion = 1;
419   ln = 1;
420   while ((line = read_whole_line (fp)) != NULL)
421     {
422       char *com, *val;
423       int comind, status;
424
425       /* Parse the line.  */
426       status = parse_line (line, &com, &val, &comind);
427       xfree (line);
428       /* If everything is OK, set the value.  */
429       if (status == 1)
430         {
431           if (!setval_internal (comind, com, val))
432             fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
433                      file, ln);
434           xfree (com);
435           xfree (val);
436         }
437       else if (status == 0)
438         fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
439                  file, ln);
440       ++ln;
441     }
442   enable_tilde_expansion = 0;
443   fclose (fp);
444 }
445
446 /* Initialize the defaults and run the system wgetrc and user's own
447    wgetrc.  */
448 void
449 initialize (void)
450 {
451   char *file;
452
453   /* Load the hard-coded defaults.  */
454   defaults ();
455
456   /* If SYSTEM_WGETRC is defined, use it.  */
457 #ifdef SYSTEM_WGETRC
458   if (file_exists_p (SYSTEM_WGETRC))
459     run_wgetrc (SYSTEM_WGETRC);
460 #endif
461   /* Override it with your own, if one exists.  */
462   file = wgetrc_file_name ();
463   if (!file)
464     return;
465   /* #### We should canonicalize `file' and SYSTEM_WGETRC with
466      something like realpath() before comparing them with `strcmp'  */
467 #ifdef SYSTEM_WGETRC
468   if (!strcmp (file, SYSTEM_WGETRC))
469     {
470       fprintf (stderr, _("\
471 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
472                exec_name, file);
473     }
474   else
475 #endif
476     run_wgetrc (file);
477   xfree (file);
478   return;
479 }
480 \f
481 /* Remove dashes and underscores from S, modifying S in the
482    process. */
483
484 static void
485 dehyphen (char *s)
486 {
487   char *t = s;                  /* t - tortoise */
488   char *h = s;                  /* h - hare     */
489   while (*h)
490     if (*h == '_' || *h == '-')
491       ++h;
492     else
493       *t++ = *h++;
494   *t = '\0';
495 }
496
497 /* Parse the line pointed by line, with the syntax:
498    <sp>* command <sp>* = <sp>* value <sp>*
499    Uses malloc to allocate space for command and value.
500    If the line is invalid, data is freed and 0 is returned.
501
502    Return values:
503     1 - success
504     0 - error
505    -1 - empty
506
507    In case of success, *COM and *VAL point to freshly allocated
508    strings, and *COMIND points to com's index.  In case of error or
509    empty line, those values are unaffected.  */
510
511 static int
512 parse_line (const char *line, char **com, char **val, int *comind)
513 {
514   const char *p;
515   const char *end = line + strlen (line);
516   const char *cmdstart, *cmdend;
517   const char *valstart, *valend;
518
519   char *cmdcopy;
520   int ind;
521
522   /* Skip leading and trailing whitespace.  */
523   while (*line && ISSPACE (*line))
524     ++line;
525   while (end > line && ISSPACE (end[-1]))
526     --end;
527
528   /* Skip empty lines and comments.  */
529   if (!*line || *line == '#')
530     return -1;
531
532   p = line;
533
534   cmdstart = p;
535   while (p < end && (ISALPHA (*p) || *p == '_' || *p == '-'))
536     ++p;
537   cmdend = p;
538
539   /* Skip '=', as well as any space before or after it. */
540   while (p < end && ISSPACE (*p))
541     ++p;
542   if (p == end || *p != '=')
543     return 0;
544   ++p;
545   while (p < end && ISSPACE (*p))
546     ++p;
547
548   valstart = p;
549   valend   = end;
550
551   /* The line now known to be syntactically correct.  Check whether
552      the command is valid.  */
553   BOUNDED_TO_ALLOCA (cmdstart, cmdend, cmdcopy);
554   dehyphen (cmdcopy);
555   ind = command_by_name (cmdcopy);
556   if (ind == -1)
557     return 0;
558
559   /* The command is valid.  Now fill in the values and report success
560      to the caller.  */
561   *comind = ind;
562   *com = strdupdelim (cmdstart, cmdend);
563   *val = strdupdelim (valstart, valend);
564   return 1;
565 }
566
567 /* Run commands[comind].action. */
568
569 static int
570 setval_internal (int comind, const char *com, const char *val)
571 {
572   assert (0 <= comind && comind < countof (commands));
573   DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
574   return ((*commands[comind].action) (com, val, commands[comind].place));
575 }
576
577 /* Run command COM with value VAL.  If running the command produces an
578    error, report the error and exit.
579
580    This is intended to be called from main() to modify Wget's behavior
581    through command-line switches.  Since COM is hard-coded in main(),
582    it is not canonicalized, and this aborts when COM is not found.
583
584    If COMIND's are exported to init.h, this function will be changed
585    to accept COMIND directly.  */
586
587 void
588 setoptval (const char *com, const char *val)
589 {
590   assert (val != NULL);
591   if (!setval_internal (command_by_name (com), com, val))
592     exit (2);
593 }
594
595 /* Parse OPT into command and value and run it.  For example,
596    run_command("foo=bar") is equivalent to setoptval("foo", "bar").
597    This is used by the `--execute' flag in main.c.  */
598
599 void
600 run_command (const char *opt)
601 {
602   char *com, *val;
603   int comind;
604   int status = parse_line (opt, &com, &val, &comind);
605   if (status == 1)
606     {
607       if (!setval_internal (comind, com, val))
608         exit (2);
609       xfree (com);
610       xfree (val);
611     }
612   else if (status == 0)
613     {
614       fprintf (stderr, _("%s: Invalid --execute command `%s'\n"),
615                exec_name, opt);
616       exit (2);
617     }
618 }
619 \f
620 /* Generic helper functions, for use with `commands'. */
621
622 /* Forward declarations: */
623 struct decode_item {
624   const char *name;
625   int code;
626 };
627 static int decode_string PARAMS ((const char *, const struct decode_item *,
628                                   int, int *));
629 static int simple_atoi PARAMS ((const char *, const char *, int *));
630 static int simple_atof PARAMS ((const char *, const char *, double *));
631
632 #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0')
633
634 #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0)        \
635                          && TOLOWER((p)[1]) == (c1)     \
636                          && (p)[2] == '\0')
637
638 #define CMP3(p, c0, c1, c2) (TOLOWER((p)[0]) == (c0)    \
639                      && TOLOWER((p)[1]) == (c1)         \
640                      && TOLOWER((p)[2]) == (c2)         \
641                      && (p)[3] == '\0')
642
643
644 /* Store the boolean value from VAL to PLACE.  COM is ignored,
645    except for error messages.  */
646 static int
647 cmd_boolean (const char *com, const char *val, void *place)
648 {
649   int bool_value;
650
651   if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
652     /* "on", "yes" and "1" mean true. */
653     bool_value = 1;
654   else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
655     /* "off", "no" and "0" mean false. */
656     bool_value = 0;
657   else
658     {
659       fprintf (stderr,
660                _("%s: %s: Invalid boolean `%s', use `on' or `off'.\n"),
661                exec_name, com, val);
662       return 0;
663     }
664
665   *(int *)place = bool_value;
666   return 1;
667 }
668
669 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to PLACE.
670    COM is ignored, except for error messages.  Values 2 and -1
671    indicate that once defined, the value may not be changed by
672    successive wgetrc files or command-line arguments.
673
674    Values: 2 - Enable a particular option for good ("always")
675            1 - Enable an option ("on")
676            0 - Disable an option ("off")
677           -1 - Disable an option for good ("never") */
678 static int
679 cmd_lockable_boolean (const char *com, const char *val, void *place)
680 {
681   int lockable_boolean_value;
682
683   int oldval = *(int *)place;
684
685   /*
686    * If a config file said "always" or "never", don't allow command line
687    * arguments to override the config file.
688    */
689   if (oldval == -1 || oldval == 2)
690     return 1;
691
692   if (0 == strcasecmp (val, "always") || CMP1 (val, '2'))
693     lockable_boolean_value = 2;
694   else if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
695     lockable_boolean_value = 1;
696   else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
697     lockable_boolean_value = 0;
698   else if (0 == strcasecmp (val, "never") || CMP2 (val, '-', '1'))
699     lockable_boolean_value = -1;
700   else
701     {
702       fprintf (stderr,
703                _("%s: %s: Invalid boolean `%s', use always, on, off, or never.\n"),
704                exec_name, com, val);
705       return 0;
706     }
707
708   *(int *)place = lockable_boolean_value;
709   return 1;
710 }
711
712 /* Set the non-negative integer value from VAL to PLACE.  With
713    incorrect specification, the number remains unchanged.  */
714 static int
715 cmd_number (const char *com, const char *val, void *place)
716 {
717   if (!simple_atoi (val, val + strlen (val), place)
718       || *(int *) place < 0)
719     {
720       fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
721                exec_name, com, val);
722       return 0;
723     }
724   return 1;
725 }
726
727 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0.  */
728 static int
729 cmd_number_inf (const char *com, const char *val, void *place)
730 {
731   if (!strcasecmp (val, "inf"))
732     {
733       *(int *)place = 0;
734       return 1;
735     }
736   return cmd_number (com, val, place);
737 }
738
739 /* Copy (strdup) the string at COM to a new location and place a
740    pointer to *PLACE.  */
741 static int
742 cmd_string (const char *com, const char *val, void *place)
743 {
744   char **pstring = (char **)place;
745
746   xfree_null (*pstring);
747   *pstring = xstrdup (val);
748   return 1;
749 }
750
751 #ifndef WINDOWS
752 # define ISSEP(c) ((c) == '/')
753 #else
754 # define ISSEP(c) ((c) == '/' || (c) == '\\')
755 #endif
756
757 /* Like the above, but handles tilde-expansion when reading a user's
758    `.wgetrc'.  In that case, and if VAL begins with `~', the tilde
759    gets expanded to the user's home directory.  */
760 static int
761 cmd_file (const char *com, const char *val, void *place)
762 {
763   char **pstring = (char **)place;
764
765   xfree_null (*pstring);
766
767   /* #### If VAL is empty, perhaps should set *PLACE to NULL.  */
768
769   if (!enable_tilde_expansion || !(*val == '~' && ISSEP (val[1])))
770     {
771     noexpand:
772       *pstring = xstrdup (val);
773     }
774   else
775     {
776       int homelen;
777       char *home = home_dir ();
778       if (!home)
779         goto noexpand;
780
781       homelen = strlen (home);
782       while (homelen && ISSEP (home[homelen - 1]))
783         home[--homelen] = '\0';
784
785       /* Skip the leading "~/". */
786       for (++val; ISSEP (*val); val++)
787         ;
788
789       *pstring = concat_strings (home, "/", val, (char *) 0);
790     }
791
792 #ifdef WINDOWS
793   /* Convert "\" to "/". */
794   {
795     char *s;
796     for (s = *pstring; *s; s++)
797       if (*s == '\\')
798         *s = '/';
799   }
800 #endif
801   return 1;
802 }
803
804 /* Like cmd_file, but strips trailing '/' characters.  */
805 static int
806 cmd_directory (const char *com, const char *val, void *place)
807 {
808   char *s, *t;
809
810   /* Call cmd_file() for tilde expansion and separator
811      canonicalization (backslash -> slash under Windows).  These
812      things should perhaps be in a separate function.  */
813   if (!cmd_file (com, val, place))
814     return 0;
815
816   s = *(char **)place;
817   t = s + strlen (s);
818   while (t > s && *--t == '/')
819     *t = '\0';
820
821   return 1;
822 }
823
824 /* Split VAL by space to a vector of values, and append those values
825    to vector pointed to by the PLACE argument.  If VAL is empty, the
826    PLACE vector is cleared instead.  */
827
828 static int
829 cmd_vector (const char *com, const char *val, void *place)
830 {
831   char ***pvec = (char ***)place;
832
833   if (*val)
834     *pvec = merge_vecs (*pvec, sepstring (val));
835   else
836     {
837       free_vec (*pvec);
838       *pvec = NULL;
839     }
840   return 1;
841 }
842
843 static int
844 cmd_directory_vector (const char *com, const char *val, void *place)
845 {
846   char ***pvec = (char ***)place;
847
848   if (*val)
849     {
850       /* Strip the trailing slashes from directories.  */
851       char **t, **seps;
852
853       seps = sepstring (val);
854       for (t = seps; t && *t; t++)
855         {
856           int len = strlen (*t);
857           /* Skip degenerate case of root directory.  */
858           if (len > 1)
859             {
860               if ((*t)[len - 1] == '/')
861                 (*t)[len - 1] = '\0';
862             }
863         }
864       *pvec = merge_vecs (*pvec, seps);
865     }
866   else
867     {
868       free_vec (*pvec);
869       *pvec = NULL;
870     }
871   return 1;
872 }
873
874 /* Engine for cmd_bytes and cmd_bytes_large: converts a string such as
875    "100k" or "2.5G" to a floating point number.  */
876
877 static int
878 parse_bytes_helper (const char *val, double *result)
879 {
880   double number, mult;
881   const char *end = val + strlen (val);
882
883   /* Check for "inf".  */
884   if (0 == strcmp (val, "inf"))
885     {
886       *result = 0;
887       return 1;
888     }
889
890   /* Strip trailing whitespace.  */
891   while (val < end && ISSPACE (end[-1]))
892     --end;
893   if (val == end)
894     return 0;
895
896   switch (TOLOWER (end[-1]))
897     {
898     case 'k':
899       --end, mult = 1024.0;
900       break;
901     case 'm':
902       --end, mult = 1048576.0;
903       break;
904     case 'g':
905       --end, mult = 1073741824.0;
906       break;
907     case 't':
908       --end, mult = 1099511627776.0;
909       break;
910     default:
911       /* Not a recognized suffix: assume it's a digit.  (If not,
912          simple_atof will raise an error.)  */
913       mult = 1;
914     }
915
916   /* Skip leading and trailing whitespace. */
917   while (val < end && ISSPACE (*val))
918     ++val;
919   while (val < end && ISSPACE (end[-1]))
920     --end;
921   if (val == end)
922     return 0;
923
924   if (!simple_atof (val, end, &number) || number < 0)
925     return 0;
926
927   *result = number * mult;
928   return 1;
929 }
930
931 /* Parse VAL as a number and set its value to PLACE (which should
932    point to a wgint).
933
934    By default, the value is assumed to be in bytes.  If "K", "M", or
935    "G" are appended, the value is multiplied with 1<<10, 1<<20, or
936    1<<30, respectively.  Floating point values are allowed and are
937    cast to integer before use.  The idea is to be able to use things
938    like 1.5k instead of "1536".
939
940    The string "inf" is returned as 0.
941
942    In case of error, 0 is returned and memory pointed to by PLACE
943    remains unmodified.  */
944
945 static int
946 cmd_bytes (const char *com, const char *val, void *place)
947 {
948   double byte_value;
949   if (!parse_bytes_helper (val, &byte_value))
950     {
951       fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
952                exec_name, com, val);
953       return 0;
954     }
955   *(wgint *)place = (wgint)byte_value;
956   return 1;
957 }
958
959 /* Like cmd_bytes, but PLACE is interpreted as a pointer to
960    LARGE_INT.  It works by converting the string to double, therefore
961    working with values up to 2^53-1 without loss of precision.  This
962    value (8192 TB) is large enough to serve for a while.  */
963
964 static int
965 cmd_bytes_large (const char *com, const char *val, void *place)
966 {
967   double byte_value;
968   if (!parse_bytes_helper (val, &byte_value))
969     {
970       fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
971                exec_name, com, val);
972       return 0;
973     }
974   *(LARGE_INT *)place = (LARGE_INT)byte_value;
975   return 1;
976 }
977
978 /* Store the value of VAL to *OUT.  The value is a time period, by
979    default expressed in seconds, but also accepting suffixes "m", "h",
980    "d", and "w" for minutes, hours, days, and weeks respectively.  */
981
982 static int
983 cmd_time (const char *com, const char *val, void *place)
984 {
985   double number, mult;
986   const char *end = val + strlen (val);
987
988   /* Strip trailing whitespace.  */
989   while (val < end && ISSPACE (end[-1]))
990     --end;
991
992   if (val == end)
993     {
994     err:
995       fprintf (stderr, _("%s: %s: Invalid time period `%s'\n"),
996                exec_name, com, val);
997       return 0;
998     }
999
1000   switch (TOLOWER (end[-1]))
1001     {
1002     case 's':
1003       --end, mult = 1;          /* seconds */
1004       break;
1005     case 'm':
1006       --end, mult = 60;         /* minutes */
1007       break;
1008     case 'h':
1009       --end, mult = 3600;       /* hours */
1010       break;
1011     case 'd':
1012       --end, mult = 86400.0;    /* days */
1013       break;
1014     case 'w':
1015       --end, mult = 604800.0;   /* weeks */
1016       break;
1017     default:
1018       /* Not a recognized suffix: assume it belongs to the number.
1019          (If not, simple_atof will raise an error.)  */
1020       mult = 1;
1021     }
1022
1023   /* Skip leading and trailing whitespace. */
1024   while (val < end && ISSPACE (*val))
1025     ++val;
1026   while (val < end && ISSPACE (end[-1]))
1027     --end;
1028   if (val == end)
1029     goto err;
1030
1031   if (!simple_atof (val, end, &number))
1032     goto err;
1033
1034   *(double *)place = number * mult;
1035   return 1;
1036 }
1037
1038 #ifdef HAVE_SSL
1039 static int
1040 cmd_cert_type (const char *com, const char *val, void *place)
1041 {
1042   static const struct decode_item choices[] = {
1043     { "pem", keyfile_pem },
1044     { "der", keyfile_asn1 },
1045     { "asn1", keyfile_asn1 },
1046   };
1047   int ok = decode_string (val, choices, countof (choices), place);
1048   if (!ok)
1049     fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1050   return ok;
1051 }
1052 #endif
1053 \f
1054 /* Specialized helper functions, used by `commands' to handle some
1055    options specially.  */
1056
1057 static int check_user_specified_header PARAMS ((const char *));
1058
1059 static int
1060 cmd_spec_dirstruct (const char *com, const char *val, void *place_ignored)
1061 {
1062   if (!cmd_boolean (com, val, &opt.dirstruct))
1063     return 0;
1064   /* Since dirstruct behaviour is explicitly changed, no_dirstruct
1065      must be affected inversely.  */
1066   if (opt.dirstruct)
1067     opt.no_dirstruct = 0;
1068   else
1069     opt.no_dirstruct = 1;
1070   return 1;
1071 }
1072
1073 static int
1074 cmd_spec_header (const char *com, const char *val, void *place)
1075 {
1076   if (!check_user_specified_header (val))
1077     {
1078       fprintf (stderr, _("%s: %s: Invalid header `%s'.\n"),
1079                exec_name, com, val);
1080       return 0;
1081     }
1082   return cmd_vector (com, val, place);
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   /* Just check for empty string and newline, so we don't throw total
1248      junk to the server.  */
1249   if (!*val || strchr (val, '\n'))
1250     {
1251       fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"),
1252                exec_name, com, val);
1253       return 0;
1254     }
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 PARAMS ((void));
1401 void http_cleanup PARAMS ((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 (opt.ftp_acc);
1451   xfree_null (opt.ftp_pass);
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 # endif
1465   xfree_null (opt.bind_address);
1466   xfree_null (opt.cookies_input);
1467   xfree_null (opt.cookies_output);
1468 #endif /* DEBUG_MALLOC */
1469 }