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 },
169 { "input", &opt.input_filename, cmd_file },
171 { "inet4only", &opt.ipv4_only, cmd_boolean },
172 { "inet6only", &opt.ipv6_only, cmd_boolean },
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 /* Return the user's home directory (strdup-ed), or NULL if none is
314 char *home = getenv ("HOME");
319 /* If HOME is not defined, try getting it from the password
321 struct passwd *pwd = getpwuid (getuid ());
322 if (!pwd || !pwd->pw_dir)
327 /* #### Maybe I should grab home_dir from registry, but the best
328 that I could get from there is user's Start menu. It sucks! */
332 return home ? xstrdup (home) : NULL;
335 /* Return the path to the user's .wgetrc. This is either the value of
336 `WGETRC' environment variable, or `$HOME/.wgetrc'.
338 If the `WGETRC' variable exists but the file does not exist, the
339 function will exit(). */
341 wgetrc_file_name (void)
346 /* Try the environment. */
347 env = getenv ("WGETRC");
350 if (!file_exists_p (env))
352 fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"),
356 return xstrdup (env);
360 /* If that failed, try $HOME/.wgetrc. */
364 file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
365 sprintf (file, "%s/.wgetrc", home);
369 /* Under Windows, "home" is (for the purposes of this function) the
370 directory where `wget.exe' resides, and `wget.ini' will be used
371 as file name. SYSTEM_WGETRC should not be defined under WINDOWS.
373 It is not as trivial as I assumed, because on 95 argv[0] is full
374 path, but on NT you get what you typed in command line. --dbudor */
378 file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
379 sprintf (file, "%swget.ini", home);
385 if (!file_exists_p (file))
393 static int parse_line PARAMS ((const char *, char **, char **, int *));
394 static int setval_internal PARAMS ((int, const char *, const char *));
396 /* Initialize variables from a wgetrc file. */
399 run_wgetrc (const char *file)
405 fp = fopen (file, "rb");
408 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
409 file, strerror (errno));
412 enable_tilde_expansion = 1;
414 while ((line = read_whole_line (fp)))
419 /* Parse the line. */
420 status = parse_line (line, &com, &val, &comind);
422 /* If everything is OK, set the value. */
425 if (!setval_internal (comind, com, val))
426 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
431 else if (status == 0)
432 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
436 enable_tilde_expansion = 0;
440 /* Initialize the defaults and run the system wgetrc and user's own
447 /* Load the hard-coded defaults. */
450 /* If SYSTEM_WGETRC is defined, use it. */
452 if (file_exists_p (SYSTEM_WGETRC))
453 run_wgetrc (SYSTEM_WGETRC);
455 /* Override it with your own, if one exists. */
456 file = wgetrc_file_name ();
459 /* #### We should canonicalize `file' and SYSTEM_WGETRC with
460 something like realpath() before comparing them with `strcmp' */
462 if (!strcmp (file, SYSTEM_WGETRC))
464 fprintf (stderr, _("\
465 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
475 /* Remove dashes and underscores from S, modifying S in the
481 char *t = s; /* t - tortoise */
482 char *h = s; /* h - hare */
484 if (*h == '_' || *h == '-')
491 /* Parse the line pointed by line, with the syntax:
492 <sp>* command <sp>* = <sp>* value <sp>*
493 Uses malloc to allocate space for command and value.
494 If the line is invalid, data is freed and 0 is returned.
501 In case of success, *COM and *VAL point to freshly allocated
502 strings, and *COMIND points to com's index. In case of error or
503 empty line, those values are unaffected. */
506 parse_line (const char *line, char **com, char **val, int *comind)
509 const char *end = line + strlen (line);
510 const char *cmdstart, *cmdend;
511 const char *valstart, *valend;
516 /* Skip leading and trailing whitespace. */
517 while (*line && ISSPACE (*line))
519 while (end > line && ISSPACE (end[-1]))
522 /* Skip empty lines and comments. */
523 if (!*line || *line == '#')
529 while (p < end && (ISALPHA (*p) || *p == '_' || *p == '-'))
533 /* Skip '=', as well as any space before or after it. */
534 while (p < end && ISSPACE (*p))
536 if (p == end || *p != '=')
539 while (p < end && ISSPACE (*p))
545 /* The line now known to be syntactically correct. Check whether
546 the command is valid. */
547 BOUNDED_TO_ALLOCA (cmdstart, cmdend, cmdcopy);
549 ind = command_by_name (cmdcopy);
553 /* The command is valid. Now fill in the values and report success
556 *com = strdupdelim (cmdstart, cmdend);
557 *val = strdupdelim (valstart, valend);
561 /* Run commands[comind].action. */
564 setval_internal (int comind, const char *com, const char *val)
566 assert (0 <= comind && comind < countof (commands));
567 DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
568 return ((*commands[comind].action) (com, val, commands[comind].closure));
571 /* Run command COM with value VAL. If running the command produces an
572 error, report the error and exit.
574 This is intended to be called from main() to modify Wget's behavior
575 through command-line switches. Since COM is hard-coded in main(),
576 it is not canonicalized, and this aborts when COM is not found.
578 If COMIND's are exported to init.h, this function will be changed
579 to accept COMIND directly. */
582 setoptval (const char *com, const char *val)
584 assert (val != NULL);
585 if (!setval_internal (command_by_name (com), com, val))
589 /* Parse OPT into command and value and run it. For example,
590 run_command("foo=bar") is equivalent to setoptval("foo", "bar").
591 This is used by the `--execute' flag in main.c. */
594 run_command (const char *opt)
598 int status = parse_line (opt, &com, &val, &comind);
601 if (!setval_internal (comind, com, val))
606 else if (status == 0)
608 fprintf (stderr, _("%s: Invalid --execute command `%s'\n"),
614 /* Generic helper functions, for use with `commands'. */
616 #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0')
618 #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0) \
619 && TOLOWER((p)[1]) == (c1) \
622 #define CMP3(p, c0, c1, c2) (TOLOWER((p)[0]) == (c0) \
623 && TOLOWER((p)[1]) == (c1) \
624 && TOLOWER((p)[2]) == (c2) \
628 /* Store the boolean value from VAL to CLOSURE. COM is ignored,
629 except for error messages. */
631 cmd_boolean (const char *com, const char *val, void *closure)
635 if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
636 /* "on", "yes" and "1" mean true. */
638 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
639 /* "off", "no" and "0" mean false. */
644 _("%s: %s: Invalid boolean `%s', use `on' or `off'.\n"),
645 exec_name, com, val);
649 *(int *)closure = bool_value;
653 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to CLOSURE.
654 COM is ignored, except for error messages. Values 2 and -1
655 indicate that once defined, the value may not be changed by
656 successive wgetrc files or command-line arguments.
658 Values: 2 - Enable a particular option for good ("always")
659 1 - Enable an option ("on")
660 0 - Disable an option ("off")
661 -1 - Disable an option for good ("never") */
663 cmd_lockable_boolean (const char *com, const char *val, void *closure)
665 int lockable_boolean_value;
667 int oldval = *(int *)closure;
670 * If a config file said "always" or "never", don't allow command line
671 * arguments to override the config file.
673 if (oldval == -1 || oldval == 2)
676 if (0 == strcasecmp (val, "always") || CMP1 (val, '2'))
677 lockable_boolean_value = 2;
678 else if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
679 lockable_boolean_value = 1;
680 else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
681 lockable_boolean_value = 0;
682 else if (0 == strcasecmp (val, "never") || CMP2 (val, '-', '1'))
683 lockable_boolean_value = -1;
687 _("%s: %s: Invalid boolean `%s', use always, on, off, or never.\n"),
688 exec_name, com, val);
692 *(int *)closure = lockable_boolean_value;
696 static int simple_atoi PARAMS ((const char *, const char *, int *));
698 /* Set the non-negative integer value from VAL to CLOSURE. With
699 incorrect specification, the number remains unchanged. */
701 cmd_number (const char *com, const char *val, void *closure)
703 if (!simple_atoi (val, val + strlen (val), closure))
705 fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
706 exec_name, com, val);
712 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
714 cmd_number_inf (const char *com, const char *val, void *closure)
716 if (!strcasecmp (val, "inf"))
721 return cmd_number (com, val, closure);
724 /* Copy (strdup) the string at COM to a new location and place a
725 pointer to *CLOSURE. */
727 cmd_string (const char *com, const char *val, void *closure)
729 char **pstring = (char **)closure;
731 xfree_null (*pstring);
732 *pstring = xstrdup (val);
737 # define ISSEP(c) ((c) == '/')
739 # define ISSEP(c) ((c) == '/' || (c) == '\\')
742 /* Like the above, but handles tilde-expansion when reading a user's
743 `.wgetrc'. In that case, and if VAL begins with `~', the tilde
744 gets expanded to the user's home directory. */
746 cmd_file (const char *com, const char *val, void *closure)
748 char **pstring = (char **)closure;
750 xfree_null (*pstring);
752 /* #### If VAL is empty, perhaps should set *CLOSURE to NULL. */
754 if (!enable_tilde_expansion || !(*val == '~' && ISSEP (val[1])))
757 *pstring = xstrdup (val);
763 char *home = home_dir ();
767 homelen = strlen (home);
768 while (homelen && ISSEP (home[homelen - 1]))
769 home[--homelen] = '\0';
771 /* Skip the leading "~/". */
772 for (++val; ISSEP (*val); val++)
775 result = xmalloc (homelen + 1 + strlen (val) + 1);
776 memcpy (result, home, homelen);
777 result[homelen] = '/';
778 strcpy (result + homelen + 1, val);
784 /* Convert "\" to "/". */
787 for (s = *pstring; *s; s++)
795 /* Like cmd_file, but strips trailing '/' characters. */
797 cmd_directory (const char *com, const char *val, void *closure)
801 /* Call cmd_file() for tilde expansion and separator
802 canonicalization (backslash -> slash under Windows). These
803 things should perhaps be in a separate function. */
804 if (!cmd_file (com, val, closure))
807 s = *(char **)closure;
809 while (t > s && *--t == '/')
815 /* Split VAL by space to a vector of values, and append those values
816 to vector pointed to by the CLOSURE argument. If VAL is empty, the
817 CLOSURE vector is cleared instead. */
820 cmd_vector (const char *com, const char *val, void *closure)
822 char ***pvec = (char ***)closure;
825 *pvec = merge_vecs (*pvec, sepstring (val));
835 cmd_directory_vector (const char *com, const char *val, void *closure)
837 char ***pvec = (char ***)closure;
841 /* Strip the trailing slashes from directories. */
844 seps = sepstring (val);
845 for (t = seps; t && *t; t++)
847 int len = strlen (*t);
848 /* Skip degenerate case of root directory. */
851 if ((*t)[len - 1] == '/')
852 (*t)[len - 1] = '\0';
855 *pvec = merge_vecs (*pvec, seps);
865 static int simple_atof PARAMS ((const char *, const char *, double *));
867 /* Enginge for cmd_bytes and cmd_bytes_large: converts a string such
868 as "100k" or "2.5G" to a floating point number. */
871 parse_bytes_helper (const char *val, double *result)
874 const char *end = val + strlen (val);
876 /* Check for "inf". */
877 if (0 == strcmp (val, "inf"))
883 /* Strip trailing whitespace. */
884 while (val < end && ISSPACE (end[-1]))
889 switch (TOLOWER (end[-1]))
892 --end, mult = 1024.0;
895 --end, mult = 1048576.0;
898 --end, mult = 1073741824.0;
901 --end, mult = 1099511627776.0;
904 /* Not a recognized suffix: assume it's a digit. (If not,
905 simple_atof will raise an error.) */
909 /* Skip leading and trailing whitespace. */
910 while (val < end && ISSPACE (*val))
912 while (val < end && ISSPACE (end[-1]))
917 if (!simple_atof (val, end, &number))
920 *result = number * mult;
924 /* Parse VAL as a number and set its value to CLOSURE (which should
925 point to a long int).
927 By default, the value is assumed to be in bytes. If "K", "M", or
928 "G" are appended, the value is multiplied with 1<<10, 1<<20, or
929 1<<30, respectively. Floating point values are allowed and are
930 cast to integer before use. The idea is to be able to use things
931 like 1.5k instead of "1536".
933 The string "inf" is returned as 0.
935 In case of error, 0 is returned and memory pointed to by CLOSURE
936 remains unmodified. */
939 cmd_bytes (const char *com, const char *val, void *closure)
942 if (!parse_bytes_helper (val, &byte_value))
944 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
945 exec_name, com, val);
948 *(long *)closure = (long)byte_value;
952 /* Like cmd_bytes, but CLOSURE is interpreted as a pointer to
953 LARGE_INT. It works by converting the string to double, therefore
954 working with values up to 2^53-1 without loss of precision. This
955 value (8192 TB) is large enough to serve for a while. */
958 cmd_bytes_large (const char *com, const char *val, void *closure)
961 if (!parse_bytes_helper (val, &byte_value))
963 fprintf (stderr, _("%s: %s: Invalid byte value `%s'\n"),
964 exec_name, com, val);
967 *(LARGE_INT *)closure = (LARGE_INT)byte_value;
971 /* Store the value of VAL to *OUT. The value is a time period, by
972 default expressed in seconds, but also accepting suffixes "m", "h",
973 "d", and "w" for minutes, hours, days, and weeks respectively. */
976 cmd_time (const char *com, const char *val, void *closure)
979 const char *end = val + strlen (val);
981 /* Strip trailing whitespace. */
982 while (val < end && ISSPACE (end[-1]))
988 fprintf (stderr, _("%s: %s: Invalid time period `%s'\n"),
989 exec_name, com, val);
993 switch (TOLOWER (end[-1]))
996 --end, mult = 1; /* seconds */
999 --end, mult = 60; /* minutes */
1002 --end, mult = 3600; /* hours */
1005 --end, mult = 86400.0; /* days */
1008 --end, mult = 604800.0; /* weeks */
1011 /* Not a recognized suffix: assume it belongs to the number.
1012 (If not, atof simple_atof will raise an error.) */
1016 /* Skip leading and trailing whitespace. */
1017 while (val < end && ISSPACE (*val))
1019 while (val < end && ISSPACE (end[-1]))
1024 if (!simple_atof (val, end, &number))
1027 *(double *)closure = number * mult;
1031 /* Specialized helper functions, used by `commands' to handle some
1032 options specially. */
1034 static int check_user_specified_header PARAMS ((const char *));
1037 cmd_spec_dirstruct (const char *com, const char *val, void *closure)
1039 if (!cmd_boolean (com, val, &opt.dirstruct))
1041 /* Since dirstruct behaviour is explicitly changed, no_dirstruct
1042 must be affected inversely. */
1044 opt.no_dirstruct = 0;
1046 opt.no_dirstruct = 1;
1051 cmd_spec_header (const char *com, const char *val, void *closure)
1055 /* Empty header means reset headers. */
1056 xfree_null (opt.user_header);
1057 opt.user_header = NULL;
1063 if (!check_user_specified_header (val))
1065 fprintf (stderr, _("%s: %s: Invalid header `%s'.\n"),
1066 exec_name, com, val);
1069 i = opt.user_header ? strlen (opt.user_header) : 0;
1070 opt.user_header = (char *)xrealloc (opt.user_header, i + strlen (val)
1072 strcpy (opt.user_header + i, val);
1074 opt.user_header[i++] = '\r';
1075 opt.user_header[i++] = '\n';
1076 opt.user_header[i] = '\0';
1082 cmd_spec_htmlify (const char *com, const char *val, void *closure)
1084 int flag = cmd_boolean (com, val, &opt.htmlify);
1085 if (flag && !opt.htmlify)
1086 opt.remove_listing = 0;
1090 /* Set the "mirror" mode. It means: recursive download, timestamping,
1091 no limit on max. recursion depth, and don't remove listings. */
1094 cmd_spec_mirror (const char *com, const char *val, void *closure)
1098 if (!cmd_boolean (com, val, &mirror))
1103 if (!opt.no_dirstruct)
1105 opt.timestamping = 1;
1106 opt.reclevel = INFINITE_RECURSION;
1107 opt.remove_listing = 0;
1112 /* Set progress.type to VAL, but verify that it's a valid progress
1113 implementation before that. */
1116 cmd_spec_progress (const char *com, const char *val, void *closure)
1118 if (!valid_progress_implementation_p (val))
1120 fprintf (stderr, _("%s: %s: Invalid progress type `%s'.\n"),
1121 exec_name, com, val);
1124 xfree_null (opt.progress_type);
1126 /* Don't call set_progress_implementation here. It will be called
1127 in main() when it becomes clear what the log output is. */
1128 opt.progress_type = xstrdup (val);
1132 /* Set opt.recursive to VAL as with cmd_boolean. If opt.recursive is
1133 set to true, also set opt.dirstruct to 1, unless opt.no_dirstruct
1137 cmd_spec_recursive (const char *com, const char *val, void *closure)
1139 if (!cmd_boolean (com, val, &opt.recursive))
1143 if (opt.recursive && !opt.no_dirstruct)
1150 cmd_spec_restrict_file_names (const char *com, const char *val, void *closure)
1152 int restrict_os = opt.restrict_files_os;
1153 int restrict_ctrl = opt.restrict_files_ctrl;
1155 const char *end = strchr (val, ',');
1157 end = val + strlen (val);
1159 #define VAL_IS(string_literal) BOUNDED_EQUAL (val, end, string_literal)
1161 if (VAL_IS ("unix"))
1162 restrict_os = restrict_unix;
1163 else if (VAL_IS ("windows"))
1164 restrict_os = restrict_windows;
1165 else if (VAL_IS ("nocontrol"))
1171 _("%s: %s: Invalid restriction `%s', use `unix' or `windows'.\n"),
1172 exec_name, com, val);
1180 if (!strcmp (end + 1, "nocontrol"))
1186 opt.restrict_files_os = restrict_os;
1187 opt.restrict_files_ctrl = restrict_ctrl;
1191 /* Set all three timeout values. */
1194 cmd_spec_timeout (const char *com, const char *val, void *closure)
1197 if (!cmd_time (com, val, &value))
1199 opt.read_timeout = value;
1200 opt.connect_timeout = value;
1201 opt.dns_timeout = value;
1206 cmd_spec_useragent (const char *com, const char *val, void *closure)
1208 /* Just check for empty string and newline, so we don't throw total
1209 junk to the server. */
1210 if (!*val || strchr (val, '\n'))
1212 fprintf (stderr, _("%s: %s: Invalid value `%s'.\n"),
1213 exec_name, com, val);
1216 opt.useragent = xstrdup (val);
1220 /* Miscellaneous useful routines. */
1222 /* A very simple atoi clone, more portable than strtol and friends,
1223 but reports errors, unlike atoi. Returns 1 on success, 0 on
1224 failure. In case of success, stores result to *DEST. */
1227 simple_atoi (const char *beg, const char *end, int *dest)
1235 for (p = beg; p < end && ISDIGIT (*p); p++)
1236 result = (10 * result) + (*p - '0');
1245 /* Trivial atof, with error reporting. Handles "<digits>[.<digits>]",
1246 doesn't handle exponential notation. Returns 1 on success, 0 on
1247 failure. In case of success, stores its result to *DEST. */
1250 simple_atof (const char *beg, const char *end, double *dest)
1260 for (p = beg; p < end; p++)
1266 result = (10 * result) + (ch - '0');
1268 result += (ch - '0') / (divider *= 10);
1289 check_user_specified_header (const char *s)
1293 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1294 /* The header MUST contain `:' preceded by at least one
1295 non-whitespace character. */
1296 if (*p != ':' || p == s)
1298 /* The header MUST NOT contain newlines. */
1299 if (strchr (s, '\n'))
1304 void cleanup_html_url PARAMS ((void));
1305 void res_cleanup PARAMS ((void));
1306 void downloaded_files_free PARAMS ((void));
1307 void http_cleanup PARAMS ((void));
1310 /* Free the memory allocated by global variables. */
1314 /* Free external resources, close files, etc. */
1319 /* We're exiting anyway so there's no real need to call free()
1320 hundreds of times. Skipping the frees will make Wget exit
1323 However, when detecting leaks, it's crucial to free() everything
1324 because then you can find the real leaks, i.e. the allocated
1325 memory which grows with the size of the program. */
1331 cleanup_html_url ();
1332 downloaded_files_free ();
1334 if (wget_cookie_jar)
1335 cookie_jar_delete (wget_cookie_jar);
1338 extern acc_t *netrc_list;
1339 free_netrc (netrc_list);
1341 xfree_null (opt.lfilename);
1342 xfree_null (opt.dir_prefix);
1343 xfree_null (opt.input_filename);
1344 xfree_null (opt.output_document);
1345 free_vec (opt.accepts);
1346 free_vec (opt.rejects);
1347 free_vec (opt.excludes);
1348 free_vec (opt.includes);
1349 free_vec (opt.domains);
1350 free_vec (opt.follow_tags);
1351 free_vec (opt.ignore_tags);
1352 xfree_null (opt.progress_type);
1353 xfree (opt.ftp_acc);
1354 xfree_null (opt.ftp_pass);
1355 xfree_null (opt.ftp_proxy);
1356 xfree_null (opt.https_proxy);
1357 xfree_null (opt.http_proxy);
1358 free_vec (opt.no_proxy);
1359 xfree_null (opt.useragent);
1360 xfree_null (opt.referer);
1361 xfree_null (opt.http_user);
1362 xfree_null (opt.http_passwd);
1363 xfree_null (opt.user_header);
1365 xfree_null (opt.sslcertkey);
1366 xfree_null (opt.sslcertfile);
1367 #endif /* HAVE_SSL */
1368 xfree_null (opt.bind_address);
1369 xfree_null (opt.cookies_input);
1370 xfree_null (opt.cookies_output);