1 /* Reading/parsing the initialization file.
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
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.
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.
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.
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. */
33 #include <sys/types.h>
56 #include "recur.h" /* for INFINITE_RECURSION */
57 #include "convert.h" /* for convert_cleanup */
58 #include "res.h" /* for res_cleanup */
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. */
68 static int enable_tilde_expansion;
71 #define CMD_DECLARE(func) static int func \
72 PARAMS ((const char *, const char *, void *))
74 CMD_DECLARE (cmd_boolean);
75 CMD_DECLARE (cmd_bytes);
76 CMD_DECLARE (cmd_bytes_large);
78 CMD_DECLARE (cmd_cert_type);
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);
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);
99 CMD_DECLARE (cmd_spec_secure_protocol);
101 CMD_DECLARE (cmd_spec_timeout);
102 CMD_DECLARE (cmd_spec_useragent);
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. */
114 int (*action) PARAMS ((const char *, const char *, void *));
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 },
125 { "cacertificate", &opt.ca_cert, cmd_file },
127 { "cache", &opt.allow_cache, cmd_boolean },
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 },
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 },
140 { "debug", &opt.debug, cmd_boolean },
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 },
153 { "egdfile", &opt.egd_file, cmd_file },
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_passwd, cmd_string }, /* deprecated */
161 { "ftppassword", &opt.ftp_passwd, cmd_string },
162 { "ftpuser", &opt.ftp_user, cmd_string },
163 { "ftpproxy", &opt.ftp_proxy, cmd_string },
164 { "glob", &opt.ftp_glob, cmd_boolean },
165 { "header", &opt.user_headers, cmd_spec_header },
166 { "htmlextension", &opt.html_extension, cmd_boolean },
167 { "htmlify", NULL, cmd_spec_htmlify },
168 { "httpkeepalive", &opt.http_keep_alive, cmd_boolean },
169 { "httppasswd", &opt.http_passwd, cmd_string }, /* deprecated */
170 { "httppassword", &opt.http_passwd, cmd_string },
171 { "httpproxy", &opt.http_proxy, cmd_string },
172 { "httpsproxy", &opt.https_proxy, cmd_string },
173 { "httpuser", &opt.http_user, cmd_string },
174 { "ignorelength", &opt.ignore_length, cmd_boolean },
175 { "ignoretags", &opt.ignore_tags, cmd_vector },
176 { "includedirectories", &opt.includes, cmd_directory_vector },
178 { "inet4only", &opt.ipv4_only, cmd_boolean },
179 { "inet6only", &opt.ipv6_only, cmd_boolean },
181 { "input", &opt.input_filename, cmd_file },
182 { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
183 { "killlonger", &opt.kill_longer, cmd_boolean },
184 { "limitrate", &opt.limit_rate, cmd_bytes },
185 { "loadcookies", &opt.cookies_input, cmd_file },
186 { "logfile", &opt.lfilename, cmd_file },
187 { "login", &opt.ftp_user, cmd_string },/* deprecated*/
188 { "mirror", NULL, cmd_spec_mirror },
189 { "netrc", &opt.netrc, cmd_boolean },
190 { "noclobber", &opt.noclobber, cmd_boolean },
191 { "noparent", &opt.no_parent, cmd_boolean },
192 { "noproxy", &opt.no_proxy, cmd_vector },
193 { "numtries", &opt.ntry, cmd_number_inf },/* deprecated*/
194 { "outputdocument", &opt.output_document, cmd_file },
195 { "pagerequisites", &opt.page_requisites, cmd_boolean },
196 { "passiveftp", &opt.ftp_pasv, cmd_lockable_boolean },
197 { "passwd", &opt.ftp_passwd, cmd_string },/* deprecated*/
198 { "password", &opt.passwd, cmd_string },
199 { "postdata", &opt.post_data, cmd_string },
200 { "postfile", &opt.post_file_name, cmd_file },
201 { "preferfamily", NULL, cmd_spec_prefer_family },
202 { "preservepermissions", &opt.preserve_perm, cmd_boolean },
204 { "privatekey", &opt.private_key, cmd_file },
205 { "privatekeytype", &opt.private_key_type, cmd_cert_type },
207 { "progress", &opt.progress_type, cmd_spec_progress },
208 { "protocoldirectories", &opt.protocol_directories, cmd_boolean },
209 { "proxypasswd", &opt.proxy_passwd, cmd_string }, /* deprecated */
210 { "proxypassword", &opt.proxy_passwd, cmd_string },
211 { "proxyuser", &opt.proxy_user, cmd_string },
212 { "quiet", &opt.quiet, cmd_boolean },
213 { "quota", &opt.quota, cmd_bytes_large },
214 { "randomfile", &opt.random_file, cmd_file },
215 { "randomwait", &opt.random_wait, cmd_boolean },
216 { "readtimeout", &opt.read_timeout, cmd_time },
217 { "reclevel", &opt.reclevel, cmd_number_inf },
218 { "recursive", NULL, cmd_spec_recursive },
219 { "referer", &opt.referer, cmd_string },
220 { "reject", &opt.rejects, cmd_vector },
221 { "relativeonly", &opt.relative_only, cmd_boolean },
222 { "removelisting", &opt.remove_listing, cmd_boolean },
223 { "restrictfilenames", NULL, cmd_spec_restrict_file_names },
224 { "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
225 { "retryconnrefused", &opt.retry_connrefused, cmd_boolean },
226 { "robots", &opt.use_robots, cmd_boolean },
227 { "savecookies", &opt.cookies_output, cmd_file },
228 { "saveheaders", &opt.save_headers, cmd_boolean },
230 { "secureprotocol", &opt.secure_protocol, cmd_spec_secure_protocol },
232 { "serverresponse", &opt.server_response, cmd_boolean },
233 { "spanhosts", &opt.spanhost, cmd_boolean },
234 { "spider", &opt.spider, cmd_boolean },
235 { "strictcomments", &opt.strict_comments, cmd_boolean },
236 { "timeout", NULL, cmd_spec_timeout },
237 { "timestamping", &opt.timestamping, cmd_boolean },
238 { "tries", &opt.ntry, cmd_number_inf },
239 { "useproxy", &opt.use_proxy, cmd_boolean },
240 { "user", &opt.user, cmd_string },
241 { "useragent", NULL, cmd_spec_useragent },
242 { "verbose", &opt.verbose, cmd_boolean },
243 { "wait", &opt.wait, cmd_time },
244 { "waitretry", &opt.waitretry, cmd_time }
247 /* Look up CMDNAME in the commands[] and return its position in the
248 array. If CMDNAME is not found, return -1. */
251 command_by_name (const char *cmdname)
253 /* Use binary search for speed. Wget has ~100 commands, which
254 guarantees a worst case performance of 7 string comparisons. */
255 int lo = 0, hi = countof (commands) - 1;
259 int mid = (lo + hi) >> 1;
260 int cmp = strcasecmp (cmdname, commands[mid].name);
271 /* Reset the variables to default values. */
277 /* Most of the default values are 0. Just reset everything, and
278 fill in the non-zero values. Note that initializing pointers to
279 NULL this way is technically illegal, but porting Wget to a
280 machine where NULL is not all-zero bit pattern will be the least
281 of the implementors' worries. */
292 opt.http_keep_alive = 1;
294 tmp = getenv ("no_proxy");
296 opt.no_proxy = sepstring (tmp);
299 opt.read_timeout = 900;
302 opt.remove_listing = 1;
304 opt.dot_bytes = 1024;
305 opt.dot_spacing = 10;
306 opt.dots_in_line = 50;
315 /* The default for file name restriction defaults to the OS type. */
316 #if !defined(WINDOWS) && !defined(__CYGWIN__)
317 opt.restrict_files_os = restrict_unix;
319 opt.restrict_files_os = restrict_windows;
321 opt.restrict_files_ctrl = 1;
324 /* Return the user's home directory (strdup-ed), or NULL if none is
329 char *home = getenv ("HOME");
334 /* If HOME is not defined, try getting it from the password
336 struct passwd *pwd = getpwuid (getuid ());
337 if (!pwd || !pwd->pw_dir)
341 /* Under Windows, if $HOME isn't defined, use the directory where
342 `wget.exe' resides. */
347 return home ? xstrdup (home) : NULL;
350 /* Return the path to the user's .wgetrc. This is either the value of
351 `WGETRC' environment variable, or `$HOME/.wgetrc'.
353 If the `WGETRC' variable exists but the file does not exist, the
354 function will exit(). */
356 wgetrc_file_name (void)
361 /* Try the environment. */
362 env = getenv ("WGETRC");
365 if (!file_exists_p (env))
367 fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"),
371 return xstrdup (env);
374 /* If that failed, try $HOME/.wgetrc. */
377 file = aprintf ("%s/.wgetrc", home);
381 /* Under Windows, if we still haven't found .wgetrc, look for the file
382 `wget.ini' in the directory where `wget.exe' resides; we do this for
383 backward compatibility with previous versions of Wget.
384 SYSTEM_WGETRC should not be defined under WINDOWS. */
385 if (!file || !file_exists_p (file))
391 file = aprintf ("%s/wget.ini", home);
397 if (!file_exists_p (file))
405 static int parse_line PARAMS ((const char *, char **, char **, int *));
406 static int setval_internal PARAMS ((int, const char *, const char *));
408 /* Initialize variables from a wgetrc file. */
411 run_wgetrc (const char *file)
417 fp = fopen (file, "rb");
420 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
421 file, strerror (errno));
424 enable_tilde_expansion = 1;
426 while ((line = read_whole_line (fp)) != NULL)
431 /* Parse the line. */
432 status = parse_line (line, &com, &val, &comind);
434 /* If everything is OK, set the value. */
437 if (!setval_internal (comind, com, val))
438 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
443 else if (status == 0)
444 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
448 enable_tilde_expansion = 0;
452 /* Initialize the defaults and run the system wgetrc and user's own
459 /* Load the hard-coded defaults. */
462 /* If SYSTEM_WGETRC is defined, use it. */
464 if (file_exists_p (SYSTEM_WGETRC))
465 run_wgetrc (SYSTEM_WGETRC);
467 /* Override it with your own, if one exists. */
468 file = wgetrc_file_name ();
471 /* #### We should canonicalize `file' and SYSTEM_WGETRC with
472 something like realpath() before comparing them with `strcmp' */
474 if (!strcmp (file, SYSTEM_WGETRC))
476 fprintf (stderr, _("\
477 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
487 /* Remove dashes and underscores from S, modifying S in the
493 char *t = s; /* t - tortoise */
494 char *h = s; /* h - hare */
496 if (*h == '_' || *h == '-')
503 /* Parse the line pointed by line, with the syntax:
504 <sp>* command <sp>* = <sp>* value <sp>*
505 Uses malloc to allocate space for command and value.
506 If the line is invalid, data is freed and 0 is returned.
513 In case of success, *COM and *VAL point to freshly allocated
514 strings, and *COMIND points to com's index. In case of error or
515 empty line, those values are unaffected. */
518 parse_line (const char *line, char **com, char **val, int *comind)
521 const char *end = line + strlen (line);
522 const char *cmdstart, *cmdend;
523 const char *valstart, *valend;
528 /* Skip leading and trailing whitespace. */
529 while (*line && ISSPACE (*line))
531 while (end > line && ISSPACE (end[-1]))
534 /* Skip empty lines and comments. */
535 if (!*line || *line == '#')
541 while (p < end && (ISALPHA (*p) || *p == '_' || *p == '-'))
545 /* Skip '=', as well as any space before or after it. */
546 while (p < end && ISSPACE (*p))
548 if (p == end || *p != '=')
551 while (p < end && ISSPACE (*p))
557 /* The line now known to be syntactically correct. Check whether
558 the command is valid. */
559 BOUNDED_TO_ALLOCA (cmdstart, cmdend, cmdcopy);
561 ind = command_by_name (cmdcopy);
565 /* The command is valid. Now fill in the values and report success
568 *com = strdupdelim (cmdstart, cmdend);
569 *val = strdupdelim (valstart, valend);
573 /* Run commands[comind].action. */
576 setval_internal (int comind, const char *com, const char *val)
578 assert (0 <= comind && comind < countof (commands));
579 DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
580 return ((*commands[comind].action) (com, val, commands[comind].place));
583 /* Run command COM with value VAL. If running the command produces an
584 error, report the error and exit.
586 This is intended to be called from main() to modify Wget's behavior
587 through command-line switches. Since COM is hard-coded in main(),
588 it is not canonicalized, and this aborts when COM is not found.
590 If COMIND's are exported to init.h, this function will be changed
591 to accept COMIND directly. */
594 setoptval (const char *com, const char *val)
596 assert (val != NULL);
597 if (!setval_internal (command_by_name (com), com, val))
601 /* Parse OPT into command and value and run it. For example,
602 run_command("foo=bar") is equivalent to setoptval("foo", "bar").
603 This is used by the `--execute' flag in main.c. */
606 run_command (const char *opt)
610 int status = parse_line (opt, &com, &val, &comind);
613 if (!setval_internal (comind, com, val))
618 else if (status == 0)
620 fprintf (stderr, _("%s: Invalid --execute command `%s'\n"),
626 /* Generic helper functions, for use with `commands'. */
628 /* Forward declarations: */
633 static int decode_string PARAMS ((const char *, const struct decode_item *,
635 static int simple_atoi PARAMS ((const char *, const char *, int *));
636 static int simple_atof PARAMS ((const char *, const char *, double *));
638 #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0')
640 #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0) \
641 && TOLOWER((p)[1]) == (c1) \
644 #define CMP3(p, c0, c1, c2) (TOLOWER((p)[0]) == (c0) \
645 && TOLOWER((p)[1]) == (c1) \
646 && TOLOWER((p)[2]) == (c2) \
650 /* Store the boolean value from VAL to PLACE. COM is ignored,
651 except for error messages. */
653 cmd_boolean (const char *com, const char *val, void *place)
657 if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
658 /* "on", "yes" and "1" mean true. */
660 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
661 /* "off", "no" and "0" mean false. */
666 _("%s: %s: Invalid boolean `%s', use `on' or `off'.\n"),
667 exec_name, com, val);
671 *(int *)place = bool_value;
675 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to PLACE.
676 COM is ignored, except for error messages. Values 2 and -1
677 indicate that once defined, the value may not be changed by
678 successive wgetrc files or command-line arguments.
680 Values: 2 - Enable a particular option for good ("always")
681 1 - Enable an option ("on")
682 0 - Disable an option ("off")
683 -1 - Disable an option for good ("never") */
685 cmd_lockable_boolean (const char *com, const char *val, void *place)
687 int lockable_boolean_value;
689 int oldval = *(int *)place;
692 * If a config file said "always" or "never", don't allow command line
693 * arguments to override the config file.
695 if (oldval == -1 || oldval == 2)
698 if (0 == strcasecmp (val, "always") || CMP1 (val, '2'))
699 lockable_boolean_value = 2;
700 else if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
701 lockable_boolean_value = 1;
702 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
703 lockable_boolean_value = 0;
704 else if (0 == strcasecmp (val, "never") || CMP2 (val, '-', '1'))
705 lockable_boolean_value = -1;
709 _("%s: %s: Invalid boolean `%s', use always, on, off, or never.\n"),
710 exec_name, com, val);
714 *(int *)place = lockable_boolean_value;
718 /* Set the non-negative integer value from VAL to PLACE. With
719 incorrect specification, the number remains unchanged. */
721 cmd_number (const char *com, const char *val, void *place)
723 if (!simple_atoi (val, val + strlen (val), place)
724 || *(int *) place < 0)
726 fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
727 exec_name, com, val);
733 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
735 cmd_number_inf (const char *com, const char *val, void *place)
737 if (!strcasecmp (val, "inf"))
742 return cmd_number (com, val, place);
745 /* Copy (strdup) the string at COM to a new location and place a
746 pointer to *PLACE. */
748 cmd_string (const char *com, const char *val, void *place)
750 char **pstring = (char **)place;
752 xfree_null (*pstring);
753 *pstring = xstrdup (val);
758 # define ISSEP(c) ((c) == '/')
760 # define ISSEP(c) ((c) == '/' || (c) == '\\')
763 /* Like the above, but handles tilde-expansion when reading a user's
764 `.wgetrc'. In that case, and if VAL begins with `~', the tilde
765 gets expanded to the user's home directory. */
767 cmd_file (const char *com, const char *val, void *place)
769 char **pstring = (char **)place;
771 xfree_null (*pstring);
773 /* #### If VAL is empty, perhaps should set *PLACE to NULL. */
775 if (!enable_tilde_expansion || !(*val == '~' && ISSEP (val[1])))
778 *pstring = xstrdup (val);
783 char *home = home_dir ();
787 homelen = strlen (home);
788 while (homelen && ISSEP (home[homelen - 1]))
789 home[--homelen] = '\0';
791 /* Skip the leading "~/". */
792 for (++val; ISSEP (*val); val++)
795 *pstring = concat_strings (home, "/", val, (char *) 0);
799 /* Convert "\" to "/". */
802 for (s = *pstring; *s; s++)
810 /* Like cmd_file, but strips trailing '/' characters. */
812 cmd_directory (const char *com, const char *val, void *place)
816 /* Call cmd_file() for tilde expansion and separator
817 canonicalization (backslash -> slash under Windows). These
818 things should perhaps be in a separate function. */
819 if (!cmd_file (com, val, place))
824 while (t > s && *--t == '/')
830 /* Split VAL by space to a vector of values, and append those values
831 to vector pointed to by the PLACE argument. If VAL is empty, the
832 PLACE vector is cleared instead. */
835 cmd_vector (const char *com, const char *val, void *place)
837 char ***pvec = (char ***)place;
840 *pvec = merge_vecs (*pvec, sepstring (val));
850 cmd_directory_vector (const char *com, const char *val, void *place)
852 char ***pvec = (char ***)place;
856 /* Strip the trailing slashes from directories. */
859 seps = sepstring (val);
860 for (t = seps; t && *t; t++)
862 int len = strlen (*t);
863 /* Skip degenerate case of root directory. */
866 if ((*t)[len - 1] == '/')
867 (*t)[len - 1] = '\0';
870 *pvec = merge_vecs (*pvec, seps);
880 /* Engine for cmd_bytes and cmd_bytes_large: converts a string such as
881 "100k" or "2.5G" to a floating point number. */
884 parse_bytes_helper (const char *val, double *result)
887 const char *end = val + strlen (val);
889 /* Check for "inf". */
890 if (0 == strcmp (val, "inf"))
896 /* Strip trailing whitespace. */
897 while (val < end && ISSPACE (end[-1]))
902 switch (TOLOWER (end[-1]))
905 --end, mult = 1024.0;
908 --end, mult = 1048576.0;
911 --end, mult = 1073741824.0;
914 --end, mult = 1099511627776.0;
917 /* Not a recognized suffix: assume it's a digit. (If not,
918 simple_atof will raise an error.) */
922 /* Skip leading and trailing whitespace. */
923 while (val < end && ISSPACE (*val))
925 while (val < end && ISSPACE (end[-1]))
930 if (!simple_atof (val, end, &number) || number < 0)
933 *result = number * mult;
937 /* Parse VAL as a number and set its value to PLACE (which should
940 By default, the value is assumed to be in bytes. If "K", "M", or
941 "G" are appended, the value is multiplied with 1<<10, 1<<20, or
942 1<<30, respectively. Floating point values are allowed and are
943 cast to integer before use. The idea is to be able to use things
944 like 1.5k instead of "1536".
946 The string "inf" is returned as 0.
948 In case of error, 0 is returned and memory pointed to by PLACE
949 remains unmodified. */
952 cmd_bytes (const char *com, const char *val, void *place)
955 if (!parse_bytes_helper (val, &byte_value))
957 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
958 exec_name, com, val);
961 *(wgint *)place = (wgint)byte_value;
965 /* Like cmd_bytes, but PLACE is interpreted as a pointer to
966 LARGE_INT. It works by converting the string to double, therefore
967 working with values up to 2^53-1 without loss of precision. This
968 value (8192 TB) is large enough to serve for a while. */
971 cmd_bytes_large (const char *com, const char *val, void *place)
974 if (!parse_bytes_helper (val, &byte_value))
976 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
977 exec_name, com, val);
980 *(LARGE_INT *)place = (LARGE_INT)byte_value;
984 /* Store the value of VAL to *OUT. The value is a time period, by
985 default expressed in seconds, but also accepting suffixes "m", "h",
986 "d", and "w" for minutes, hours, days, and weeks respectively. */
989 cmd_time (const char *com, const char *val, void *place)
992 const char *end = val + strlen (val);
994 /* Strip trailing whitespace. */
995 while (val < end && ISSPACE (end[-1]))
1001 fprintf (stderr, _("%s: %s: Invalid time period `%s'\n"),
1002 exec_name, com, val);
1006 switch (TOLOWER (end[-1]))
1009 --end, mult = 1; /* seconds */
1012 --end, mult = 60; /* minutes */
1015 --end, mult = 3600; /* hours */
1018 --end, mult = 86400.0; /* days */
1021 --end, mult = 604800.0; /* weeks */
1024 /* Not a recognized suffix: assume it belongs to the number.
1025 (If not, simple_atof will raise an error.) */
1029 /* Skip leading and trailing whitespace. */
1030 while (val < end && ISSPACE (*val))
1032 while (val < end && ISSPACE (end[-1]))
1037 if (!simple_atof (val, end, &number))
1040 *(double *)place = number * mult;
1046 cmd_cert_type (const char *com, const char *val, void *place)
1048 static const struct decode_item choices[] = {
1049 { "pem", keyfile_pem },
1050 { "der", keyfile_asn1 },
1051 { "asn1", keyfile_asn1 },
1053 int ok = decode_string (val, choices, countof (choices), place);
1055 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1060 /* Specialized helper functions, used by `commands' to handle some
1061 options specially. */
1063 static int check_user_specified_header PARAMS ((const char *));
1066 cmd_spec_dirstruct (const char *com, const char *val, void *place_ignored)
1068 if (!cmd_boolean (com, val, &opt.dirstruct))
1070 /* Since dirstruct behaviour is explicitly changed, no_dirstruct
1071 must be affected inversely. */
1073 opt.no_dirstruct = 0;
1075 opt.no_dirstruct = 1;
1080 cmd_spec_header (const char *com, const char *val, void *place)
1082 if (!check_user_specified_header (val))
1084 fprintf (stderr, _("%s: %s: Invalid header `%s'.\n"),
1085 exec_name, com, val);
1088 return cmd_vector (com, val, place);
1092 cmd_spec_htmlify (const char *com, const char *val, void *place_ignored)
1094 int flag = cmd_boolean (com, val, &opt.htmlify);
1095 if (flag && !opt.htmlify)
1096 opt.remove_listing = 0;
1100 /* Set the "mirror" mode. It means: recursive download, timestamping,
1101 no limit on max. recursion depth, and don't remove listings. */
1104 cmd_spec_mirror (const char *com, const char *val, void *place_ignored)
1108 if (!cmd_boolean (com, val, &mirror))
1113 if (!opt.no_dirstruct)
1115 opt.timestamping = 1;
1116 opt.reclevel = INFINITE_RECURSION;
1117 opt.remove_listing = 0;
1122 /* Validate --prefer-family and set the choice. Allowed values are
1123 "IPv4", "IPv6", and "none". */
1126 cmd_spec_prefer_family (const char *com, const char *val, void *place_ignored)
1128 static const struct decode_item choices[] = {
1129 { "IPv4", prefer_ipv4 },
1130 { "IPv6", prefer_ipv6 },
1131 { "none", prefer_none },
1133 int ok = decode_string (val, choices, countof (choices),
1134 (int *) &opt.prefer_family);
1136 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1140 /* Set progress.type to VAL, but verify that it's a valid progress
1141 implementation before that. */
1144 cmd_spec_progress (const char *com, const char *val, void *place_ignored)
1146 if (!valid_progress_implementation_p (val))
1148 fprintf (stderr, _("%s: %s: Invalid progress type `%s'.\n"),
1149 exec_name, com, val);
1152 xfree_null (opt.progress_type);
1154 /* Don't call set_progress_implementation here. It will be called
1155 in main() when it becomes clear what the log output is. */
1156 opt.progress_type = xstrdup (val);
1160 /* Set opt.recursive to VAL as with cmd_boolean. If opt.recursive is
1161 set to true, also set opt.dirstruct to 1, unless opt.no_dirstruct
1165 cmd_spec_recursive (const char *com, const char *val, void *place_ignored)
1167 if (!cmd_boolean (com, val, &opt.recursive))
1171 if (opt.recursive && !opt.no_dirstruct)
1178 cmd_spec_restrict_file_names (const char *com, const char *val, void *place_ignored)
1180 int restrict_os = opt.restrict_files_os;
1181 int restrict_ctrl = opt.restrict_files_ctrl;
1183 const char *end = strchr (val, ',');
1185 end = val + strlen (val);
1187 #define VAL_IS(string_literal) BOUNDED_EQUAL (val, end, string_literal)
1189 if (VAL_IS ("unix"))
1190 restrict_os = restrict_unix;
1191 else if (VAL_IS ("windows"))
1192 restrict_os = restrict_windows;
1193 else if (VAL_IS ("nocontrol"))
1199 _("%s: %s: Invalid restriction `%s', use `unix' or `windows'.\n"),
1200 exec_name, com, val);
1208 if (!strcmp (end + 1, "nocontrol"))
1214 opt.restrict_files_os = restrict_os;
1215 opt.restrict_files_ctrl = restrict_ctrl;
1221 cmd_spec_secure_protocol (const char *com, const char *val, void *place)
1223 static const struct decode_item choices[] = {
1224 { "auto", secure_protocol_auto },
1225 { "sslv2", secure_protocol_sslv2 },
1226 { "sslv3", secure_protocol_sslv3 },
1227 { "tlsv1", secure_protocol_tlsv1 },
1229 int ok = decode_string (val, choices, countof (choices), place);
1231 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"), exec_name, com, val);
1236 /* Set all three timeout values. */
1239 cmd_spec_timeout (const char *com, const char *val, void *place_ignored)
1242 if (!cmd_time (com, val, &value))
1244 opt.read_timeout = value;
1245 opt.connect_timeout = value;
1246 opt.dns_timeout = value;
1251 cmd_spec_useragent (const char *com, const char *val, void *place_ignored)
1253 /* Just check for empty string and newline, so we don't throw total
1254 junk to the server. */
1255 if (!*val || strchr (val, '\n'))
1257 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"),
1258 exec_name, com, val);
1261 opt.useragent = xstrdup (val);
1265 /* Miscellaneous useful routines. */
1267 /* A very simple atoi clone, more useful than atoi because it works on
1268 delimited strings, and has error reportage. Returns 1 on success,
1269 0 on failure. If successful, stores result to *DEST. */
1272 simple_atoi (const char *beg, const char *end, int *dest)
1276 const char *p = beg;
1278 while (p < end && ISSPACE (*p))
1280 if (p < end && (*p == '-' || *p == '+'))
1282 negative = (*p == '-');
1288 /* Read negative numbers in a separate loop because the most
1289 negative integer cannot be represented as a positive number. */
1292 for (; p < end && ISDIGIT (*p); p++)
1294 int next = (10 * result) + (*p - '0');
1296 return 0; /* overflow */
1300 for (; p < end && ISDIGIT (*p); p++)
1302 int next = (10 * result) - (*p - '0');
1304 return 0; /* underflow */
1315 /* Trivial atof, with error reporting. Handles "<digits>[.<digits>]",
1316 doesn't handle exponential notation. Returns 1 on success, 0 on
1317 failure. In case of success, stores its result to *DEST. */
1320 simple_atof (const char *beg, const char *end, double *dest)
1329 const char *p = beg;
1331 while (p < end && ISSPACE (*p))
1333 if (p < end && (*p == '-' || *p == '+'))
1335 negative = (*p == '-');
1339 for (; p < end; p++)
1345 result = (10 * result) + (ch - '0');
1347 result += (ch - '0') / (divider *= 10);
1369 /* Verify that the user-specified header in S is valid. It must
1370 contain a colon preceded by non-white-space characters and must not
1371 contain newlines. */
1374 check_user_specified_header (const char *s)
1378 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1379 /* The header MUST contain `:' preceded by at least one
1380 non-whitespace character. */
1381 if (*p != ':' || p == s)
1383 /* The header MUST NOT contain newlines. */
1384 if (strchr (s, '\n'))
1389 /* Decode VAL into a number, according to ITEMS. */
1392 decode_string (const char *val, const struct decode_item *items, int itemcount,
1396 for (i = 0; i < itemcount; i++)
1397 if (0 == strcasecmp (val, items[i].name))
1399 *place = items[i].code;
1406 void cleanup_html_url PARAMS ((void));
1407 void http_cleanup PARAMS ((void));
1410 /* Free the memory allocated by global variables. */
1414 /* Free external resources, close files, etc. */
1417 extern FILE *output_stream;
1419 fclose (output_stream);
1420 /* No need to check for error because Wget flushes its output (and
1421 checks for errors) after any data arrives. */
1424 /* We're exiting anyway so there's no real need to call free()
1425 hundreds of times. Skipping the frees will make Wget exit
1428 However, when detecting leaks, it's crucial to free() everything
1429 because then you can find the real leaks, i.e. the allocated
1430 memory which grows with the size of the program. */
1436 cleanup_html_url ();
1441 extern acc_t *netrc_list;
1442 free_netrc (netrc_list);
1444 xfree_null (opt.lfilename);
1445 xfree_null (opt.dir_prefix);
1446 xfree_null (opt.input_filename);
1447 xfree_null (opt.output_document);
1448 free_vec (opt.accepts);
1449 free_vec (opt.rejects);
1450 free_vec (opt.excludes);
1451 free_vec (opt.includes);
1452 free_vec (opt.domains);
1453 free_vec (opt.follow_tags);
1454 free_vec (opt.ignore_tags);
1455 xfree_null (opt.progress_type);
1456 xfree (opt.ftp_acc);
1457 xfree_null (opt.ftp_user);
1458 xfree_null (opt.ftp_passwd);
1459 xfree_null (opt.ftp_proxy);
1460 xfree_null (opt.https_proxy);
1461 xfree_null (opt.http_proxy);
1462 free_vec (opt.no_proxy);
1463 xfree_null (opt.useragent);
1464 xfree_null (opt.referer);
1465 xfree_null (opt.http_user);
1466 xfree_null (opt.http_passwd);
1467 free_vec (opt.user_headers);
1469 xfree_null (opt.cert_file);
1470 xfree_null (opt.private_key);
1472 xfree_null (opt.bind_address);
1473 xfree_null (opt.cookies_input);
1474 xfree_null (opt.cookies_output);
1475 xfree_null (opt.user);
1476 xfree_null (opt.passwd);
1477 #endif /* DEBUG_MALLOC */