home *** CD-ROM | disk | FTP | other *** search
- /* Reading/parsing the initialization file.
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
-
- This program 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,
- 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. */
-
-
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif /* HAVE_CONFIG_H */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #ifdef HAVE_STRING_H
- # include <string.h>
- #else
- # include <strings.h>
- #endif
-
- #ifdef HAVE_PWD_H
- #include <pwd.h>
- #endif
-
- #include <assert.h>
-
- #include "wget.h"
- #include "options.h"
- #include "utils.h"
- #include "init.h"
- #include "url.h"
- #include "ftp.h"
- #include "host.h"
- #include "recur.h"
- #include "netrc.h"
-
- extern char *version_string;
- extern struct options opt;
- extern int errno;
-
- extern acc_t *netrc_list;
-
- /* List of recognized commands, each consisting of a string-name, ID
- and what_to_do.
-
- When adding a new command, you must append it to the list (it is a
- good idea to keep the list sorted). Each command has an ID (as
- listed in init.h, a pointer over which it will work, and an
- indication how it will work.
-
- CONOFF -> integer toggle
- CNUM -> integer
- CNUMINF -> integer, with "inf" synomim for 0
- CSTR -> free old string, if non-NULL, and strdup val
- CVEC -> vector
- CSPEC -> special, has to be treated specially in setval */
- struct cmd commands[] = {
- { "accept", ACCEPT, &opt.accepts, CVEC },
- { "addhostdir", ADDHOSTDIR, &opt.add_hostdir, CONOFF },
- { "alwaysrest", ALWAYSREST, &opt.always_rest, CONOFF },
- { "backups", BACKUPS, &opt.backups, CONOFF },
- { "basehref", BASEHREF, &opt.base_href, CSTR },
- { "cache", CACHE, &opt.proxy_cache, CONOFF },
- { "convertlinks", CONVERTLINKS, &opt.convert_links, CONOFF },
- { "debug", DEBUG_, NULL, CSPEC },
- { "deleteafter", DELETEAFTER, &opt.delete_after, CONOFF },
- { "dirmode", DIRMODE, NULL, CSPEC },
- { "dirprefix", DIRPREFIX, &opt.dir_prefix, CSTR },
- { "dirstruct", DIRSTRUCT, NULL, CSPEC },
- { "domains", DOMAINS, &opt.domains, CVEC },
- { "dotbytes", DOTBYTES, &opt.dot_bytes, CBYT },
- { "dotsinline", DOTSINLINE, &opt.dots_in_line, CNUM },
- { "dotspacing", DOTSPACING, &opt.dot_spacing, CNUM },
- { "dotstyle", DOTSTYLE, NULL, CSPEC },
- { "excludedirectories", EXCLUDEDIRECTORIES, &opt.excludes, CVECDIR },
- { "excludedomains", EXCLUDEDOMAINS, &opt.exclude_domains, CVEC },
- { "followftp", FOLLOWFTP, &opt.follow_ftp, CONOFF },
- { "forcehtml", FORCEHTML, &opt.force_html, CONOFF },
- { "ftpproxy", FTPPROXY, &opt.ftp_proxy, CSTR },
- { "glob", GLOB, &opt.ftp_glob, CONOFF },
- { "header", HEADER, NULL, CSPEC },
- { "htmlify", HTMLIFY, NULL, CSPEC },
- { "httppasswd", HTTPPASSWD, &opt.http_passwd, CSTR },
- { "httpproxy", HTTPPROXY, &opt.http_proxy, CSTR },
- { "httpuser", HTTPUSER, &opt.http_user, CSTR },
- { "ignorelength", IGNORELENGTH, &opt.ignore_length, CONOFF },
- { "includedirectories", INCLUDEDIRECTORIES, &opt.includes, CVECDIR },
- { "input", INPUT, &opt.input_filename, CSTR },
- { "killlonger", KILLLONGER, &opt.kill_longer, CONOFF },
- { "logfile", LOGFILE, &opt.lfilename, CSTR },
- { "login", LOGIN, &opt.ftp_acc, CSTR },
- { "mirror", MIRROR, NULL, CSPEC },
- { "noclobber", NOCLOBBER, &opt.noclobber, CONOFF },
- { "noparent", NOPARENT, &opt.no_parent, CONOFF },
- { "noproxy", NOPROXY, &opt.no_proxy, CVEC },
- { "numtries", NUMTRIES, &opt.ntry, CNUMINF },
- { "outputdocument", OUTPUTDOCUMENT, NULL, CSPEC },
- { "passiveftp", PASSIVEFTP, &opt.ftp_pasv, CONOFF },
- { "passwd", PASSWD, &opt.ftp_pass, CSTR },
- { "quiet", QUIET, &opt.quiet, CONOFF },
- { "quota", QUOTA, &opt.quota, CBYT },
- { "reclevel", RECLEVEL, &opt.maxreclevel, CNUMINF },
- { "recursive", RECURSIVE, NULL, CSPEC },
- { "reject", REJECT, &opt.rejects, CVEC },
- { "relativeonly", RELATIVEONLY, &opt.relative_only, CONOFF },
- { "removelisting", REMOVELISTING, &opt.remove_listing, CONOFF },
- { "retrsymlinks", RETRSYMLINKS, &opt.retr_symlinks, CONOFF },
- { "robots", ROBOTS, &opt.use_robots, CONOFF },
- { "saveheaders", SAVEHEADERS, &opt.save_headers, CONOFF },
- { "serverresponse", SERVERRESPONSE, &opt.server_response, CONOFF },
- { "simplehostcheck", SIMPLEHOSTCHECK,&opt.simple_check, CONOFF },
- { "spanhosts", SPANHOSTS, &opt.spanhost, CONOFF },
- { "spider", SPIDER, &opt.spider, CONOFF },
- { "timeout", TIMEOUT, NULL, CSPEC },
- { "timestamping", TIMESTAMPING, &opt.timestamping, CONOFF },
- { "useproxy", USEPROXY, &opt.use_proxy, CONOFF },
- { "useragent", USERAGENT, &opt.useragent, CSTR },
- { "verbose", VERBOSE, &opt.verbose, CONOFF },
- { "wait", WAIT, &opt.wait, CNUM },
- { NULL, LAST }
- };
-
-
- /* Return index of a valid command, -1 if none. */
- int
- comind(const struct cmd *commands, const char *com)
- {
- int i;
-
- for (i = 0; commands[i].name; i++)
- if (!strcasecmp(commands[i].name, com))
- return i;
- return -1;
- }
-
- /* Reset the variables to default values. */
- void
- defaults(void)
- {
- char *tmp;
-
- #ifdef DEBUG
- opt.debug = 0;
- #endif
- opt.verbose = -1;
- opt.quiet = 0;
-
- opt.kill_longer = 0;
- opt.ignore_length = 0;
- opt.lfilename = NULL;
- opt.input_filename = NULL;
- opt.dirstruct = 0;
- opt.no_dirstruct = 0;
- opt.dir_prefix = nstrdup(DEFAULT_DIRPREFIX);
-
- opt.ntry = DEFAULT_NUMBER_OF_TRIES;
- opt.recursive = 0;
- opt.maxreclevel = DEFAULT_MAXRECLEVEL;
- opt.spanhost = 0;
- opt.relative_only = 0;
- opt.no_parent = 0;
- opt.accepts = opt.rejects = NULL;
- opt.includes = opt.excludes = NULL;
-
- opt.simple_check = 0;
- opt.dirmode = DEFAULT_DIRMODE;
- opt.add_hostdir = 1;
- opt.noclobber = 0;
-
- opt.follow_ftp = 0;
- opt.retr_symlinks = 0;
- opt.always_rest = 0;
- opt.ftp_acc = nstrdup(DEFAULT_FTP_ACCT);
- opt.ftp_pass = nstrdup(ftp_getaddress());
- opt.ftp_glob = 1;
- opt.ftp_pasv = 0;
- opt.htmlify = 1;
-
- opt.http_user = NULL;
- opt.http_passwd = NULL;
- opt.user_header = NULL;
-
- opt.useragent = NULL;
- opt.output_document = NULL;
-
- opt.use_proxy = 1;
- opt.http_proxy = opt.ftp_proxy = NULL;
- opt.no_proxy = NULL;
- tmp = getenv("no_proxy");
- if (tmp)
- opt.no_proxy = sepstring(tmp);
- opt.proxy_cache = 1;
- opt.base_href = NULL;
-
- #ifdef HAVE_SELECT
- opt.timeout = DEFAULT_TIMEOUT;
- #endif
- opt.wait = 0;
-
- opt.use_robots = 1;
-
- opt.quota = 0;
- opt.downloaded = 0;
- opt.numurls = 0;
-
- opt.server_response = 0;
- opt.save_headers = 0;
- opt.timestamping = 0;
- opt.remove_listing = 1;
- opt.delete_after = 0;
-
- opt.backups = 0;
- opt.convert_links = 0;
-
- opt.dot_bytes = DOT_BYTES;
- opt.dot_spacing = DOT_SPACING;
- opt.dots_in_line = DOTS_IN_LINE;
- }
-
- /* Return the user's home directory (strdup-ed), or NULL if none found. */
- char *
- home_dir(void)
- {
- char *home;
- #ifdef WINDOWS
- /* TODO - maybe I should grab home_dir from registry,
- but the best that I could get from there is users
- Start menu. It sucks! */
- home = getenv("HOME");
- return home ? nstrdup(home) : NULL;
-
- #else /* Unix or stuff */
- struct passwd *pwd;
-
- home = getenv("HOME");
- /* If HOME is not defined, try getting it from the password file. */
- if (!home)
- {
- pwd = getpwuid(getuid());
- if (!pwd || !pwd->pw_dir)
- return NULL;
- home = pwd->pw_dir;
- }
- if (home)
- return nstrdup(home);
- return NULL;
- #endif /* WINDOWS */
- }
-
- /* Return the path to the user's .wgetrc. */
- char *
- init_path(void)
- {
- char *env, *home, *path;
- struct stat buf;
- int err;
-
- /* Try the environment. */
- if ((env = getenv("WGETRC")))
- {
- path = nstrdup(env);
- err = stat(path, &buf);
- if (err == 0)
- return path;
- free(path);
- fprintf(stderr, "Cannot load .wgetrc.\n");
- exit(1);
- }
- /* If that failed, try $HOME/.wgetrc. */
- home = home_dir();
- if (!home)
- return NULL;
- path = (char *)nmalloc(strlen(home) + 1 + strlen(".wgetrc") + 1);
- sprintf(path, "%s/.wgetrc", home);
- free(home);
- err = stat(path, &buf);
- if (err == -1)
- {
- free(path);
- return NULL;
- }
- return path;
- }
-
- /* Initialize variables from a wgetrc file */
- void
- run_wgetrc(const char *path)
- {
- char *com, *val;
- FILE *fp;
- char *line;
- int stat, ln, length;
-
- fp = fopen(path, "r");
- if (!fp)
- {
- fprintf(stderr, "Cannot read %s (%s).\n", path, mystrerror(errno));
- return;
- }
- /* Reset line number. */
- ln = 1;
- /* While there are lines in the file: */
- while ((line = read_whole_line(fp)))
- {
- length = strlen(line);
- if (length && line[length - 1] == '\r')
- line[length - 1] = '\0';
- /* Parse the line. */
- stat = parse_line((unsigned char *)line,
- (unsigned char **)&com, (unsigned char **)&val);
- free(line);
- /* If everything is OK, set the value. */
- if (stat == 1)
- {
- if (!setval(com, val))
- fprintf(stderr, "Error in %s at line %d.\n", path, ln);
- free(com);
- free(val);
- }
- else if (stat == 0)
- fprintf(stderr, "Error in %s at line %d.\n", path, ln);
- ++ln;
- }
- fclose(fp);
- }
-
- /* Initialize the defaults and run the system wgetrc and user's own
- wgetrc. Parse ~/.netrc. */
- void
- initialize(void)
- {
- char *path;
- struct stat buf;
- int err;
- char *home;
-
- /* Load defaults. */
- defaults();
-
- /* If SYSTEM_WGETRC is defined, use it. */
- #ifdef SYSTEM_WGETRC
- err = stat(SYSTEM_WGETRC, &buf);
- if (err != -1) /* File exists */
- run_wgetrc(SYSTEM_WGETRC);
- #endif
- /* Override it with your own, if one exists. */
- path = init_path();
- if (path)
- {
- run_wgetrc(path);
- free(path);
- }
- /* Find ~/.netrc. */
- netrc_list = NULL;
- home = home_dir();
- if (home)
- {
- path = nmalloc(strlen(home) + 1 + strlen(NETRC_FILE_NAME) + 1);
- sprintf(path, "%s/%s", home, NETRC_FILE_NAME);
- free(home);
- err = stat(path, &buf);
- if (err == 0)
- netrc_list = parse_netrc(path);
- free(path);
- }
- }
-
- /* Parse the line pointed by line, with the syntax:
- <sp>* command <sp>* = <sp>* value <newline>
- Uses malloc to allocate space for command and value.
- If the line is invalid, data is freed and 0 is returned.
-
- Return values:
- 1 - success
- 0 - failure
- -1 - comment */
- int
- parse_line(const unsigned char *line, unsigned char **com, unsigned char **val)
- {
- int i, j;
-
- /* Skip spaces. */
- for (i = 0; line[i] == ' ' || line[i] == '\t'; i++);
-
- /* Skip empty or hashed lines. */
- if (!line[i] || line[i] == '\n' || line[i] == '#')
- return -1;
-
- /* Allocate command. */
- *com = (unsigned char *)nmalloc(1);
- (*com)[0] = '\0';
- for (j = 0; (isalpha(line[i]) || line[i] == '_' || line[i] == '-'); i++)
- {
- if (line[i] == '_' || line[i] == '-')
- continue;
- *com = (unsigned char *)nrealloc(*com, j + 2);
- (*com)[j] = tolower(line[i]);
- (*com)[j + 1] = '\0';
- ++j;
- }
- /* The next char should be space or '='. */
- if (!isspace(line[i]) && (line[i] != '='))
- {
- free(*com);
- return 0;
- }
- /* If the command is invalid, exit now. */
- if (comind(commands, (char *)*com) == NONE)
- {
- free(*com);
- return 0;
- }
- /* Skip spaces before '='. */
- for (; isspace(line[i]); i++);
- /* If '=' not found, bail out. */
- if (line[i] != '=')
- {
- free(com);
- return 0;
- }
- /* Skip spaces after '='. */
- for (++i; isspace(line[i]); i++);
- /* Get the ending position. */
- for (j = i; line[i] && line[i] != '\n'; i++);
- /* Allocate *val, and copy from line. */
- (*val) = (unsigned char *)nmalloc(i - j + 1);
- strncpy((char *)*val, (char *)line + j, i - j);
- (*val)[i - j] = '\0';
- return 1;
- }
-
- /* Do the job for each line. No fatals -- error signal prints a
- warning and resets to default value. All error messages are
- printed to stderr, *not* to opt.lfile, since opt.lfile wasn't even
- generated yet. */
- int
- setval(const char *com, const char *val)
- {
- int flag, mirror;
- int i, ind; /* To be used for various loops. */
- const char *p; /* Likewise. */
-
- if (!com || !val)
- return 0;
- ind = comind(commands, com);
- if (ind == -1)
- {
- #ifdef DEBUG
- fprintf(stderr, "Unknown command `%s', value `%s'.\n", com, val);
- #endif
- return 0;
- }
- switch (commands[ind].what_to_do)
- {
- case CONOFF:
- return setonoff((int *)commands[ind].varp, com, val);
- break;
- case CNUM:
- return setnum((int *)commands[ind].varp, com, val, 0);
- break;
- case CNUMINF:
- return setnum((int *)commands[ind].varp, com, val, SINF);
- break;
- case CSTR:
- if (*(char **)commands[ind].varp)
- free(*(char **)commands[ind].varp);
- *(char **)commands[ind].varp = (char *)nstrdup(val);
- break;
- case CVEC:
- if (*val)
- *(char ***)commands[ind].varp = merge_vecs(*(char ***)commands[ind].varp,
- sepstring(val));
- else
- {
- free_vec(*(char ***)commands[ind].varp);
- *(char ***)commands[ind].varp = NULL;
- }
- break;
- case CVECDIR:
- if (*val)
- {
- /* Strip the trailing slashes from directories. */
- char **t, **seps;
- int len;
-
- seps = sepstring(val);
- for (t = seps; t && *t; t++)
- {
- len = strlen(*t);
- /* Skip degenerate case of root directory. */
- if (len > 1)
- {
- if ((*t)[len - 1] == '/')
- (*t)[len - 1] = '\0';
- }
- }
- *(char ***)commands[ind].varp =
- merge_vecs(*(char ***)commands[ind].varp, seps);
- }
- else
- {
- free_vec(*(char ***)commands[ind].varp);
- *(char ***)commands[ind].varp = NULL;
- }
- break;
- case CBYT:
- return setbytes((long *)commands[ind].varp, com, val);
- break;
- case CSPEC:
- switch(commands[ind].id)
- {
- case DEBUG_:
- #ifdef DEBUG
- return setonoff(&opt.debug, com, val);
- #else
- fprintf(stderr, "%s: debug support not loaded.\n", com);
- return 0;
- #endif
- break;
- case DIRMODE:
- flag = getperms(val);
- if (flag == -1)
- {
- fprintf(stderr, "%s: Invalid mode specification `%s'.\n",
- com, val);
- return 0;
- }
- opt.dirmode = DEFAULT_DIRMODE;
- break;
- case DIRSTRUCT:
- if (!setonoff(&opt.dirstruct, com, val))
- return 0;
- /* Since dirstruct behaviour is explicitly changed,
- no_dirstruct must be affected inversely. */
- if (opt.dirstruct)
- opt.no_dirstruct = 0;
- else
- opt.no_dirstruct = 1;
- break;
- case DOTSTYLE:
- /* Retrieval styles. */
- if (!strcasecmp(val, "default"))
- {
- /* Default style: 1K dots, 10 dots in a cluster, 50
- dots in a line. */
- opt.dot_bytes = DOT_BYTES;
- opt.dot_spacing = DOT_SPACING;
- opt.dots_in_line = DOTS_IN_LINE;
- }
- else if (!strcasecmp(val, "binary"))
- {
- /* "Binary" retrieval: 8K dots, 16 dots in a cluster,
- 64 dots (512K) in a line. */
- opt.dot_bytes = 8192;
- opt.dot_spacing = 16;
- opt.dots_in_line = 64;
- }
- 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, "micro"))
- {
- /* "Micro" retrieval, for retrieving very small files;
- 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: Invalid specification `%s'.\n", com, val);
- return 0;
- }
- break;
- case HEADER:
- if (!*val)
- {
- /* Empty header means to reset headers. */
- if (opt.user_header)
- {
- free(opt.user_header);
- opt.user_header = NULL;
- }
- }
- else
- {
- /* Check for sanity of the header value. */
- flag = 0;
- for (p = val; *p && *p != ':' && !isspace(*p); p++);
- /* The header MUST contain ':' preceded by at least one
- non-space character. */
- if (*p != ':' || p == val)
- flag = 1;
- /* The header MUST NOT contain newlines. */
- if (!flag)
- if (strchr(val, '\n'))
- flag = 1;
- if (flag)
- {
- fprintf(stderr, "%s: Invalid specification `%s'.\n", com, val);
- return 0;
- }
- i = opt.user_header ? strlen(opt.user_header) : 0;
- opt.user_header = (char *)nrealloc(opt.user_header,
- i + strlen(val) + 2 + 1);
- strcpy(opt.user_header + i, val);
- i += strlen(val);
- opt.user_header[i++] = '\r';
- opt.user_header[i++] = '\n';
- opt.user_header[i] = '\0';
- }
- break;
- case HTMLIFY:
- flag = setonoff(&opt.htmlify, com, val);
- if (flag && !opt.htmlify)
- opt.remove_listing = 0;
- return flag;
- break;
- case MIRROR:
- if (!setonoff(&mirror, com, val))
- return 0;
- if (mirror)
- {
- opt.recursive = 1;
- if (!opt.no_dirstruct)
- opt.dirstruct = 1;
- opt.timestamping = 1;
- opt.maxreclevel = 0;
- opt.remove_listing = 0;
- }
- break;
- case OUTPUTDOCUMENT:
- if (opt.output_document)
- free(opt.output_document);
- opt.output_document = nstrdup(val);
- opt.ntry = 1;
- if (ISHYPHEN(opt.output_document))
- opt.quiet = 1;
- break;
- case RECURSIVE:
- if (!setonoff(&opt.recursive, com, val))
- return 0;
- else
- {
- if (opt.recursive && !opt.no_dirstruct)
- opt.dirstruct = 1;
- }
- break;
- case TIMEOUT:
- #ifdef HAVE_SELECT
- return setnum(&opt.timeout, com, val, SINF);
- #else
- fprintf(stderr, "Unable to set timeout without select().\n");
- #endif
- break;
- default:
- assert(0);
- }
- break;
- default:
- assert(0);
- }
- return 1;
- }
-
- /* Return 0 if off, 1 if on, -1 if error. */
- int
- onoff(const char *val)
- {
- if (strcasecmp(val, "on") == 0 || strcmp(val, "1") == 0)
- return 1;
- else if (strcasecmp(val, "off") == 0 || strcmp(val, "0") == 0)
- return 0;
- else
- return -1;
- }
-
- /* Set the integer value pointed to by what on value represented in
- string val. String com is used only for error messages. */
- int
- setonoff(int *what, const char *com, const char *val)
- {
- int flag;
-
- flag = onoff(val);
- if (flag == -1)
- {
- fprintf(stderr, "%s: Please specify on or off.\n", com);
- return 0;
- }
- *what = flag;
- return 1;
- }
-
- /* Similar to setonoff, but converts numbers. With incorrect
- specification, the number remains unchanged. With flags set to
- SINF, uses "inf" for meaning zero. */
- int
- setnum(int *what, const char *com, const char *val, int flags)
- {
- int res;
-
- if (flags == SINF && !strcasecmp(val, "inf"))
- {
- *what = 0;
- return 1;
- }
- res = myatoi(val);
- if (res == -1)
- {
- fprintf(stderr, "%s: Invalid specification `%s'.\n", com, val);
- return 0;
- }
- *what = res;
- return 1;
- }
-
- /* Return the int value of a positive integer written in a string,
- or -1 if an error was encountered */
- int
- myatoi(const char *s)
- {
- int res;
- const char *orig;
-
- orig = s;
- for (res = 0; *s && isdigit(*s); s++)
- {
- res *= 10;
- res += *s - '0';
- }
- if (*s || orig == s)
- return -1;
- else
- return res;
- }
-
- /* Return the decimal representation of octal mode three-digit
- permission string, or -1 if incorrect. */
- int
- getperms(const char *s)
- {
- if (strlen(s) != 3 || !ISODIGIT(s[0]) || !ISODIGIT(s[1]) || !ISODIGIT(s[2]))
- return -1;
- return (s[2] - '0') + 8 * (s[1] - '0') + 64 * (s[0] - '0');
- }
-
- /* Free the memory allocated by global variables. */
- void
- cleanup(void)
- {
- recursive_retrieve(NULL, NULL, RCLEANUP);
- clean_hosts();
- free_netrc(netrc_list);
- if (opt.dfp)
- fclose(opt.dfp);
- if (opt.lfilename)
- free(opt.lfilename);
- free(opt.dir_prefix);
- if (opt.input_filename)
- free(opt.input_filename);
- if (opt.output_document)
- free(opt.output_document);
- free_vec(opt.accepts);
- free_vec(opt.rejects);
- free_vec(opt.excludes);
- free_vec(opt.includes);
- free_vec(opt.domains);
- free(opt.ftp_acc);
- free(opt.ftp_pass);
- if (opt.ftp_proxy)
- free(opt.ftp_proxy);
- if (opt.http_proxy)
- free(opt.http_proxy);
- free_vec(opt.no_proxy);
- if (opt.useragent)
- free(opt.useragent);
- if (opt.http_user)
- free(opt.http_user);
- if (opt.http_passwd)
- free(opt.http_passwd);
- if (opt.user_header)
- free(opt.user_header);
- }
-
- /* Sets the value stored in string val to a long int out, allowing
- several postfices, with the following syntax (regexp):
-
- [0-9]+ -> bytes
- [0-9]+[kK] -> bytes * 1024
- [0-9]+[mM] -> bytes * 1024 * 1024
- inf -> 0
-
- Anything else is flagged as incorrect, and *out is unchanged. */
- int
- setbytes(long *out, const char *com, const char *val)
- {
- long result;
- const char *p;
-
- result = 0;
- p = val;
- /* Check for "inf". */
- if (p[0] == 'i' && p[1] == 'n' && p[2] == 'f' && p[3] == '\0')
- {
- *out = 0L;
- return 1;
- }
- /* Search for digits and construct result. */
- for (; *p && isdigit(*p); p++)
- {
- result *= 10;
- result += *p - '0';
- }
- /* If no digits were found, or more than one character is following
- them, bail out. */
- if (p == val || (*p != '\0' && *(p + 1) != '\0'))
- {
- printf("%s: Invalid specification `%s'\n", com, val);
- return 0;
- }
- /* Search for a designator. */
- switch(*p)
- {
- case 'K': case 'k':
- /* Kilobytes */
- result *= 1024;
- break;
- case 'M': case 'm':
- /* Megabytes */
- result *= (long)1024 * 1024;
- break;
- case '\0':
- /* Never mind. */
- break;
- default:
- printf("%s: Invalid specification `%s'\n", com, val);
- return 0;
- }
- *out = result;
- return 1;
- }
-