1 /* Reading/parsing the initialization file.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 This file is part of Wget.
6 This program 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.
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <sys/types.h>
38 # include <sys/socket.h>
39 # include <netinet/in.h>
40 # include <arpa/inet.h>
59 #define CMD_DECLARE(func) static int func \
60 PARAMS ((const char *, const char *, void *))
62 CMD_DECLARE (cmd_address);
63 CMD_DECLARE (cmd_boolean);
64 CMD_DECLARE (cmd_bytes);
65 CMD_DECLARE (cmd_directory_vector);
66 CMD_DECLARE (cmd_lockable_boolean);
67 CMD_DECLARE (cmd_number);
68 CMD_DECLARE (cmd_number_inf);
69 CMD_DECLARE (cmd_string);
70 CMD_DECLARE (cmd_time);
71 CMD_DECLARE (cmd_vector);
73 CMD_DECLARE (cmd_spec_dirstruct);
74 CMD_DECLARE (cmd_spec_dotstyle);
75 CMD_DECLARE (cmd_spec_header);
76 CMD_DECLARE (cmd_spec_htmlify);
77 CMD_DECLARE (cmd_spec_mirror);
78 CMD_DECLARE (cmd_spec_recursive);
79 CMD_DECLARE (cmd_spec_useragent);
81 /* List of recognized commands, each consisting of name, closure and function.
82 When adding a new command, simply add it to the list, but be sure to keep the
83 list sorted alphabetically, as comind() depends on it. Also, be sure to add
84 any entries that allocate memory (e.g. cmd_string and cmd_vector guys) to the
85 cleanup() function below. */
89 int (*action) PARAMS ((const char *, const char *, void *));
91 { "accept", &opt.accepts, cmd_vector },
92 { "addhostdir", &opt.add_hostdir, cmd_boolean },
93 { "alwaysrest", &opt.always_rest, cmd_boolean }, /* deprecated */
94 { "background", &opt.background, cmd_boolean },
95 { "backupconverted", &opt.backup_converted, cmd_boolean },
96 { "backups", &opt.backups, cmd_number },
97 { "base", &opt.base_href, cmd_string },
98 { "bindaddress", &opt.bind_address, cmd_address },
99 { "cache", &opt.proxy_cache, cmd_boolean },
100 { "continue", &opt.always_rest, cmd_boolean },
101 { "convertlinks", &opt.convert_links, cmd_boolean },
102 { "cutdirs", &opt.cut_dirs, cmd_number },
104 { "debug", &opt.debug, cmd_boolean },
106 { "deleteafter", &opt.delete_after, cmd_boolean },
107 { "dirprefix", &opt.dir_prefix, cmd_string },
108 { "dirstruct", NULL, cmd_spec_dirstruct },
109 { "domains", &opt.domains, cmd_vector },
110 { "dotbytes", &opt.dot_bytes, cmd_bytes },
111 { "dotsinline", &opt.dots_in_line, cmd_number },
112 { "dotspacing", &opt.dot_spacing, cmd_number },
113 { "dotstyle", NULL, cmd_spec_dotstyle },
114 { "excludedirectories", &opt.excludes, cmd_directory_vector },
115 { "excludedomains", &opt.exclude_domains, cmd_vector },
116 { "followftp", &opt.follow_ftp, cmd_boolean },
117 { "followtags", &opt.follow_tags, cmd_vector },
118 { "forcehtml", &opt.force_html, cmd_boolean },
119 { "ftpproxy", &opt.ftp_proxy, cmd_string },
120 { "glob", &opt.ftp_glob, cmd_boolean },
121 { "header", NULL, cmd_spec_header },
122 { "htmlextension", &opt.html_extension, cmd_boolean },
123 { "htmlify", NULL, cmd_spec_htmlify },
124 { "httpkeepalive", &opt.http_keep_alive, cmd_boolean },
125 { "httppasswd", &opt.http_passwd, cmd_string },
126 { "httpproxy", &opt.http_proxy, cmd_string },
127 { "httpsproxy", &opt.https_proxy, cmd_string },
128 { "httpuser", &opt.http_user, cmd_string },
129 { "ignorelength", &opt.ignore_length, cmd_boolean },
130 { "ignoretags", &opt.ignore_tags, cmd_vector },
131 { "includedirectories", &opt.includes, cmd_directory_vector },
132 { "input", &opt.input_filename, cmd_string },
133 { "killlonger", &opt.kill_longer, cmd_boolean },
134 { "logfile", &opt.lfilename, cmd_string },
135 { "login", &opt.ftp_acc, cmd_string },
136 { "mirror", NULL, cmd_spec_mirror },
137 { "netrc", &opt.netrc, cmd_boolean },
138 { "noclobber", &opt.noclobber, cmd_boolean },
139 { "noparent", &opt.no_parent, cmd_boolean },
140 { "noproxy", &opt.no_proxy, cmd_vector },
141 { "numtries", &opt.ntry, cmd_number_inf },/* deprecated*/
142 { "outputdocument", &opt.output_document, cmd_string },
143 { "pagerequisites", &opt.page_requisites, cmd_boolean },
144 { "passiveftp", &opt.ftp_pasv, cmd_lockable_boolean },
145 { "passwd", &opt.ftp_pass, cmd_string },
146 { "proxypasswd", &opt.proxy_passwd, cmd_string },
147 { "proxyuser", &opt.proxy_user, cmd_string },
148 { "quiet", &opt.quiet, cmd_boolean },
149 { "quota", &opt.quota, cmd_bytes },
150 { "reclevel", &opt.reclevel, cmd_number_inf },
151 { "recursive", NULL, cmd_spec_recursive },
152 { "referer", &opt.referer, cmd_string },
153 { "reject", &opt.rejects, cmd_vector },
154 { "relativeonly", &opt.relative_only, cmd_boolean },
155 { "removelisting", &opt.remove_listing, cmd_boolean },
156 { "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
157 { "robots", &opt.use_robots, cmd_boolean },
158 { "saveheaders", &opt.save_headers, cmd_boolean },
159 { "serverresponse", &opt.server_response, cmd_boolean },
160 { "simplehostcheck", &opt.simple_check, cmd_boolean },
161 { "spanhosts", &opt.spanhost, cmd_boolean },
162 { "spider", &opt.spider, cmd_boolean },
164 { "sslcertfile", &opt.sslcertfile, cmd_string },
165 { "sslcertkey", &opt.sslcertkey, cmd_string },
166 #endif /* HAVE_SSL */
167 { "timeout", &opt.timeout, cmd_time },
168 { "timestamping", &opt.timestamping, cmd_boolean },
169 { "tries", &opt.ntry, cmd_number_inf },
170 { "useproxy", &opt.use_proxy, cmd_boolean },
171 { "useragent", NULL, cmd_spec_useragent },
172 { "verbose", &opt.verbose, cmd_boolean },
173 { "wait", &opt.wait, cmd_time },
174 { "waitretry", &opt.waitretry, cmd_time }
177 /* Return index of COM if it is a valid command, or -1 otherwise. COM
178 is looked up in `commands' using binary search algorithm. */
180 comind (const char *com)
182 int min = 0, max = ARRAY_SIZE (commands) - 1;
186 int i = (min + max) / 2;
187 int cmp = strcasecmp (com, commands[i].name);
199 /* Reset the variables to default values. */
205 /* Most of the default values are 0. Just reset everything, and
206 fill in the non-zero values. Note that initializing pointers to
207 NULL this way is technically illegal, but porting Wget to a
208 machine where NULL is not all-zero bit pattern will be the least
209 of the implementors' worries. */
210 memset (&opt, 0, sizeof (opt));
213 opt.dir_prefix = xstrdup (".");
217 opt.ftp_acc = xstrdup ("anonymous");
218 /*opt.ftp_pass = xstrdup (ftp_getaddress ());*/
222 opt.http_keep_alive = 1;
224 tmp = getenv ("no_proxy");
226 opt.no_proxy = sepstring (tmp);
234 opt.remove_listing = 1;
236 opt.dot_bytes = 1024;
237 opt.dot_spacing = 10;
238 opt.dots_in_line = 50;
241 /* Return the user's home directory (strdup-ed), or NULL if none is
246 char *home = getenv ("HOME");
251 /* If HOME is not defined, try getting it from the password
253 struct passwd *pwd = getpwuid (getuid ());
254 if (!pwd || !pwd->pw_dir)
259 /* #### Maybe I should grab home_dir from registry, but the best
260 that I could get from there is user's Start menu. It sucks! */
264 return home ? xstrdup (home) : NULL;
267 /* Return the path to the user's .wgetrc. This is either the value of
268 `WGETRC' environment variable, or `$HOME/.wgetrc'.
270 If the `WGETRC' variable exists but the file does not exist, the
271 function will exit(). */
273 wgetrc_file_name (void)
278 /* Try the environment. */
279 env = getenv ("WGETRC");
282 if (!file_exists_p (env))
284 fprintf (stderr, "%s: %s: %s.\n", exec_name, file, strerror (errno));
287 return xstrdup (env);
291 /* If that failed, try $HOME/.wgetrc. */
295 file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
296 sprintf (file, "%s/.wgetrc", home);
300 /* Under Windows, "home" is (for the purposes of this function) the
301 directory where `wget.exe' resides, and `wget.ini' will be used
302 as file name. SYSTEM_WGETRC should not be defined under WINDOWS.
304 It is not as trivial as I assumed, because on 95 argv[0] is full
305 path, but on NT you get what you typed in command line. --dbudor */
309 file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
310 sprintf (file, "%swget.ini", home);
316 if (!file_exists_p (file))
324 /* Initialize variables from a wgetrc file */
326 run_wgetrc (const char *file)
332 fp = fopen (file, "rb");
335 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
336 file, strerror (errno));
339 /* Reset line number. */
341 while ((line = read_whole_line (fp)))
346 /* Parse the line. */
347 status = parse_line (line, &com, &val);
349 /* If everything is OK, set the value. */
352 if (!setval (com, val))
353 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
358 else if (status == 0)
359 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
366 /* Initialize the defaults and run the system wgetrc and user's own
373 /* Load the hard-coded defaults. */
376 /* If SYSTEM_WGETRC is defined, use it. */
378 if (file_exists_p (SYSTEM_WGETRC))
379 run_wgetrc (SYSTEM_WGETRC);
381 /* Override it with your own, if one exists. */
382 file = wgetrc_file_name ();
385 /* #### We should somehow canonicalize `file' and SYSTEM_WGETRC,
388 if (!strcmp (file, SYSTEM_WGETRC))
390 fprintf (stderr, _("\
391 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
401 /* Parse the line pointed by line, with the syntax:
402 <sp>* command <sp>* = <sp>* value <newline>
403 Uses malloc to allocate space for command and value.
404 If the line is invalid, data is freed and 0 is returned.
411 parse_line (const char *line, char **com, char **val)
413 const char *p = line;
414 const char *orig_comptr, *end;
417 /* Skip whitespace. */
418 while (*p && ISSPACE (*p))
421 /* Don't process empty lines. */
422 if (!*p || *p == '#')
425 for (orig_comptr = p; ISALPHA (*p) || *p == '_' || *p == '-'; p++)
427 /* The next char should be space or '='. */
428 if (!ISSPACE (*p) && (*p != '='))
430 /* Here we cannot use strdupdelim() as we normally would because we
431 want to skip the `-' and `_' characters in the input string. */
432 *com = (char *)xmalloc (p - orig_comptr + 1);
433 for (new_comptr = *com; orig_comptr < p; orig_comptr++)
435 if (*orig_comptr == '_' || *orig_comptr == '-')
437 *new_comptr++ = *orig_comptr;
440 /* If the command is invalid, exit now. */
441 if (comind (*com) == -1)
447 /* Skip spaces before '='. */
448 for (; ISSPACE (*p); p++);
449 /* If '=' not found, bail out. */
455 /* Skip spaces after '='. */
456 for (++p; ISSPACE (*p); p++);
457 /* Get the ending position for VAL by starting with the end of the
458 line and skipping whitespace. */
459 end = line + strlen (line) - 1;
460 while (end > p && ISSPACE (*end))
462 *val = strdupdelim (p, end + 1);
466 /* Set COM to VAL. This is the meat behind processing `.wgetrc'. No
467 fatals -- error signal prints a warning and resets to default
468 value. All error messages are printed to stderr, *not* to
469 opt.lfile, since opt.lfile wasn't even generated yet. */
471 setval (const char *com, const char *val)
480 /* #### Should I just abort()? */
482 fprintf (stderr, _("%s: BUG: unknown command `%s', value `%s'.\n"),
483 exec_name, com, val);
487 return ((*commands[ind].action) (com, val, commands[ind].closure));
490 /* Generic helper functions, for use with `commands'. */
492 static int myatoi PARAMS ((const char *s));
494 /* Interpret VAL as an Internet address (a hostname or a dotted-quad
495 IP address), and write it (in network order) to a malloc-allocated
496 address. That address gets stored to the memory pointed to by
497 CLOSURE. COM is ignored, except for error messages.
499 #### IMHO it's a mistake to do this kind of work so early in the
500 process (before any download even started!) opt.bind_address
501 should simply remember the provided value as a string. Another
502 function should do the lookup, when needed, and cache the
505 cmd_address (const char *com, const char *val, void *closure)
507 struct sockaddr_in sin;
508 struct sockaddr_in **target = (struct sockaddr_in **)closure;
510 if (!store_hostaddress ((unsigned char *)&sin.sin_addr, val))
512 fprintf (stderr, _("%s: %s: Cannot convert `%s' to an IP address.\n"),
513 exec_name, com, val);
517 sin.sin_family = AF_INET;
520 FREE_MAYBE (*target);
522 *target = xmalloc (sizeof (sin));
523 memcpy (*target, &sin, sizeof (sin));
528 /* Store the boolean value from VAL to CLOSURE. COM is ignored,
529 except for error messages. */
531 cmd_boolean (const char *com, const char *val, void *closure)
535 if (!strcasecmp (val, "on")
536 || (*val == '1' && !*(val + 1)))
538 else if (!strcasecmp (val, "off")
539 || (*val == '0' && !*(val + 1)))
543 fprintf (stderr, _("%s: %s: Please specify on or off.\n"),
548 *(int *)closure = bool_value;
552 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to CLOSURE. COM is
553 ignored, except for error messages. Values 2 and -1 indicate that once
554 defined, the value may not be changed by successive wgetrc files or
555 command-line arguments.
557 Values: 2 - Enable a particular option for good ("always")
558 1 - Enable an option ("on")
559 0 - Disable an option ("off")
560 -1 - Disable an option for good ("never") */
562 cmd_lockable_boolean (const char *com, const char *val, void *closure)
564 int lockable_boolean_value;
567 * If a config file said "always" or "never", don't allow command line
568 * arguments to override the config file.
570 if (*(int *)closure == -1 || *(int *)closure == 2)
573 if (!strcasecmp (val, "always")
574 || (*val == '2' && !*(val + 1)))
575 lockable_boolean_value = 2;
576 else if (!strcasecmp (val, "on")
577 || (*val == '1' && !*(val + 1)))
578 lockable_boolean_value = 1;
579 else if (!strcasecmp (val, "off")
580 || (*val == '0' && !*(val + 1)))
581 lockable_boolean_value = 0;
582 else if (!strcasecmp (val, "never")
583 || (*val == '-' && *(val + 1) == '1' && !*(val + 2)))
584 lockable_boolean_value = -1;
587 fprintf (stderr, _("%s: %s: Please specify always, on, off, "
593 *(int *)closure = lockable_boolean_value;
597 /* Set the non-negative integer value from VAL to CLOSURE. With
598 incorrect specification, the number remains unchanged. */
600 cmd_number (const char *com, const char *val, void *closure)
602 int num = myatoi (val);
606 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
607 exec_name, com, val);
610 *(int *)closure = num;
614 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
616 cmd_number_inf (const char *com, const char *val, void *closure)
618 if (!strcasecmp (val, "inf"))
623 return cmd_number (com, val, closure);
626 /* Copy (strdup) the string at COM to a new location and place a
627 pointer to *CLOSURE. */
629 cmd_string (const char *com, const char *val, void *closure)
631 char **pstring = (char **)closure;
633 FREE_MAYBE (*pstring);
634 *pstring = xstrdup (val);
638 /* Merge the vector (array of strings separated with `,') in COM with
639 the vector (NULL-terminated array of strings) pointed to by
642 cmd_vector (const char *com, const char *val, void *closure)
644 char ***pvec = (char ***)closure;
647 *pvec = merge_vecs (*pvec, sepstring (val));
657 cmd_directory_vector (const char *com, const char *val, void *closure)
659 char ***pvec = (char ***)closure;
663 /* Strip the trailing slashes from directories. */
666 seps = sepstring (val);
667 for (t = seps; t && *t; t++)
669 int len = strlen (*t);
670 /* Skip degenerate case of root directory. */
673 if ((*t)[len - 1] == '/')
674 (*t)[len - 1] = '\0';
677 *pvec = merge_vecs (*pvec, seps);
687 /* Set the value stored in VAL to CLOSURE (which should point to a
688 long int), allowing several postfixes, with the following syntax
692 [0-9]+[kK] -> bytes * 1024
693 [0-9]+[mM] -> bytes * 1024 * 1024
696 Anything else is flagged as incorrect, and CLOSURE is unchanged. */
698 cmd_bytes (const char *com, const char *val, void *closure)
701 long *out = (long *)closure;
706 /* Check for "inf". */
707 if (p[0] == 'i' && p[1] == 'n' && p[2] == 'f' && p[3] == '\0')
712 /* Search for digits and construct result. */
713 for (; *p && ISDIGIT (*p); p++)
714 result = (10 * result) + (*p - '0');
715 /* If no digits were found, or more than one character is following
717 if (p == val || (*p != '\0' && *(p + 1) != '\0'))
719 printf (_("%s: Invalid specification `%s'\n"), com, val);
722 /* Search for a designator. */
723 switch (TOLOWER (*p))
734 result *= (long)1024 * 1024;
738 result *= (long)1024 * 1024 * 1024;
741 printf (_("%s: Invalid specification `%s'\n"), com, val);
748 /* Store the value of VAL to *OUT, allowing suffixes for minutes and
751 cmd_time (const char *com, const char *val, void *closure)
756 /* Search for digits and construct result. */
757 for (; *p && ISDIGIT (*p); p++)
758 result = (10 * result) + (*p - '0');
759 /* If no digits were found, or more than one character is following
761 if (p == val || (*p != '\0' && *(p + 1) != '\0'))
763 printf (_("%s: Invalid specification `%s'\n"), com, val);
766 /* Search for a suffix. */
767 switch (TOLOWER (*p))
781 /* Days (overflow on 16bit machines) */
789 printf (_("%s: Invalid specification `%s'\n"), com, val);
792 *(long *)closure = result;
796 /* Specialized helper functions, used by `commands' to handle some
797 options specially. */
799 static int check_user_specified_header PARAMS ((const char *));
802 cmd_spec_dirstruct (const char *com, const char *val, void *closure)
804 if (!cmd_boolean (com, val, &opt.dirstruct))
806 /* Since dirstruct behaviour is explicitly changed, no_dirstruct
807 must be affected inversely. */
809 opt.no_dirstruct = 0;
811 opt.no_dirstruct = 1;
816 cmd_spec_dotstyle (const char *com, const char *val, void *closure)
818 /* Retrieval styles. */
819 if (!strcasecmp (val, "default"))
821 /* Default style: 1K dots, 10 dots in a cluster, 50 dots in a
823 opt.dot_bytes = 1024;
824 opt.dot_spacing = 10;
825 opt.dots_in_line = 50;
827 else if (!strcasecmp (val, "binary"))
829 /* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots
831 opt.dot_bytes = 8192;
832 opt.dot_spacing = 16;
833 opt.dots_in_line = 48;
835 else if (!strcasecmp (val, "mega"))
837 /* "Mega" retrieval, for retrieving very long files; each dot is
838 64K, 8 dots in a cluster, 6 clusters (3M) in a line. */
839 opt.dot_bytes = 65536L;
841 opt.dots_in_line = 48;
843 else if (!strcasecmp (val, "giga"))
845 /* "Giga" retrieval, for retrieving very very *very* long files;
846 each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a
848 opt.dot_bytes = (1L << 20);
850 opt.dots_in_line = 32;
852 else if (!strcasecmp (val, "micro"))
854 /* "Micro" retrieval, for retrieving very small files (and/or
855 slow connections); each dot is 128 bytes, 8 dots in a
856 cluster, 6 clusters (6K) in a line. */
859 opt.dots_in_line = 48;
863 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
864 exec_name, com, val);
871 cmd_spec_header (const char *com, const char *val, void *closure)
875 /* Empty header means reset headers. */
876 FREE_MAYBE (opt.user_header);
877 opt.user_header = NULL;
883 if (!check_user_specified_header (val))
885 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
886 exec_name, com, val);
889 i = opt.user_header ? strlen (opt.user_header) : 0;
890 opt.user_header = (char *)xrealloc (opt.user_header, i + strlen (val)
892 strcpy (opt.user_header + i, val);
894 opt.user_header[i++] = '\r';
895 opt.user_header[i++] = '\n';
896 opt.user_header[i] = '\0';
902 cmd_spec_htmlify (const char *com, const char *val, void *closure)
904 int flag = cmd_boolean (com, val, &opt.htmlify);
905 if (flag && !opt.htmlify)
906 opt.remove_listing = 0;
911 cmd_spec_mirror (const char *com, const char *val, void *closure)
915 if (!cmd_boolean (com, val, &mirror))
920 if (!opt.no_dirstruct)
922 opt.timestamping = 1;
923 opt.reclevel = INFINITE_RECURSION;
924 opt.remove_listing = 0;
930 cmd_spec_recursive (const char *com, const char *val, void *closure)
932 if (!cmd_boolean (com, val, &opt.recursive))
936 if (opt.recursive && !opt.no_dirstruct)
943 cmd_spec_useragent (const char *com, const char *val, void *closure)
945 /* Just check for empty string and newline, so we don't throw total
946 junk to the server. */
947 if (!*val || strchr (val, '\n'))
949 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
950 exec_name, com, val);
953 opt.useragent = xstrdup (val);
957 /* Miscellaneous useful routines. */
959 /* Return the integer value of a positive integer written in S, or -1
960 if an error was encountered. */
962 myatoi (const char *s)
965 const char *orig = s;
967 for (res = 0; *s && ISDIGIT (*s); s++)
968 res = 10 * res + (*s - '0');
975 #define ISODIGIT(x) ((x) >= '0' && (x) <= '7')
978 check_user_specified_header (const char *s)
982 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
983 /* The header MUST contain `:' preceded by at least one
984 non-whitespace character. */
985 if (*p != ':' || p == s)
987 /* The header MUST NOT contain newlines. */
988 if (strchr (s, '\n'))
993 void cleanup_html_url PARAMS ((void));
994 void downloaded_files_free PARAMS ((void));
997 /* Free the memory allocated by global variables. */
1001 extern acc_t *netrc_list;
1003 recursive_cleanup ();
1005 free_netrc (netrc_list);
1008 cleanup_html_url ();
1009 downloaded_files_free ();
1010 FREE_MAYBE (opt.lfilename);
1011 xfree (opt.dir_prefix);
1012 FREE_MAYBE (opt.input_filename);
1013 FREE_MAYBE (opt.output_document);
1014 free_vec (opt.accepts);
1015 free_vec (opt.rejects);
1016 free_vec (opt.excludes);
1017 free_vec (opt.includes);
1018 free_vec (opt.domains);
1019 free_vec (opt.follow_tags);
1020 free_vec (opt.ignore_tags);
1021 xfree (opt.ftp_acc);
1022 FREE_MAYBE (opt.ftp_pass);
1023 FREE_MAYBE (opt.ftp_proxy);
1024 FREE_MAYBE (opt.https_proxy);
1025 FREE_MAYBE (opt.http_proxy);
1026 free_vec (opt.no_proxy);
1027 FREE_MAYBE (opt.useragent);
1028 FREE_MAYBE (opt.referer);
1029 FREE_MAYBE (opt.http_user);
1030 FREE_MAYBE (opt.http_passwd);
1031 FREE_MAYBE (opt.user_header);
1033 FREE_MAYBE (opt.sslcertkey);
1034 FREE_MAYBE (opt.sslcertfile);
1035 #endif /* HAVE_SSL */
1036 FREE_MAYBE (opt.bind_address);