X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Finit.c;h=9ce9b1662a8414601425fa65b4fca94b758387bd;hb=7c802e58d3e45e3a21d99c8d24dc5be806ecf174;hp=45ae35453bfbfac2a7cb86af1975567ae87a32ae;hpb=5d8cfbd9044f91d277027d8c1aab3c47e118b407;p=wget diff --git a/src/init.c b/src/init.c index 45ae3545..9ce9b166 100644 --- a/src/init.c +++ b/src/init.c @@ -1,26 +1,36 @@ /* Reading/parsing the initialization file. - Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 + Free Software Foundation, Inc. -This file is part of Wget. +This file is part of GNU Wget. -This program is free software; you can redistribute it and/or modify +GNU Wget is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, +GNU Wget is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with Wget; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +In addition, as a special exception, the Free Software Foundation +gives permission to link the code of its release of Wget with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. */ #include #include -#include #include #include #ifdef HAVE_UNISTD_H @@ -33,6 +43,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif #include +#ifdef WINDOWS +# include +#else +# include +# include +#ifndef __BEOS__ +# include +#endif +#endif + #ifdef HAVE_PWD_H #include #endif @@ -43,38 +63,51 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "host.h" #include "recur.h" #include "netrc.h" +#include "cookies.h" /* for cookie_jar_delete */ +#include "progress.h" #ifndef errno extern int errno; #endif +extern struct cookie_jar *wget_cookie_jar; + +/* We want tilde expansion enabled only when reading `.wgetrc' lines; + otherwise, it will be performed by the shell. This variable will + be set by the wgetrc-reading function. */ + +static int enable_tilde_expansion; + #define CMD_DECLARE(func) static int func \ PARAMS ((const char *, const char *, void *)) CMD_DECLARE (cmd_boolean); -CMD_DECLARE (cmd_boolean); +CMD_DECLARE (cmd_bytes); +CMD_DECLARE (cmd_directory_vector); +CMD_DECLARE (cmd_lockable_boolean); CMD_DECLARE (cmd_number); CMD_DECLARE (cmd_number_inf); CMD_DECLARE (cmd_string); -CMD_DECLARE (cmd_vector); -CMD_DECLARE (cmd_directory_vector); -CMD_DECLARE (cmd_bytes); +CMD_DECLARE (cmd_file); +CMD_DECLARE (cmd_directory); CMD_DECLARE (cmd_time); +CMD_DECLARE (cmd_vector); CMD_DECLARE (cmd_spec_dirstruct); -CMD_DECLARE (cmd_spec_dotstyle); CMD_DECLARE (cmd_spec_header); CMD_DECLARE (cmd_spec_htmlify); CMD_DECLARE (cmd_spec_mirror); -CMD_DECLARE (cmd_spec_outputdocument); +CMD_DECLARE (cmd_spec_progress); CMD_DECLARE (cmd_spec_recursive); +CMD_DECLARE (cmd_spec_restrict_file_names); CMD_DECLARE (cmd_spec_useragent); -/* List of recognized commands, each consisting of name, closure and - function. When adding a new command, simply add it to the list, - but be sure to keep the list sorted alphabetically, as comind() - depends on it. */ +/* List of recognized commands, each consisting of name, closure and function. + When adding a new command, simply add it to the list, but be sure to keep the + list sorted alphabetically, as comind() depends on it. Also, be sure to add + any entries that allocate memory (e.g. cmd_string and cmd_vector guys) to the + cleanup() function below. */ static struct { char *name; void *closure; @@ -87,64 +120,94 @@ static struct { { "backupconverted", &opt.backup_converted, cmd_boolean }, { "backups", &opt.backups, cmd_number }, { "base", &opt.base_href, cmd_string }, - { "cache", &opt.proxy_cache, cmd_boolean }, + { "bindaddress", &opt.bind_address, cmd_string }, + { "cache", &opt.allow_cache, cmd_boolean }, { "continue", &opt.always_rest, cmd_boolean }, { "convertlinks", &opt.convert_links, cmd_boolean }, + { "cookies", &opt.cookies, cmd_boolean }, { "cutdirs", &opt.cut_dirs, cmd_number }, #ifdef DEBUG { "debug", &opt.debug, cmd_boolean }, #endif { "deleteafter", &opt.delete_after, cmd_boolean }, - { "dirprefix", &opt.dir_prefix, cmd_string }, + { "dirprefix", &opt.dir_prefix, cmd_directory }, { "dirstruct", NULL, cmd_spec_dirstruct }, + { "dnscache", &opt.dns_cache, cmd_boolean }, { "domains", &opt.domains, cmd_vector }, { "dotbytes", &opt.dot_bytes, cmd_bytes }, { "dotsinline", &opt.dots_in_line, cmd_number }, { "dotspacing", &opt.dot_spacing, cmd_number }, - { "dotstyle", NULL, cmd_spec_dotstyle }, + { "dotstyle", &opt.dot_style, cmd_string }, +#ifdef HAVE_SSL + { "egdfile", &opt.sslegdsock, cmd_file }, +#endif { "excludedirectories", &opt.excludes, cmd_directory_vector }, { "excludedomains", &opt.exclude_domains, cmd_vector }, { "followftp", &opt.follow_ftp, cmd_boolean }, + { "followtags", &opt.follow_tags, cmd_vector }, { "forcehtml", &opt.force_html, cmd_boolean }, { "ftpproxy", &opt.ftp_proxy, cmd_string }, { "glob", &opt.ftp_glob, cmd_boolean }, { "header", NULL, cmd_spec_header }, + { "htmlextension", &opt.html_extension, cmd_boolean }, { "htmlify", NULL, cmd_spec_htmlify }, + { "httpkeepalive", &opt.http_keep_alive, cmd_boolean }, { "httppasswd", &opt.http_passwd, cmd_string }, { "httpproxy", &opt.http_proxy, cmd_string }, + { "httpsproxy", &opt.https_proxy, cmd_string }, { "httpuser", &opt.http_user, cmd_string }, { "ignorelength", &opt.ignore_length, cmd_boolean }, + { "ignoretags", &opt.ignore_tags, cmd_vector }, { "includedirectories", &opt.includes, cmd_directory_vector }, - { "input", &opt.input_filename, cmd_string }, + { "input", &opt.input_filename, cmd_file }, { "killlonger", &opt.kill_longer, cmd_boolean }, - { "logfile", &opt.lfilename, cmd_string }, + { "limitrate", &opt.limit_rate, cmd_bytes }, + { "loadcookies", &opt.cookies_input, cmd_file }, + { "logfile", &opt.lfilename, cmd_file }, { "login", &opt.ftp_acc, cmd_string }, { "mirror", NULL, cmd_spec_mirror }, { "netrc", &opt.netrc, cmd_boolean }, { "noclobber", &opt.noclobber, cmd_boolean }, { "noparent", &opt.no_parent, cmd_boolean }, { "noproxy", &opt.no_proxy, cmd_vector }, - { "numtries", &opt.ntry, cmd_number_inf }, /* deprecated */ - { "outputdocument", NULL, cmd_spec_outputdocument }, - { "passiveftp", &opt.ftp_pasv, cmd_boolean }, + { "numtries", &opt.ntry, cmd_number_inf },/* deprecated*/ + { "outputdocument", &opt.output_document, cmd_file }, + { "pagerequisites", &opt.page_requisites, cmd_boolean }, + { "passiveftp", &opt.ftp_pasv, cmd_lockable_boolean }, { "passwd", &opt.ftp_pass, cmd_string }, + { "postdata", &opt.post_data, cmd_string }, + { "postfile", &opt.post_file_name, cmd_file }, + { "progress", &opt.progress_type, cmd_spec_progress }, { "proxypasswd", &opt.proxy_passwd, cmd_string }, { "proxyuser", &opt.proxy_user, cmd_string }, { "quiet", &opt.quiet, cmd_boolean }, { "quota", &opt.quota, cmd_bytes }, + { "randomwait", &opt.random_wait, cmd_boolean }, { "reclevel", &opt.reclevel, cmd_number_inf }, { "recursive", NULL, cmd_spec_recursive }, { "referer", &opt.referer, cmd_string }, { "reject", &opt.rejects, cmd_vector }, { "relativeonly", &opt.relative_only, cmd_boolean }, { "removelisting", &opt.remove_listing, cmd_boolean }, + { "restrictfilenames", NULL, cmd_spec_restrict_file_names }, { "retrsymlinks", &opt.retr_symlinks, cmd_boolean }, + { "retryconnrefused", &opt.retry_connrefused, cmd_boolean }, { "robots", &opt.use_robots, cmd_boolean }, + { "savecookies", &opt.cookies_output, cmd_file }, { "saveheaders", &opt.save_headers, cmd_boolean }, { "serverresponse", &opt.server_response, cmd_boolean }, - { "simplehostcheck", &opt.simple_check, cmd_boolean }, { "spanhosts", &opt.spanhost, cmd_boolean }, { "spider", &opt.spider, cmd_boolean }, +#ifdef HAVE_SSL + { "sslcadir", &opt.sslcadir, cmd_directory }, + { "sslcafile", &opt.sslcafile, cmd_file }, + { "sslcertfile", &opt.sslcertfile, cmd_file }, + { "sslcertkey", &opt.sslcertkey, cmd_file }, + { "sslcerttype", &opt.sslcerttype, cmd_number }, + { "sslcheckcert", &opt.sslcheckcert, cmd_number }, + { "sslprotocol", &opt.sslprotocol, cmd_number }, +#endif /* HAVE_SSL */ + { "strictcomments", &opt.strict_comments, cmd_boolean }, { "timeout", &opt.timeout, cmd_time }, { "timestamping", &opt.timestamping, cmd_boolean }, { "tries", &opt.ntry, cmd_number_inf }, @@ -155,25 +218,25 @@ static struct { { "waitretry", &opt.waitretry, cmd_time } }; -/* Return index of COM if it is a valid command, or -1 otherwise. COM - is looked up in `commands' using binary search algorithm. */ +/* Look up COM in the commands[] array and return its index. If COM + is not found, -1 is returned. This function uses binary search. */ + static int comind (const char *com) { - int min = 0, max = ARRAY_SIZE (commands); + int lo = 0, hi = ARRAY_SIZE (commands) - 1; - do + while (lo <= hi) { - int i = (min + max) / 2; - int cmp = strcasecmp (com, commands[i].name); - if (cmp == 0) - return i; - else if (cmp < 0) - max = i - 1; + int mid = (lo + hi) >> 1; + int cmp = strcasecmp (com, commands[mid].name); + if (cmp < 0) + hi = mid - 1; + else if (cmp > 0) + lo = mid + 1; else - min = i + 1; + return mid; } - while (min <= max); return -1; } @@ -190,21 +253,24 @@ defaults (void) of the implementors' worries. */ memset (&opt, 0, sizeof (opt)); + opt.cookies = 1; + opt.verbose = -1; opt.dir_prefix = xstrdup ("."); opt.ntry = 20; opt.reclevel = 5; opt.add_hostdir = 1; - opt.ftp_acc = xstrdup ("anonymous"); - /*opt.ftp_pass = xstrdup (ftp_getaddress ());*/ + opt.ftp_acc = xstrdup ("anonymous"); + opt.ftp_pass = xstrdup ("-wget@"); opt.netrc = 1; opt.ftp_glob = 1; opt.htmlify = 1; + opt.http_keep_alive = 1; opt.use_proxy = 1; tmp = getenv ("no_proxy"); if (tmp) opt.no_proxy = sepstring (tmp); - opt.proxy_cache = 1; + opt.allow_cache = 1; #ifdef HAVE_SELECT opt.timeout = 900; @@ -216,6 +282,16 @@ defaults (void) opt.dot_bytes = 1024; opt.dot_spacing = 10; opt.dots_in_line = 50; + + opt.dns_cache = 1; + + /* The default for file name restriction defaults to the OS type. */ +#if !defined(WINDOWS) && !defined(__CYGWIN__) + opt.restrict_files_os = restrict_unix; +#else + opt.restrict_files_os = restrict_windows; +#endif + opt.restrict_files_ctrl = 1; } /* Return the user's home directory (strdup-ed), or NULL if none is @@ -261,7 +337,7 @@ wgetrc_file_name (void) { if (!file_exists_p (env)) { - fprintf (stderr, "%s: %s: %s.\n", exec_name, file, strerror (errno)); + fprintf (stderr, "%s: %s: %s.\n", exec_name, env, strerror (errno)); exit (1); } return xstrdup (env); @@ -275,6 +351,7 @@ wgetrc_file_name (void) file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1); sprintf (file, "%s/.wgetrc", home); } + FREE_MAYBE (home); #else /* WINDOWS */ /* Under Windows, "home" is (for the purposes of this function) the directory where `wget.exe' resides, and `wget.ini' will be used @@ -290,12 +367,11 @@ wgetrc_file_name (void) } #endif /* WINDOWS */ - FREE_MAYBE (home); if (!file) return NULL; if (!file_exists_p (file)) { - free (file); + xfree (file); return NULL; } return file; @@ -316,33 +392,31 @@ run_wgetrc (const char *file) file, strerror (errno)); return; } - /* Reset line number. */ + enable_tilde_expansion = 1; ln = 1; while ((line = read_whole_line (fp))) { char *com, *val; int status; - int length = strlen (line); - if (length && line[length - 1] == '\r') - line[length - 1] = '\0'; /* Parse the line. */ status = parse_line (line, &com, &val); - free (line); + xfree (line); /* If everything is OK, set the value. */ if (status == 1) { if (!setval (com, val)) fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name, file, ln); - free (com); - free (val); + xfree (com); + xfree (val); } else if (status == 0) fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name, file, ln); ++ln; } + enable_tilde_expansion = 0; fclose (fp); } @@ -377,7 +451,7 @@ initialize (void) else #endif run_wgetrc (file); - free (file); + xfree (file); return; } @@ -397,12 +471,12 @@ parse_line (const char *line, char **com, char **val) const char *orig_comptr, *end; char *new_comptr; - /* Skip spaces. */ - while (*p == ' ' || *p == '\t') + /* Skip whitespace. */ + while (*p && ISSPACE (*p)) ++p; /* Don't process empty lines. */ - if (!*p || *p == '\n' || *p == '#') + if (!*p || *p == '#') return -1; for (orig_comptr = p; ISALPHA (*p) || *p == '_' || *p == '-'; p++) @@ -410,6 +484,8 @@ parse_line (const char *line, char **com, char **val) /* The next char should be space or '='. */ if (!ISSPACE (*p) && (*p != '=')) return 0; + /* Here we cannot use strdupdelim() as we normally would because we + want to skip the `-' and `_' characters in the input string. */ *com = (char *)xmalloc (p - orig_comptr + 1); for (new_comptr = *com; orig_comptr < p; orig_comptr++) { @@ -421,7 +497,7 @@ parse_line (const char *line, char **com, char **val) /* If the command is invalid, exit now. */ if (comind (*com) == -1) { - free (*com); + xfree (*com); return 0; } @@ -430,15 +506,17 @@ parse_line (const char *line, char **com, char **val) /* If '=' not found, bail out. */ if (*p != '=') { - free (*com); + xfree (*com); return 0; } /* Skip spaces after '='. */ for (++p; ISSPACE (*p); p++); - /* Get the ending position. */ - for (end = p; *end && *end != '\n'; end++); - /* Allocate *val, and copy from line. */ - *val = strdupdelim (p, end); + /* Get the ending position for VAL by starting with the end of the + line and skipping whitespace. */ + end = line + strlen (line) - 1; + while (end > p && ISSPACE (*end)) + --end; + *val = strdupdelim (p, end + 1); return 1; } @@ -476,12 +554,22 @@ static int cmd_boolean (const char *com, const char *val, void *closure) { int bool_value; - - if (!strcasecmp (val, "on") - || (*val == '1' && !*(val + 1))) + const char *v = val; +#define LC(x) TOLOWER(x) + + if ((LC(v[0]) == 'o' && LC(v[1]) == 'n' && !v[2]) + || + (LC(v[0]) == 'y' && LC(v[1]) == 'e' && LC(v[2]) == 's' && !v[3]) + || + (v[0] == '1' && !v[1])) + /* "on", "yes" and "1" mean true. */ bool_value = 1; - else if (!strcasecmp (val, "off") - || (*val == '0' && !*(val + 1))) + else if ((LC(v[0]) == 'o' && LC(v[1]) == 'f' && LC(v[2]) == 'f' && !v[3]) + || + (LC(v[0]) == 'n' && LC(v[1]) == 'o' && !v[2]) + || + (v[0] == '0' && !v[1])) + /* "off", "no" and "0" mean false. */ bool_value = 0; else { @@ -494,6 +582,51 @@ cmd_boolean (const char *com, const char *val, void *closure) return 1; } +/* Store the lockable_boolean {2, 1, 0, -1} value from VAL to CLOSURE. COM is + ignored, except for error messages. Values 2 and -1 indicate that once + defined, the value may not be changed by successive wgetrc files or + command-line arguments. + + Values: 2 - Enable a particular option for good ("always") + 1 - Enable an option ("on") + 0 - Disable an option ("off") + -1 - Disable an option for good ("never") */ +static int +cmd_lockable_boolean (const char *com, const char *val, void *closure) +{ + int lockable_boolean_value; + + /* + * If a config file said "always" or "never", don't allow command line + * arguments to override the config file. + */ + if (*(int *)closure == -1 || *(int *)closure == 2) + return 1; + + if (!strcasecmp (val, "always") || !strcmp (val, "2")) + lockable_boolean_value = 2; + else if (!strcasecmp (val, "on") + || !strcasecmp (val, "yes") + || !strcmp (val, "1")) + lockable_boolean_value = 1; + else if (!strcasecmp (val, "off") + || !strcasecmp (val, "no") + || !strcmp (val, "0")) + lockable_boolean_value = 0; + else if (!strcasecmp (val, "never") || !strcmp (val, "-1")) + lockable_boolean_value = -1; + else + { + fprintf (stderr, _("%s: %s: Please specify always, on, off, " + "or never.\n"), + exec_name, com); + return 0; + } + + *(int *)closure = lockable_boolean_value; + return 1; +} + /* Set the non-negative integer value from VAL to CLOSURE. With incorrect specification, the number remains unchanged. */ static int @@ -535,6 +668,91 @@ cmd_string (const char *com, const char *val, void *closure) return 1; } +/* Like the above, but handles tilde-expansion when reading a user's + `.wgetrc'. In that case, and if VAL begins with `~', the tilde + gets expanded to the user's home directory. */ +static int +cmd_file (const char *com, const char *val, void *closure) +{ + char **pstring = (char **)closure; + + FREE_MAYBE (*pstring); + + /* #### If VAL is empty, perhaps should set *CLOSURE to NULL. */ + + if (!enable_tilde_expansion || !(*val == '~' && (*(val + 1) == '/' +#ifdef WINDOWS + || *(val + 1) == '\\' +#endif + ))) + { + noexpand: + *pstring = xstrdup (val); + } + else + { + char *result; + int homelen; + char *home = home_dir (); + if (!home) + goto noexpand; + + homelen = strlen (home); + while (homelen && (home[homelen - 1] == '/' +#ifdef WINDOWS + || home[homelen - 1] == '\\' +#endif + )) + home[--homelen] = '\0'; + + /* Skip the leading "~/". */ +#ifdef WINDOWS + for (++val; *val == '/' || *val == '\\'; val++) + ; +#else + for (++val; *val == '/'; val++) + ; +#endif + + result = xmalloc (homelen + 1 + strlen (val) + 1); + memcpy (result, home, homelen); + result[homelen] = '/'; + strcpy (result + homelen + 1, val); + + *pstring = result; + } +#ifdef WINDOWS + /* Convert "\" to "/". */ + { + char *s; + for (s = *pstring; *s; s++) + if (*s == '\\') + *s = '/'; + } +#endif + return 1; +} + +/* Like cmd_file, but strips trailing '/' characters. */ +static int +cmd_directory (const char *com, const char *val, void *closure) +{ + char *s, *t; + + /* Call cmd_file() for tilde expansion and separator + canonicalization (backslash -> slash under Windows). These + things should perhaps be in a separate function. */ + if (!cmd_file (com, val, closure)) + return 0; + + s = *(char **)closure; + t = s + strlen (s); + while (t > s && *--t == '/') + *t = '\0'; + + return 1; +} + /* Merge the vector (array of strings separated with `,') in COM with the vector (NULL-terminated array of strings) pointed to by CLOSURE. */ @@ -620,7 +838,7 @@ cmd_bytes (const char *com, const char *val, void *closure) return 0; } /* Search for a designator. */ - switch (tolower (*p)) + switch (TOLOWER (*p)) { case '\0': /* None */ @@ -664,7 +882,7 @@ cmd_time (const char *com, const char *val, void *closure) return 0; } /* Search for a suffix. */ - switch (tolower (*p)) + switch (TOLOWER (*p)) { case '\0': /* None */ @@ -712,61 +930,6 @@ cmd_spec_dirstruct (const char *com, const char *val, void *closure) return 1; } -static int -cmd_spec_dotstyle (const char *com, const char *val, void *closure) -{ - /* Retrieval styles. */ - if (!strcasecmp (val, "default")) - { - /* Default style: 1K dots, 10 dots in a cluster, 50 dots in a - line. */ - opt.dot_bytes = 1024; - opt.dot_spacing = 10; - opt.dots_in_line = 50; - } - else if (!strcasecmp (val, "binary")) - { - /* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots - (384K) in a line. */ - opt.dot_bytes = 8192; - opt.dot_spacing = 16; - opt.dots_in_line = 48; - } - else if (!strcasecmp (val, "mega")) - { - /* "Mega" retrieval, for retrieving very long files; each dot is - 64K, 8 dots in a cluster, 6 clusters (3M) in a line. */ - opt.dot_bytes = 65536L; - opt.dot_spacing = 8; - opt.dots_in_line = 48; - } - else if (!strcasecmp (val, "giga")) - { - /* "Giga" retrieval, for retrieving very very *very* long files; - each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a - line. */ - opt.dot_bytes = (1L << 20); - opt.dot_spacing = 8; - opt.dots_in_line = 32; - } - else if (!strcasecmp (val, "micro")) - { - /* "Micro" retrieval, for retrieving very small files (and/or - slow connections); each dot is 128 bytes, 8 dots in a - cluster, 6 clusters (6K) in a line. */ - opt.dot_bytes = 128; - opt.dot_spacing = 8; - opt.dots_in_line = 48; - } - else - { - fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"), - exec_name, com, val); - return 0; - } - return 1; -} - static int cmd_spec_header (const char *com, const char *val, void *closure) { @@ -820,18 +983,26 @@ cmd_spec_mirror (const char *com, const char *val, void *closure) if (!opt.no_dirstruct) opt.dirstruct = 1; opt.timestamping = 1; - opt.reclevel = 0; + opt.reclevel = INFINITE_RECURSION; opt.remove_listing = 0; } return 1; } static int -cmd_spec_outputdocument (const char *com, const char *val, void *closure) +cmd_spec_progress (const char *com, const char *val, void *closure) { - FREE_MAYBE (opt.output_document); - opt.output_document = xstrdup (val); - opt.ntry = 1; + if (!valid_progress_implementation_p (val)) + { + fprintf (stderr, _("%s: %s: Invalid progress type `%s'.\n"), + exec_name, com, val); + return 0; + } + FREE_MAYBE (opt.progress_type); + + /* Don't call set_progress_implementation here. It will be called + in main() when it becomes clear what the log output is. */ + opt.progress_type = xstrdup (val); return 1; } @@ -848,6 +1019,47 @@ cmd_spec_recursive (const char *com, const char *val, void *closure) return 1; } +static int +cmd_spec_restrict_file_names (const char *com, const char *val, void *closure) +{ + int restrict_os = opt.restrict_files_os; + int restrict_ctrl = opt.restrict_files_ctrl; + + const char *end = strchr (val, ','); + if (!end) + end = val + strlen (val); + +#define VAL_IS(string_literal) BOUNDED_EQUAL (val, end, string_literal) + + if (VAL_IS ("unix")) + restrict_os = restrict_unix; + else if (VAL_IS ("windows")) + restrict_os = restrict_windows; + else if (VAL_IS ("nocontrol")) + restrict_ctrl = 0; + else + { + err: + fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"), + exec_name, com, val); + return 0; + } + +#undef VAL_IS + + if (*end) + { + if (!strcmp (end + 1, "nocontrol")) + restrict_ctrl = 0; + else + goto err; + } + + opt.restrict_files_os = restrict_os; + opt.restrict_files_ctrl = restrict_ctrl; + return 1; +} + static int cmd_spec_useragent (const char *com, const char *val, void *closure) { @@ -881,8 +1093,6 @@ myatoi (const char *s) return res; } -#define ISODIGIT(x) ((x) >= '0' && (x) <= '7') - static int check_user_specified_header (const char *s) { @@ -899,19 +1109,44 @@ check_user_specified_header (const char *s) return 1; } +void cleanup_html_url PARAMS ((void)); +void res_cleanup PARAMS ((void)); +void downloaded_files_free PARAMS ((void)); +void http_cleanup PARAMS ((void)); + + /* Free the memory allocated by global variables. */ void cleanup (void) { - extern acc_t *netrc_list; + /* Free external resources, close files, etc. */ - recursive_cleanup (); - clean_hosts (); - free_netrc (netrc_list); if (opt.dfp) fclose (opt.dfp); + + /* We're exiting anyway so there's no real need to call free() + hundreds of times. Skipping the frees will make Wget exit + faster. + + However, when detecting leaks, it's crucial to free() everything + because then you can find the real leaks, i.e. the allocated + memory which grows with the size of the program. */ + +#ifdef DEBUG_MALLOC + recursive_cleanup (); + res_cleanup (); + http_cleanup (); + cleanup_html_url (); + downloaded_files_free (); + host_cleanup (); + cookie_jar_delete (wget_cookie_jar); + + { + extern acc_t *netrc_list; + free_netrc (netrc_list); + } FREE_MAYBE (opt.lfilename); - free (opt.dir_prefix); + xfree (opt.dir_prefix); FREE_MAYBE (opt.input_filename); FREE_MAYBE (opt.output_document); free_vec (opt.accepts); @@ -919,9 +1154,13 @@ cleanup (void) free_vec (opt.excludes); free_vec (opt.includes); free_vec (opt.domains); - free (opt.ftp_acc); - free (opt.ftp_pass); + free_vec (opt.follow_tags); + free_vec (opt.ignore_tags); + FREE_MAYBE (opt.progress_type); + xfree (opt.ftp_acc); + FREE_MAYBE (opt.ftp_pass); FREE_MAYBE (opt.ftp_proxy); + FREE_MAYBE (opt.https_proxy); FREE_MAYBE (opt.http_proxy); free_vec (opt.no_proxy); FREE_MAYBE (opt.useragent); @@ -929,4 +1168,12 @@ cleanup (void) FREE_MAYBE (opt.http_user); FREE_MAYBE (opt.http_passwd); FREE_MAYBE (opt.user_header); +#ifdef HAVE_SSL + FREE_MAYBE (opt.sslcertkey); + FREE_MAYBE (opt.sslcertfile); +#endif /* HAVE_SSL */ + FREE_MAYBE (opt.bind_address); + FREE_MAYBE (opt.cookies_input); + FREE_MAYBE (opt.cookies_output); +#endif }