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 xfree_null (opt.useragent);
1262 opt.useragent = xstrdup (val);
1266 /* Miscellaneous useful routines. */
1268 /* A very simple atoi clone, more useful than atoi because it works on
1269 delimited strings, and has error reportage. Returns 1 on success,
1270 0 on failure. If successful, stores result to *DEST. */
1273 simple_atoi (const char *beg, const char *end, int *dest)
1277 const char *p = beg;
1279 while (p < end && ISSPACE (*p))
1281 if (p < end && (*p == '-' || *p == '+'))
1283 negative = (*p == '-');
1289 /* Read negative numbers in a separate loop because the most
1290 negative integer cannot be represented as a positive number. */
1293 for (; p < end && ISDIGIT (*p); p++)
1295 int next = (10 * result) + (*p - '0');
1297 return 0; /* overflow */
1301 for (; p < end && ISDIGIT (*p); p++)
1303 int next = (10 * result) - (*p - '0');
1305 return 0; /* underflow */
1316 /* Trivial atof, with error reporting. Handles "<digits>[.<digits>]",
1317 doesn't handle exponential notation. Returns 1 on success, 0 on
1318 failure. In case of success, stores its result to *DEST. */
1321 simple_atof (const char *beg, const char *end, double *dest)
1330 const char *p = beg;
1332 while (p < end && ISSPACE (*p))
1334 if (p < end && (*p == '-' || *p == '+'))
1336 negative = (*p == '-');
1340 for (; p < end; p++)
1346 result = (10 * result) + (ch - '0');
1348 result += (ch - '0') / (divider *= 10);
1370 /* Verify that the user-specified header in S is valid. It must
1371 contain a colon preceded by non-white-space characters and must not
1372 contain newlines. */
1375 check_user_specified_header (const char *s)
1379 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1380 /* The header MUST contain `:' preceded by at least one
1381 non-whitespace character. */
1382 if (*p != ':' || p == s)
1384 /* The header MUST NOT contain newlines. */
1385 if (strchr (s, '\n'))
1390 /* Decode VAL into a number, according to ITEMS. */
1393 decode_string (const char *val, const struct decode_item *items, int itemcount,
1397 for (i = 0; i < itemcount; i++)
1398 if (0 == strcasecmp (val, items[i].name))
1400 *place = items[i].code;
1407 void cleanup_html_url PARAMS ((void));
1408 void http_cleanup PARAMS ((void));
1411 /* Free the memory allocated by global variables. */
1415 /* Free external resources, close files, etc. */
1418 extern FILE *output_stream;
1420 fclose (output_stream);
1421 /* No need to check for error because Wget flushes its output (and
1422 checks for errors) after any data arrives. */
1425 /* We're exiting anyway so there's no real need to call free()
1426 hundreds of times. Skipping the frees will make Wget exit
1429 However, when detecting leaks, it's crucial to free() everything
1430 because then you can find the real leaks, i.e. the allocated
1431 memory which grows with the size of the program. */
1437 cleanup_html_url ();
1442 extern acc_t *netrc_list;
1443 free_netrc (netrc_list);
1445 xfree_null (opt.lfilename);
1446 xfree_null (opt.dir_prefix);
1447 xfree_null (opt.input_filename);
1448 xfree_null (opt.output_document);
1449 free_vec (opt.accepts);
1450 free_vec (opt.rejects);
1451 free_vec (opt.excludes);
1452 free_vec (opt.includes);
1453 free_vec (opt.domains);
1454 free_vec (opt.follow_tags);
1455 free_vec (opt.ignore_tags);
1456 xfree_null (opt.progress_type);
1457 xfree (opt.ftp_acc);
1458 xfree_null (opt.ftp_user);
1459 xfree_null (opt.ftp_passwd);
1460 xfree_null (opt.ftp_proxy);
1461 xfree_null (opt.https_proxy);
1462 xfree_null (opt.http_proxy);
1463 free_vec (opt.no_proxy);
1464 xfree_null (opt.useragent);
1465 xfree_null (opt.referer);
1466 xfree_null (opt.http_user);
1467 xfree_null (opt.http_passwd);
1468 free_vec (opt.user_headers);
1470 xfree_null (opt.cert_file);
1471 xfree_null (opt.private_key);
1473 xfree_null (opt.bind_address);
1474 xfree_null (opt.cookies_input);
1475 xfree_null (opt.cookies_output);
1476 xfree_null (opt.user);
1477 xfree_null (opt.passwd);
1478 #endif /* DEBUG_MALLOC */