1 /* Reading/parsing the initialization file.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2003
3 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables. You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL". If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so. If you do not wish to do
29 so, delete this exception statement from your version. */
34 #include <sys/types.h>
49 # include <sys/socket.h>
50 # include <netinet/in.h>
52 # include <arpa/inet.h>
66 #include "cookies.h" /* for cookie_jar_delete */
68 #include "recur.h" /* for INFINITE_RECURSION */
74 extern struct cookie_jar *wget_cookie_jar;
76 /* We want tilde expansion enabled only when reading `.wgetrc' lines;
77 otherwise, it will be performed by the shell. This variable will
78 be set by the wgetrc-reading function. */
80 static int enable_tilde_expansion;
83 #define CMD_DECLARE(func) static int func \
84 PARAMS ((const char *, const char *, void *))
86 CMD_DECLARE (cmd_boolean);
87 CMD_DECLARE (cmd_bytes);
88 CMD_DECLARE (cmd_bytes_large);
89 CMD_DECLARE (cmd_directory_vector);
90 CMD_DECLARE (cmd_lockable_boolean);
91 CMD_DECLARE (cmd_number);
92 CMD_DECLARE (cmd_number_inf);
93 CMD_DECLARE (cmd_string);
94 CMD_DECLARE (cmd_file);
95 CMD_DECLARE (cmd_directory);
96 CMD_DECLARE (cmd_time);
97 CMD_DECLARE (cmd_vector);
99 CMD_DECLARE (cmd_spec_dirstruct);
100 CMD_DECLARE (cmd_spec_header);
101 CMD_DECLARE (cmd_spec_htmlify);
102 CMD_DECLARE (cmd_spec_mirror);
103 CMD_DECLARE (cmd_spec_progress);
104 CMD_DECLARE (cmd_spec_recursive);
105 CMD_DECLARE (cmd_spec_restrict_file_names);
106 CMD_DECLARE (cmd_spec_timeout);
107 CMD_DECLARE (cmd_spec_useragent);
109 /* List of recognized commands, each consisting of name, closure and
110 function. When adding a new command, simply add it to the list,
111 but be sure to keep the list sorted alphabetically, as
112 command_by_name depends on it. Also, be sure to add any entries
113 that allocate memory (e.g. cmd_string and cmd_vector guys) to the
114 cleanup() function below. */
119 int (*action) PARAMS ((const char *, const char *, void *));
121 { "accept", &opt.accepts, cmd_vector },
122 { "addhostdir", &opt.add_hostdir, cmd_boolean },
123 { "alwaysrest", &opt.always_rest, cmd_boolean }, /* deprecated */
124 { "background", &opt.background, cmd_boolean },
125 { "backupconverted", &opt.backup_converted, cmd_boolean },
126 { "backups", &opt.backups, cmd_number },
127 { "base", &opt.base_href, cmd_string },
128 { "bindaddress", &opt.bind_address, cmd_string },
129 { "cache", &opt.allow_cache, cmd_boolean },
130 { "connecttimeout", &opt.connect_timeout, cmd_time },
131 { "continue", &opt.always_rest, cmd_boolean },
132 { "convertlinks", &opt.convert_links, cmd_boolean },
133 { "cookies", &opt.cookies, cmd_boolean },
134 { "cutdirs", &opt.cut_dirs, cmd_number },
136 { "debug", &opt.debug, cmd_boolean },
138 { "deleteafter", &opt.delete_after, cmd_boolean },
139 { "dirprefix", &opt.dir_prefix, cmd_directory },
140 { "dirstruct", NULL, cmd_spec_dirstruct },
141 { "dnscache", &opt.dns_cache, cmd_boolean },
142 { "dnstimeout", &opt.dns_timeout, cmd_time },
143 { "domains", &opt.domains, cmd_vector },
144 { "dotbytes", &opt.dot_bytes, cmd_bytes },
145 { "dotsinline", &opt.dots_in_line, cmd_number },
146 { "dotspacing", &opt.dot_spacing, cmd_number },
147 { "dotstyle", &opt.dot_style, cmd_string },
149 { "egdfile", &opt.sslegdsock, cmd_file },
151 { "excludedirectories", &opt.excludes, cmd_directory_vector },
152 { "excludedomains", &opt.exclude_domains, cmd_vector },
153 { "followftp", &opt.follow_ftp, cmd_boolean },
154 { "followtags", &opt.follow_tags, cmd_vector },
155 { "forcehtml", &opt.force_html, cmd_boolean },
156 { "ftpproxy", &opt.ftp_proxy, cmd_string },
157 { "glob", &opt.ftp_glob, cmd_boolean },
158 { "header", NULL, cmd_spec_header },
159 { "htmlextension", &opt.html_extension, cmd_boolean },
160 { "htmlify", NULL, cmd_spec_htmlify },
161 { "httpkeepalive", &opt.http_keep_alive, cmd_boolean },
162 { "httppasswd", &opt.http_passwd, cmd_string },
163 { "httpproxy", &opt.http_proxy, cmd_string },
164 { "httpsproxy", &opt.https_proxy, cmd_string },
165 { "httpuser", &opt.http_user, cmd_string },
166 { "ignorelength", &opt.ignore_length, cmd_boolean },
167 { "ignoretags", &opt.ignore_tags, cmd_vector },
168 { "includedirectories", &opt.includes, cmd_directory_vector },
170 { "inet4only", &opt.ipv4_only, cmd_boolean },
171 { "inet6only", &opt.ipv6_only, cmd_boolean },
173 { "input", &opt.input_filename, cmd_file },
174 { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
175 { "killlonger", &opt.kill_longer, cmd_boolean },
176 { "limitrate", &opt.limit_rate, cmd_bytes },
177 { "loadcookies", &opt.cookies_input, cmd_file },
178 { "logfile", &opt.lfilename, cmd_file },
179 { "login", &opt.ftp_acc, cmd_string },
180 { "mirror", NULL, cmd_spec_mirror },
181 { "netrc", &opt.netrc, cmd_boolean },
182 { "noclobber", &opt.noclobber, cmd_boolean },
183 { "noparent", &opt.no_parent, cmd_boolean },
184 { "noproxy", &opt.no_proxy, cmd_vector },
185 { "numtries", &opt.ntry, cmd_number_inf },/* deprecated*/
186 { "outputdocument", &opt.output_document, cmd_file },
187 { "pagerequisites", &opt.page_requisites, cmd_boolean },
188 { "passiveftp", &opt.ftp_pasv, cmd_lockable_boolean },
189 { "passwd", &opt.ftp_pass, cmd_string },
190 { "postdata", &opt.post_data, cmd_string },
191 { "postfile", &opt.post_file_name, cmd_file },
192 { "preservepermissions", &opt.preserve_perm, cmd_boolean },
193 { "progress", &opt.progress_type, cmd_spec_progress },
194 { "proxypasswd", &opt.proxy_passwd, cmd_string },
195 { "proxyuser", &opt.proxy_user, cmd_string },
196 { "quiet", &opt.quiet, cmd_boolean },
197 { "quota", &opt.quota, cmd_bytes_large },
198 { "randomwait", &opt.random_wait, cmd_boolean },
199 { "readtimeout", &opt.read_timeout, cmd_time },
200 { "reclevel", &opt.reclevel, cmd_number_inf },
201 { "recursive", NULL, cmd_spec_recursive },
202 { "referer", &opt.referer, cmd_string },
203 { "reject", &opt.rejects, cmd_vector },
204 { "relativeonly", &opt.relative_only, cmd_boolean },
205 { "removelisting", &opt.remove_listing, cmd_boolean },
206 { "restrictfilenames", NULL, cmd_spec_restrict_file_names },
207 { "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
208 { "retryconnrefused", &opt.retry_connrefused, cmd_boolean },
209 { "robots", &opt.use_robots, cmd_boolean },
210 { "savecookies", &opt.cookies_output, cmd_file },
211 { "saveheaders", &opt.save_headers, cmd_boolean },
212 { "serverresponse", &opt.server_response, cmd_boolean },
213 { "spanhosts", &opt.spanhost, cmd_boolean },
214 { "spider", &opt.spider, cmd_boolean },
216 { "sslcadir", &opt.sslcadir, cmd_directory },
217 { "sslcafile", &opt.sslcafile, cmd_file },
218 { "sslcertfile", &opt.sslcertfile, cmd_file },
219 { "sslcertkey", &opt.sslcertkey, cmd_file },
220 { "sslcerttype", &opt.sslcerttype, cmd_number },
221 { "sslcheckcert", &opt.sslcheckcert, cmd_number },
222 { "sslprotocol", &opt.sslprotocol, cmd_number },
223 #endif /* HAVE_SSL */
224 { "strictcomments", &opt.strict_comments, cmd_boolean },
225 { "timeout", NULL, cmd_spec_timeout },
226 { "timestamping", &opt.timestamping, cmd_boolean },
227 { "tries", &opt.ntry, cmd_number_inf },
228 { "useproxy", &opt.use_proxy, cmd_boolean },
229 { "useragent", NULL, cmd_spec_useragent },
230 { "verbose", &opt.verbose, cmd_boolean },
231 { "wait", &opt.wait, cmd_time },
232 { "waitretry", &opt.waitretry, cmd_time }
235 /* Look up CMDNAME in the commands[] and return its position in the
236 array. If CMDNAME is not found, return -1. */
239 command_by_name (const char *cmdname)
241 /* Use binary search for speed. Wget has ~100 commands, which
242 guarantees a worst case performance of 7 string comparisons. */
243 int lo = 0, hi = countof (commands) - 1;
247 int mid = (lo + hi) >> 1;
248 int cmp = strcasecmp (cmdname, commands[mid].name);
259 /* Reset the variables to default values. */
265 /* Most of the default values are 0. Just reset everything, and
266 fill in the non-zero values. Note that initializing pointers to
267 NULL this way is technically illegal, but porting Wget to a
268 machine where NULL is not all-zero bit pattern will be the least
269 of the implementors' worries. */
277 opt.ftp_acc = xstrdup ("anonymous");
278 opt.ftp_pass = xstrdup ("-wget@");
282 opt.http_keep_alive = 1;
284 tmp = getenv ("no_proxy");
286 opt.no_proxy = sepstring (tmp);
289 opt.read_timeout = 900;
292 opt.remove_listing = 1;
294 opt.dot_bytes = 1024;
295 opt.dot_spacing = 10;
296 opt.dots_in_line = 50;
300 /* The default for file name restriction defaults to the OS type. */
301 #if !defined(WINDOWS) && !defined(__CYGWIN__)
302 opt.restrict_files_os = restrict_unix;
304 opt.restrict_files_os = restrict_windows;
306 opt.restrict_files_ctrl = 1;
309 # ifndef HAVE_GETADDRINFO_AI_ADDRCONFIG
310 /* If IPv6 is enabled, but AI_ADDRCONFIG is missing, check whether
311 we can create AF_INET6 sockets. If we can't, turn on the
312 --inet4-only setting. This is necessary because on some systems
313 (e.g. RHL 9) getaddrinfo resolves AAAA records, but socket()
314 can't even create an AF_INET6 socket, let alone connect to IPv6
315 hosts. To avoid "address family not supported" error messages,
318 We do it as early as here, so that the user can revert the
319 settingn using --no-inet4-only, in case he wants to see the error
320 messages, for whatever reason. */
322 int sock = socket (AF_INET6, SOCK_STREAM, 0);
328 # endif /* not HAVE_GETADDRINFO_AI_ADDRCONFIG */
329 #endif /* ENABLE_IPV6 */
332 /* Return the user's home directory (strdup-ed), or NULL if none is
337 char *home = getenv ("HOME");
342 /* If HOME is not defined, try getting it from the password
344 struct passwd *pwd = getpwuid (getuid ());
345 if (!pwd || !pwd->pw_dir)
350 /* #### Maybe I should grab home_dir from registry, but the best
351 that I could get from there is user's Start menu. It sucks! */
355 return home ? xstrdup (home) : NULL;
358 /* Return the path to the user's .wgetrc. This is either the value of
359 `WGETRC' environment variable, or `$HOME/.wgetrc'.
361 If the `WGETRC' variable exists but the file does not exist, the
362 function will exit(). */
364 wgetrc_file_name (void)
369 /* Try the environment. */
370 env = getenv ("WGETRC");
373 if (!file_exists_p (env))
375 fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"),
379 return xstrdup (env);
383 /* If that failed, try $HOME/.wgetrc. */
387 file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
388 sprintf (file, "%s/.wgetrc", home);
392 /* Under Windows, "home" is (for the purposes of this function) the
393 directory where `wget.exe' resides, and `wget.ini' will be used
394 as file name. SYSTEM_WGETRC should not be defined under WINDOWS.
396 It is not as trivial as I assumed, because on 95 argv[0] is full
397 path, but on NT you get what you typed in command line. --dbudor */
401 file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
402 sprintf (file, "%swget.ini", home);
408 if (!file_exists_p (file))
416 static int parse_line PARAMS ((const char *, char **, char **, int *));
417 static int setval_internal PARAMS ((int, const char *, const char *));
419 /* Initialize variables from a wgetrc file. */
422 run_wgetrc (const char *file)
428 fp = fopen (file, "rb");
431 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
432 file, strerror (errno));
435 enable_tilde_expansion = 1;
437 while ((line = read_whole_line (fp)))
442 /* Parse the line. */
443 status = parse_line (line, &com, &val, &comind);
445 /* If everything is OK, set the value. */
448 if (!setval_internal (comind, com, val))
449 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
454 else if (status == 0)
455 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
459 enable_tilde_expansion = 0;
463 /* Initialize the defaults and run the system wgetrc and user's own
470 /* Load the hard-coded defaults. */
473 /* If SYSTEM_WGETRC is defined, use it. */
475 if (file_exists_p (SYSTEM_WGETRC))
476 run_wgetrc (SYSTEM_WGETRC);
478 /* Override it with your own, if one exists. */
479 file = wgetrc_file_name ();
482 /* #### We should canonicalize `file' and SYSTEM_WGETRC with
483 something like realpath() before comparing them with `strcmp' */
485 if (!strcmp (file, SYSTEM_WGETRC))
487 fprintf (stderr, _("\
488 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
498 /* Remove dashes and underscores from S, modifying S in the
504 char *t = s; /* t - tortoise */
505 char *h = s; /* h - hare */
507 if (*h == '_' || *h == '-')
514 /* Parse the line pointed by line, with the syntax:
515 <sp>* command <sp>* = <sp>* value <sp>*
516 Uses malloc to allocate space for command and value.
517 If the line is invalid, data is freed and 0 is returned.
524 In case of success, *COM and *VAL point to freshly allocated
525 strings, and *COMIND points to com's index. In case of error or
526 empty line, those values are unaffected. */
529 parse_line (const char *line, char **com, char **val, int *comind)
532 const char *end = line + strlen (line);
533 const char *cmdstart, *cmdend;
534 const char *valstart, *valend;
539 /* Skip leading and trailing whitespace. */
540 while (*line && ISSPACE (*line))
542 while (end > line && ISSPACE (end[-1]))
545 /* Skip empty lines and comments. */
546 if (!*line || *line == '#')
552 while (p < end && (ISALPHA (*p) || *p == '_' || *p == '-'))
556 /* Skip '=', as well as any space before or after it. */
557 while (p < end && ISSPACE (*p))
559 if (p == end || *p != '=')
562 while (p < end && ISSPACE (*p))
568 /* The line now known to be syntactically correct. Check whether
569 the command is valid. */
570 BOUNDED_TO_ALLOCA (cmdstart, cmdend, cmdcopy);
572 ind = command_by_name (cmdcopy);
576 /* The command is valid. Now fill in the values and report success
579 *com = strdupdelim (cmdstart, cmdend);
580 *val = strdupdelim (valstart, valend);
584 /* Run commands[comind].action. */
587 setval_internal (int comind, const char *com, const char *val)
589 assert (0 <= comind && comind < countof (commands));
590 DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
591 return ((*commands[comind].action) (com, val, commands[comind].closure));
594 /* Run command COM with value VAL. If running the command produces an
595 error, report the error and exit.
597 This is intended to be called from main() to modify Wget's behavior
598 through command-line switches. Since COM is hard-coded in main(),
599 it is not canonicalized, and this aborts when COM is not found.
601 If COMIND's are exported to init.h, this function will be changed
602 to accept COMIND directly. */
605 setoptval (const char *com, const char *val)
607 assert (val != NULL);
608 if (!setval_internal (command_by_name (com), com, val))
612 /* Parse OPT into command and value and run it. For example,
613 run_command("foo=bar") is equivalent to setoptval("foo", "bar").
614 This is used by the `--execute' flag in main.c. */
617 run_command (const char *opt)
621 int status = parse_line (opt, &com, &val, &comind);
624 if (!setval_internal (comind, com, val))
629 else if (status == 0)
631 fprintf (stderr, _("%s: Invalid --execute command `%s'\n"),
637 /* Generic helper functions, for use with `commands'. */
639 #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0')
641 #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0) \
642 && TOLOWER((p)[1]) == (c1) \
645 #define CMP3(p, c0, c1, c2) (TOLOWER((p)[0]) == (c0) \
646 && TOLOWER((p)[1]) == (c1) \
647 && TOLOWER((p)[2]) == (c2) \
651 /* Store the boolean value from VAL to CLOSURE. COM is ignored,
652 except for error messages. */
654 cmd_boolean (const char *com, const char *val, void *closure)
658 if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
659 /* "on", "yes" and "1" mean true. */
661 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
662 /* "off", "no" and "0" mean false. */
667 _("%s: %s: Invalid boolean `%s', use `on' or `off'.\n"),
668 exec_name, com, val);
672 *(int *)closure = bool_value;
676 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to CLOSURE.
677 COM is ignored, except for error messages. Values 2 and -1
678 indicate that once defined, the value may not be changed by
679 successive wgetrc files or command-line arguments.
681 Values: 2 - Enable a particular option for good ("always")
682 1 - Enable an option ("on")
683 0 - Disable an option ("off")
684 -1 - Disable an option for good ("never") */
686 cmd_lockable_boolean (const char *com, const char *val, void *closure)
688 int lockable_boolean_value;
690 int oldval = *(int *)closure;
693 * If a config file said "always" or "never", don't allow command line
694 * arguments to override the config file.
696 if (oldval == -1 || oldval == 2)
699 if (0 == strcasecmp (val, "always") || CMP1 (val, '2'))
700 lockable_boolean_value = 2;
701 else if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
702 lockable_boolean_value = 1;
703 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
704 lockable_boolean_value = 0;
705 else if (0 == strcasecmp (val, "never") || CMP2 (val, '-', '1'))
706 lockable_boolean_value = -1;
710 _("%s: %s: Invalid boolean `%s', use always, on, off, or never.\n"),
711 exec_name, com, val);
715 *(int *)closure = lockable_boolean_value;
719 static int simple_atoi PARAMS ((const char *, const char *, int *));
721 /* Set the non-negative integer value from VAL to CLOSURE. With
722 incorrect specification, the number remains unchanged. */
724 cmd_number (const char *com, const char *val, void *closure)
726 if (!simple_atoi (val, val + strlen (val), closure))
728 fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
729 exec_name, com, val);
735 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
737 cmd_number_inf (const char *com, const char *val, void *closure)
739 if (!strcasecmp (val, "inf"))
744 return cmd_number (com, val, closure);
747 /* Copy (strdup) the string at COM to a new location and place a
748 pointer to *CLOSURE. */
750 cmd_string (const char *com, const char *val, void *closure)
752 char **pstring = (char **)closure;
754 xfree_null (*pstring);
755 *pstring = xstrdup (val);
760 # define ISSEP(c) ((c) == '/')
762 # define ISSEP(c) ((c) == '/' || (c) == '\\')
765 /* Like the above, but handles tilde-expansion when reading a user's
766 `.wgetrc'. In that case, and if VAL begins with `~', the tilde
767 gets expanded to the user's home directory. */
769 cmd_file (const char *com, const char *val, void *closure)
771 char **pstring = (char **)closure;
773 xfree_null (*pstring);
775 /* #### If VAL is empty, perhaps should set *CLOSURE to NULL. */
777 if (!enable_tilde_expansion || !(*val == '~' && ISSEP (val[1])))
780 *pstring = xstrdup (val);
786 char *home = home_dir ();
790 homelen = strlen (home);
791 while (homelen && ISSEP (home[homelen - 1]))
792 home[--homelen] = '\0';
794 /* Skip the leading "~/". */
795 for (++val; ISSEP (*val); val++)
798 result = xmalloc (homelen + 1 + strlen (val) + 1);
799 memcpy (result, home, homelen);
800 result[homelen] = '/';
801 strcpy (result + homelen + 1, val);
807 /* Convert "\" to "/". */
810 for (s = *pstring; *s; s++)
818 /* Like cmd_file, but strips trailing '/' characters. */
820 cmd_directory (const char *com, const char *val, void *closure)
824 /* Call cmd_file() for tilde expansion and separator
825 canonicalization (backslash -> slash under Windows). These
826 things should perhaps be in a separate function. */
827 if (!cmd_file (com, val, closure))
830 s = *(char **)closure;
832 while (t > s && *--t == '/')
838 /* Split VAL by space to a vector of values, and append those values
839 to vector pointed to by the CLOSURE argument. If VAL is empty, the
840 CLOSURE vector is cleared instead. */
843 cmd_vector (const char *com, const char *val, void *closure)
845 char ***pvec = (char ***)closure;
848 *pvec = merge_vecs (*pvec, sepstring (val));
858 cmd_directory_vector (const char *com, const char *val, void *closure)
860 char ***pvec = (char ***)closure;
864 /* Strip the trailing slashes from directories. */
867 seps = sepstring (val);
868 for (t = seps; t && *t; t++)
870 int len = strlen (*t);
871 /* Skip degenerate case of root directory. */
874 if ((*t)[len - 1] == '/')
875 (*t)[len - 1] = '\0';
878 *pvec = merge_vecs (*pvec, seps);
888 static int simple_atof PARAMS ((const char *, const char *, double *));
890 /* Enginge for cmd_bytes and cmd_bytes_large: converts a string such
891 as "100k" or "2.5G" to a floating point number. */
894 parse_bytes_helper (const char *val, double *result)
897 const char *end = val + strlen (val);
899 /* Check for "inf". */
900 if (0 == strcmp (val, "inf"))
906 /* Strip trailing whitespace. */
907 while (val < end && ISSPACE (end[-1]))
912 switch (TOLOWER (end[-1]))
915 --end, mult = 1024.0;
918 --end, mult = 1048576.0;
921 --end, mult = 1073741824.0;
924 --end, mult = 1099511627776.0;
927 /* Not a recognized suffix: assume it's a digit. (If not,
928 simple_atof will raise an error.) */
932 /* Skip leading and trailing whitespace. */
933 while (val < end && ISSPACE (*val))
935 while (val < end && ISSPACE (end[-1]))
940 if (!simple_atof (val, end, &number))
943 *result = number * mult;
947 /* Parse VAL as a number and set its value to CLOSURE (which should
948 point to a long int).
950 By default, the value is assumed to be in bytes. If "K", "M", or
951 "G" are appended, the value is multiplied with 1<<10, 1<<20, or
952 1<<30, respectively. Floating point values are allowed and are
953 cast to integer before use. The idea is to be able to use things
954 like 1.5k instead of "1536".
956 The string "inf" is returned as 0.
958 In case of error, 0 is returned and memory pointed to by CLOSURE
959 remains unmodified. */
962 cmd_bytes (const char *com, const char *val, void *closure)
965 if (!parse_bytes_helper (val, &byte_value))
967 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
968 exec_name, com, val);
971 *(long *)closure = (long)byte_value;
975 /* Like cmd_bytes, but CLOSURE is interpreted as a pointer to
976 LARGE_INT. It works by converting the string to double, therefore
977 working with values up to 2^53-1 without loss of precision. This
978 value (8192 TB) is large enough to serve for a while. */
981 cmd_bytes_large (const char *com, const char *val, void *closure)
984 if (!parse_bytes_helper (val, &byte_value))
986 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
987 exec_name, com, val);
990 *(LARGE_INT *)closure = (LARGE_INT)byte_value;
994 /* Store the value of VAL to *OUT. The value is a time period, by
995 default expressed in seconds, but also accepting suffixes "m", "h",
996 "d", and "w" for minutes, hours, days, and weeks respectively. */
999 cmd_time (const char *com, const char *val, void *closure)
1001 double number, mult;
1002 const char *end = val + strlen (val);
1004 /* Strip trailing whitespace. */
1005 while (val < end && ISSPACE (end[-1]))
1011 fprintf (stderr, _("%s: %s: Invalid time period `%s'\n"),
1012 exec_name, com, val);
1016 switch (TOLOWER (end[-1]))
1019 --end, mult = 1; /* seconds */
1022 --end, mult = 60; /* minutes */
1025 --end, mult = 3600; /* hours */
1028 --end, mult = 86400.0; /* days */
1031 --end, mult = 604800.0; /* weeks */
1034 /* Not a recognized suffix: assume it belongs to the number.
1035 (If not, atof simple_atof will raise an error.) */
1039 /* Skip leading and trailing whitespace. */
1040 while (val < end && ISSPACE (*val))
1042 while (val < end && ISSPACE (end[-1]))
1047 if (!simple_atof (val, end, &number))
1050 *(double *)closure = number * mult;
1054 /* Specialized helper functions, used by `commands' to handle some
1055 options specially. */
1057 static int check_user_specified_header PARAMS ((const char *));
1060 cmd_spec_dirstruct (const char *com, const char *val, void *closure)
1062 if (!cmd_boolean (com, val, &opt.dirstruct))
1064 /* Since dirstruct behaviour is explicitly changed, no_dirstruct
1065 must be affected inversely. */
1067 opt.no_dirstruct = 0;
1069 opt.no_dirstruct = 1;
1074 cmd_spec_header (const char *com, const char *val, void *closure)
1078 /* Empty header means reset headers. */
1079 xfree_null (opt.user_header);
1080 opt.user_header = NULL;
1086 if (!check_user_specified_header (val))
1088 fprintf (stderr, _("%s: %s: Invalid header `%s'.\n"),
1089 exec_name, com, val);
1092 i = opt.user_header ? strlen (opt.user_header) : 0;
1093 opt.user_header = (char *)xrealloc (opt.user_header, i + strlen (val)
1095 strcpy (opt.user_header + i, val);
1097 opt.user_header[i++] = '\r';
1098 opt.user_header[i++] = '\n';
1099 opt.user_header[i] = '\0';
1105 cmd_spec_htmlify (const char *com, const char *val, void *closure)
1107 int flag = cmd_boolean (com, val, &opt.htmlify);
1108 if (flag && !opt.htmlify)
1109 opt.remove_listing = 0;
1113 /* Set the "mirror" mode. It means: recursive download, timestamping,
1114 no limit on max. recursion depth, and don't remove listings. */
1117 cmd_spec_mirror (const char *com, const char *val, void *closure)
1121 if (!cmd_boolean (com, val, &mirror))
1126 if (!opt.no_dirstruct)
1128 opt.timestamping = 1;
1129 opt.reclevel = INFINITE_RECURSION;
1130 opt.remove_listing = 0;
1135 /* Set progress.type to VAL, but verify that it's a valid progress
1136 implementation before that. */
1139 cmd_spec_progress (const char *com, const char *val, void *closure)
1141 if (!valid_progress_implementation_p (val))
1143 fprintf (stderr, _("%s: %s: Invalid progress type `%s'.\n"),
1144 exec_name, com, val);
1147 xfree_null (opt.progress_type);
1149 /* Don't call set_progress_implementation here. It will be called
1150 in main() when it becomes clear what the log output is. */
1151 opt.progress_type = xstrdup (val);
1155 /* Set opt.recursive to VAL as with cmd_boolean. If opt.recursive is
1156 set to true, also set opt.dirstruct to 1, unless opt.no_dirstruct
1160 cmd_spec_recursive (const char *com, const char *val, void *closure)
1162 if (!cmd_boolean (com, val, &opt.recursive))
1166 if (opt.recursive && !opt.no_dirstruct)
1173 cmd_spec_restrict_file_names (const char *com, const char *val, void *closure)
1175 int restrict_os = opt.restrict_files_os;
1176 int restrict_ctrl = opt.restrict_files_ctrl;
1178 const char *end = strchr (val, ',');
1180 end = val + strlen (val);
1182 #define VAL_IS(string_literal) BOUNDED_EQUAL (val, end, string_literal)
1184 if (VAL_IS ("unix"))
1185 restrict_os = restrict_unix;
1186 else if (VAL_IS ("windows"))
1187 restrict_os = restrict_windows;
1188 else if (VAL_IS ("nocontrol"))
1194 _("%s: %s: Invalid restriction `%s', use `unix' or `windows'.\n"),
1195 exec_name, com, val);
1203 if (!strcmp (end + 1, "nocontrol"))
1209 opt.restrict_files_os = restrict_os;
1210 opt.restrict_files_ctrl = restrict_ctrl;
1214 /* Set all three timeout values. */
1217 cmd_spec_timeout (const char *com, const char *val, void *closure)
1220 if (!cmd_time (com, val, &value))
1222 opt.read_timeout = value;
1223 opt.connect_timeout = value;
1224 opt.dns_timeout = value;
1229 cmd_spec_useragent (const char *com, const char *val, void *closure)
1231 /* Just check for empty string and newline, so we don't throw total
1232 junk to the server. */
1233 if (!*val || strchr (val, '\n'))
1235 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"),
1236 exec_name, com, val);
1239 opt.useragent = xstrdup (val);
1243 /* Miscellaneous useful routines. */
1245 /* A very simple atoi clone, more portable than strtol and friends,
1246 but reports errors, unlike atoi. Returns 1 on success, 0 on
1247 failure. In case of success, stores result to *DEST. */
1250 simple_atoi (const char *beg, const char *end, int *dest)
1258 for (p = beg; p < end && ISDIGIT (*p); p++)
1259 result = (10 * result) + (*p - '0');
1268 /* Trivial atof, with error reporting. Handles "<digits>[.<digits>]",
1269 doesn't handle exponential notation. Returns 1 on success, 0 on
1270 failure. In case of success, stores its result to *DEST. */
1273 simple_atof (const char *beg, const char *end, double *dest)
1283 for (p = beg; p < end; p++)
1289 result = (10 * result) + (ch - '0');
1291 result += (ch - '0') / (divider *= 10);
1312 check_user_specified_header (const char *s)
1316 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1317 /* The header MUST contain `:' preceded by at least one
1318 non-whitespace character. */
1319 if (*p != ':' || p == s)
1321 /* The header MUST NOT contain newlines. */
1322 if (strchr (s, '\n'))
1327 void cleanup_html_url PARAMS ((void));
1328 void res_cleanup PARAMS ((void));
1329 void downloaded_files_free PARAMS ((void));
1330 void http_cleanup PARAMS ((void));
1333 /* Free the memory allocated by global variables. */
1337 /* Free external resources, close files, etc. */
1342 /* We're exiting anyway so there's no real need to call free()
1343 hundreds of times. Skipping the frees will make Wget exit
1346 However, when detecting leaks, it's crucial to free() everything
1347 because then you can find the real leaks, i.e. the allocated
1348 memory which grows with the size of the program. */
1354 cleanup_html_url ();
1355 downloaded_files_free ();
1357 if (wget_cookie_jar)
1358 cookie_jar_delete (wget_cookie_jar);
1361 extern acc_t *netrc_list;
1362 free_netrc (netrc_list);
1364 xfree_null (opt.lfilename);
1365 xfree_null (opt.dir_prefix);
1366 xfree_null (opt.input_filename);
1367 xfree_null (opt.output_document);
1368 free_vec (opt.accepts);
1369 free_vec (opt.rejects);
1370 free_vec (opt.excludes);
1371 free_vec (opt.includes);
1372 free_vec (opt.domains);
1373 free_vec (opt.follow_tags);
1374 free_vec (opt.ignore_tags);
1375 xfree_null (opt.progress_type);
1376 xfree (opt.ftp_acc);
1377 xfree_null (opt.ftp_pass);
1378 xfree_null (opt.ftp_proxy);
1379 xfree_null (opt.https_proxy);
1380 xfree_null (opt.http_proxy);
1381 free_vec (opt.no_proxy);
1382 xfree_null (opt.useragent);
1383 xfree_null (opt.referer);
1384 xfree_null (opt.http_user);
1385 xfree_null (opt.http_passwd);
1386 xfree_null (opt.user_header);
1388 xfree_null (opt.sslcertkey);
1389 xfree_null (opt.sslcertfile);
1390 #endif /* HAVE_SSL */
1391 xfree_null (opt.bind_address);
1392 xfree_null (opt.cookies_input);
1393 xfree_null (opt.cookies_output);