1 /* Reading/parsing the initialization file.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 This file is part of Wget.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <sys/types.h>
38 # include <sys/socket.h>
39 # include <netinet/in.h>
40 # include <arpa/inet.h>
58 /* We want tilde expansion enabled only when reading `.wgetrc' lines;
59 otherwise, it will be performed by the shell. This variable will
60 be set by the wgetrc-reading function. */
62 static int enable_tilde_expansion;
65 #define CMD_DECLARE(func) static int func \
66 PARAMS ((const char *, const char *, void *))
68 CMD_DECLARE (cmd_address);
69 CMD_DECLARE (cmd_boolean);
70 CMD_DECLARE (cmd_bytes);
71 CMD_DECLARE (cmd_directory_vector);
72 CMD_DECLARE (cmd_lockable_boolean);
73 CMD_DECLARE (cmd_number);
74 CMD_DECLARE (cmd_number_inf);
75 CMD_DECLARE (cmd_string);
76 CMD_DECLARE (cmd_file);
77 CMD_DECLARE (cmd_time);
78 CMD_DECLARE (cmd_vector);
80 CMD_DECLARE (cmd_spec_dirstruct);
81 CMD_DECLARE (cmd_spec_dotstyle);
82 CMD_DECLARE (cmd_spec_header);
83 CMD_DECLARE (cmd_spec_htmlify);
84 CMD_DECLARE (cmd_spec_mirror);
85 CMD_DECLARE (cmd_spec_recursive);
86 CMD_DECLARE (cmd_spec_useragent);
88 /* List of recognized commands, each consisting of name, closure and function.
89 When adding a new command, simply add it to the list, but be sure to keep the
90 list sorted alphabetically, as comind() depends on it. Also, be sure to add
91 any entries that allocate memory (e.g. cmd_string and cmd_vector guys) to the
92 cleanup() function below. */
96 int (*action) PARAMS ((const char *, const char *, void *));
98 { "accept", &opt.accepts, cmd_vector },
99 { "addhostdir", &opt.add_hostdir, cmd_boolean },
100 { "alwaysrest", &opt.always_rest, cmd_boolean }, /* deprecated */
101 { "background", &opt.background, cmd_boolean },
102 { "backupconverted", &opt.backup_converted, cmd_boolean },
103 { "backups", &opt.backups, cmd_number },
104 { "base", &opt.base_href, cmd_string },
105 { "bindaddress", &opt.bind_address, cmd_address },
106 { "cache", &opt.proxy_cache, cmd_boolean },
107 { "continue", &opt.always_rest, cmd_boolean },
108 { "convertlinks", &opt.convert_links, cmd_boolean },
109 { "cookies", &opt.cookies, cmd_boolean },
110 { "cutdirs", &opt.cut_dirs, cmd_number },
112 { "debug", &opt.debug, cmd_boolean },
114 { "deleteafter", &opt.delete_after, cmd_boolean },
115 { "dirprefix", &opt.dir_prefix, cmd_file },
116 { "dirstruct", NULL, cmd_spec_dirstruct },
117 { "domains", &opt.domains, cmd_vector },
118 { "dotbytes", &opt.dot_bytes, cmd_bytes },
119 { "dotsinline", &opt.dots_in_line, cmd_number },
120 { "dotspacing", &opt.dot_spacing, cmd_number },
121 { "dotstyle", NULL, cmd_spec_dotstyle },
122 { "excludedirectories", &opt.excludes, cmd_directory_vector },
123 { "excludedomains", &opt.exclude_domains, cmd_vector },
124 { "followftp", &opt.follow_ftp, cmd_boolean },
125 { "followtags", &opt.follow_tags, cmd_vector },
126 { "forcehtml", &opt.force_html, cmd_boolean },
127 { "ftpproxy", &opt.ftp_proxy, cmd_string },
128 { "glob", &opt.ftp_glob, cmd_boolean },
129 { "header", NULL, cmd_spec_header },
130 { "htmlextension", &opt.html_extension, cmd_boolean },
131 { "htmlify", NULL, cmd_spec_htmlify },
132 { "httpkeepalive", &opt.http_keep_alive, cmd_boolean },
133 { "httppasswd", &opt.http_passwd, cmd_string },
134 { "httpproxy", &opt.http_proxy, cmd_string },
135 { "httpsproxy", &opt.https_proxy, cmd_string },
136 { "httpuser", &opt.http_user, cmd_string },
137 { "ignorelength", &opt.ignore_length, cmd_boolean },
138 { "ignoretags", &opt.ignore_tags, cmd_vector },
139 { "includedirectories", &opt.includes, cmd_directory_vector },
140 { "input", &opt.input_filename, cmd_file },
141 { "killlonger", &opt.kill_longer, cmd_boolean },
142 { "loadcookies", &opt.cookies_input, cmd_file },
143 { "logfile", &opt.lfilename, cmd_file },
144 { "login", &opt.ftp_acc, cmd_string },
145 { "mirror", NULL, cmd_spec_mirror },
146 { "netrc", &opt.netrc, cmd_boolean },
147 { "noclobber", &opt.noclobber, cmd_boolean },
148 { "noparent", &opt.no_parent, cmd_boolean },
149 { "noproxy", &opt.no_proxy, cmd_vector },
150 { "numtries", &opt.ntry, cmd_number_inf },/* deprecated*/
151 { "outputdocument", &opt.output_document, cmd_file },
152 { "pagerequisites", &opt.page_requisites, cmd_boolean },
153 { "passiveftp", &opt.ftp_pasv, cmd_lockable_boolean },
154 { "passwd", &opt.ftp_pass, cmd_string },
155 { "proxypasswd", &opt.proxy_passwd, cmd_string },
156 { "proxyuser", &opt.proxy_user, cmd_string },
157 { "quiet", &opt.quiet, cmd_boolean },
158 { "quota", &opt.quota, cmd_bytes },
159 { "reclevel", &opt.reclevel, cmd_number_inf },
160 { "recursive", NULL, cmd_spec_recursive },
161 { "referer", &opt.referer, cmd_string },
162 { "reject", &opt.rejects, cmd_vector },
163 { "relativeonly", &opt.relative_only, cmd_boolean },
164 { "removelisting", &opt.remove_listing, cmd_boolean },
165 { "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
166 { "robots", &opt.use_robots, cmd_boolean },
167 { "savecookies", &opt.cookies_output, cmd_file },
168 { "saveheaders", &opt.save_headers, cmd_boolean },
169 { "serverresponse", &opt.server_response, cmd_boolean },
170 { "simplehostcheck", &opt.simple_check, cmd_boolean },
171 { "spanhosts", &opt.spanhost, cmd_boolean },
172 { "spider", &opt.spider, cmd_boolean },
174 { "sslcertfile", &opt.sslcertfile, cmd_file },
175 { "sslcertkey", &opt.sslcertkey, cmd_file },
176 #endif /* HAVE_SSL */
177 { "timeout", &opt.timeout, cmd_time },
178 { "timestamping", &opt.timestamping, cmd_boolean },
179 { "tries", &opt.ntry, cmd_number_inf },
180 { "useproxy", &opt.use_proxy, cmd_boolean },
181 { "useragent", NULL, cmd_spec_useragent },
182 { "verbose", &opt.verbose, cmd_boolean },
183 { "wait", &opt.wait, cmd_time },
184 { "waitretry", &opt.waitretry, cmd_time }
187 /* Return index of COM if it is a valid command, or -1 otherwise. COM
188 is looked up in `commands' using binary search algorithm. */
190 comind (const char *com)
192 int min = 0, max = ARRAY_SIZE (commands) - 1;
196 int i = (min + max) / 2;
197 int cmp = strcasecmp (com, commands[i].name);
209 /* Reset the variables to default values. */
215 /* Most of the default values are 0. Just reset everything, and
216 fill in the non-zero values. Note that initializing pointers to
217 NULL this way is technically illegal, but porting Wget to a
218 machine where NULL is not all-zero bit pattern will be the least
219 of the implementors' worries. */
220 memset (&opt, 0, sizeof (opt));
225 opt.dir_prefix = xstrdup (".");
229 opt.ftp_acc = xstrdup ("anonymous");
230 /*opt.ftp_pass = xstrdup (ftp_getaddress ());*/
234 opt.http_keep_alive = 1;
236 tmp = getenv ("no_proxy");
238 opt.no_proxy = sepstring (tmp);
246 opt.remove_listing = 1;
248 opt.dot_bytes = 1024;
249 opt.dot_spacing = 10;
250 opt.dots_in_line = 50;
253 /* Return the user's home directory (strdup-ed), or NULL if none is
258 char *home = getenv ("HOME");
263 /* If HOME is not defined, try getting it from the password
265 struct passwd *pwd = getpwuid (getuid ());
266 if (!pwd || !pwd->pw_dir)
271 /* #### Maybe I should grab home_dir from registry, but the best
272 that I could get from there is user's Start menu. It sucks! */
276 return home ? xstrdup (home) : NULL;
279 /* Return the path to the user's .wgetrc. This is either the value of
280 `WGETRC' environment variable, or `$HOME/.wgetrc'.
282 If the `WGETRC' variable exists but the file does not exist, the
283 function will exit(). */
285 wgetrc_file_name (void)
290 /* Try the environment. */
291 env = getenv ("WGETRC");
294 if (!file_exists_p (env))
296 fprintf (stderr, "%s: %s: %s.\n", exec_name, file, strerror (errno));
299 return xstrdup (env);
303 /* If that failed, try $HOME/.wgetrc. */
307 file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
308 sprintf (file, "%s/.wgetrc", home);
312 /* Under Windows, "home" is (for the purposes of this function) the
313 directory where `wget.exe' resides, and `wget.ini' will be used
314 as file name. SYSTEM_WGETRC should not be defined under WINDOWS.
316 It is not as trivial as I assumed, because on 95 argv[0] is full
317 path, but on NT you get what you typed in command line. --dbudor */
321 file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
322 sprintf (file, "%swget.ini", home);
328 if (!file_exists_p (file))
336 /* Initialize variables from a wgetrc file */
338 run_wgetrc (const char *file)
344 fp = fopen (file, "rb");
347 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
348 file, strerror (errno));
351 enable_tilde_expansion = 1;
353 while ((line = read_whole_line (fp)))
358 /* Parse the line. */
359 status = parse_line (line, &com, &val);
361 /* If everything is OK, set the value. */
364 if (!setval (com, val))
365 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
370 else if (status == 0)
371 fprintf (stderr, _("%s: Error in %s at line %d.\n"), exec_name,
375 enable_tilde_expansion = 0;
379 /* Initialize the defaults and run the system wgetrc and user's own
386 /* Load the hard-coded defaults. */
389 /* If SYSTEM_WGETRC is defined, use it. */
391 if (file_exists_p (SYSTEM_WGETRC))
392 run_wgetrc (SYSTEM_WGETRC);
394 /* Override it with your own, if one exists. */
395 file = wgetrc_file_name ();
398 /* #### We should somehow canonicalize `file' and SYSTEM_WGETRC,
401 if (!strcmp (file, SYSTEM_WGETRC))
403 fprintf (stderr, _("\
404 %s: Warning: Both system and user wgetrc point to `%s'.\n"),
414 /* Parse the line pointed by line, with the syntax:
415 <sp>* command <sp>* = <sp>* value <newline>
416 Uses malloc to allocate space for command and value.
417 If the line is invalid, data is freed and 0 is returned.
424 parse_line (const char *line, char **com, char **val)
426 const char *p = line;
427 const char *orig_comptr, *end;
430 /* Skip whitespace. */
431 while (*p && ISSPACE (*p))
434 /* Don't process empty lines. */
435 if (!*p || *p == '#')
438 for (orig_comptr = p; ISALPHA (*p) || *p == '_' || *p == '-'; p++)
440 /* The next char should be space or '='. */
441 if (!ISSPACE (*p) && (*p != '='))
443 /* Here we cannot use strdupdelim() as we normally would because we
444 want to skip the `-' and `_' characters in the input string. */
445 *com = (char *)xmalloc (p - orig_comptr + 1);
446 for (new_comptr = *com; orig_comptr < p; orig_comptr++)
448 if (*orig_comptr == '_' || *orig_comptr == '-')
450 *new_comptr++ = *orig_comptr;
453 /* If the command is invalid, exit now. */
454 if (comind (*com) == -1)
460 /* Skip spaces before '='. */
461 for (; ISSPACE (*p); p++);
462 /* If '=' not found, bail out. */
468 /* Skip spaces after '='. */
469 for (++p; ISSPACE (*p); p++);
470 /* Get the ending position for VAL by starting with the end of the
471 line and skipping whitespace. */
472 end = line + strlen (line) - 1;
473 while (end > p && ISSPACE (*end))
475 *val = strdupdelim (p, end + 1);
479 /* Set COM to VAL. This is the meat behind processing `.wgetrc'. No
480 fatals -- error signal prints a warning and resets to default
481 value. All error messages are printed to stderr, *not* to
482 opt.lfile, since opt.lfile wasn't even generated yet. */
484 setval (const char *com, const char *val)
493 /* #### Should I just abort()? */
495 fprintf (stderr, _("%s: BUG: unknown command `%s', value `%s'.\n"),
496 exec_name, com, val);
500 return ((*commands[ind].action) (com, val, commands[ind].closure));
503 /* Generic helper functions, for use with `commands'. */
505 static int myatoi PARAMS ((const char *s));
507 /* Interpret VAL as an Internet address (a hostname or a dotted-quad
508 IP address), and write it (in network order) to a malloc-allocated
509 address. That address gets stored to the memory pointed to by
510 CLOSURE. COM is ignored, except for error messages.
512 #### IMHO it's a mistake to do this kind of work so early in the
513 process (before any download even started!) opt.bind_address
514 should simply remember the provided value as a string. Another
515 function should do the lookup, when needed, and cache the
518 cmd_address (const char *com, const char *val, void *closure)
520 struct sockaddr_in sin;
521 struct sockaddr_in **target = (struct sockaddr_in **)closure;
523 if (!store_hostaddress ((unsigned char *)&sin.sin_addr, val))
525 fprintf (stderr, _("%s: %s: Cannot convert `%s' to an IP address.\n"),
526 exec_name, com, val);
530 sin.sin_family = AF_INET;
533 FREE_MAYBE (*target);
535 *target = xmalloc (sizeof (sin));
536 memcpy (*target, &sin, sizeof (sin));
541 /* Store the boolean value from VAL to CLOSURE. COM is ignored,
542 except for error messages. */
544 cmd_boolean (const char *com, const char *val, void *closure)
548 if (!strcasecmp (val, "on")
549 || (*val == '1' && !*(val + 1)))
551 else if (!strcasecmp (val, "off")
552 || (*val == '0' && !*(val + 1)))
556 fprintf (stderr, _("%s: %s: Please specify on or off.\n"),
561 *(int *)closure = bool_value;
565 /* Store the lockable_boolean {2, 1, 0, -1} value from VAL to CLOSURE. COM is
566 ignored, except for error messages. Values 2 and -1 indicate that once
567 defined, the value may not be changed by successive wgetrc files or
568 command-line arguments.
570 Values: 2 - Enable a particular option for good ("always")
571 1 - Enable an option ("on")
572 0 - Disable an option ("off")
573 -1 - Disable an option for good ("never") */
575 cmd_lockable_boolean (const char *com, const char *val, void *closure)
577 int lockable_boolean_value;
580 * If a config file said "always" or "never", don't allow command line
581 * arguments to override the config file.
583 if (*(int *)closure == -1 || *(int *)closure == 2)
586 if (!strcasecmp (val, "always")
587 || (*val == '2' && !*(val + 1)))
588 lockable_boolean_value = 2;
589 else if (!strcasecmp (val, "on")
590 || (*val == '1' && !*(val + 1)))
591 lockable_boolean_value = 1;
592 else if (!strcasecmp (val, "off")
593 || (*val == '0' && !*(val + 1)))
594 lockable_boolean_value = 0;
595 else if (!strcasecmp (val, "never")
596 || (*val == '-' && *(val + 1) == '1' && !*(val + 2)))
597 lockable_boolean_value = -1;
600 fprintf (stderr, _("%s: %s: Please specify always, on, off, "
606 *(int *)closure = lockable_boolean_value;
610 /* Set the non-negative integer value from VAL to CLOSURE. With
611 incorrect specification, the number remains unchanged. */
613 cmd_number (const char *com, const char *val, void *closure)
615 int num = myatoi (val);
619 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
620 exec_name, com, val);
623 *(int *)closure = num;
627 /* Similar to cmd_number(), only accepts `inf' as a synonym for 0. */
629 cmd_number_inf (const char *com, const char *val, void *closure)
631 if (!strcasecmp (val, "inf"))
636 return cmd_number (com, val, closure);
639 /* Copy (strdup) the string at COM to a new location and place a
640 pointer to *CLOSURE. */
642 cmd_string (const char *com, const char *val, void *closure)
644 char **pstring = (char **)closure;
646 FREE_MAYBE (*pstring);
647 *pstring = xstrdup (val);
651 /* Like the above, but handles tilde-expansion when reading a user's
652 `.wgetrc'. In that case, and if VAL begins with `~', the tilde
653 gets expanded to the user's home directory. */
655 cmd_file (const char *com, const char *val, void *closure)
657 char **pstring = (char **)closure;
659 FREE_MAYBE (*pstring);
660 if (!enable_tilde_expansion || !(*val == '~' && *(val + 1) == '/'))
663 *pstring = xstrdup (val);
669 char *home = home_dir ();
673 homelen = strlen (home);
674 while (homelen && home[homelen - 1] == '/')
675 home[--homelen] = '\0';
677 /* Skip the leading "~/". */
678 for (++val; *val == '/'; val++)
681 result = xmalloc (homelen + 1 + strlen (val));
682 memcpy (result, home, homelen);
683 result[homelen] = '/';
684 strcpy (result + homelen + 1, val);
691 /* Merge the vector (array of strings separated with `,') in COM with
692 the vector (NULL-terminated array of strings) pointed to by
695 cmd_vector (const char *com, const char *val, void *closure)
697 char ***pvec = (char ***)closure;
700 *pvec = merge_vecs (*pvec, sepstring (val));
710 cmd_directory_vector (const char *com, const char *val, void *closure)
712 char ***pvec = (char ***)closure;
716 /* Strip the trailing slashes from directories. */
719 seps = sepstring (val);
720 for (t = seps; t && *t; t++)
722 int len = strlen (*t);
723 /* Skip degenerate case of root directory. */
726 if ((*t)[len - 1] == '/')
727 (*t)[len - 1] = '\0';
730 *pvec = merge_vecs (*pvec, seps);
740 /* Set the value stored in VAL to CLOSURE (which should point to a
741 long int), allowing several postfixes, with the following syntax
745 [0-9]+[kK] -> bytes * 1024
746 [0-9]+[mM] -> bytes * 1024 * 1024
749 Anything else is flagged as incorrect, and CLOSURE is unchanged. */
751 cmd_bytes (const char *com, const char *val, void *closure)
754 long *out = (long *)closure;
759 /* Check for "inf". */
760 if (p[0] == 'i' && p[1] == 'n' && p[2] == 'f' && p[3] == '\0')
765 /* Search for digits and construct result. */
766 for (; *p && ISDIGIT (*p); p++)
767 result = (10 * result) + (*p - '0');
768 /* If no digits were found, or more than one character is following
770 if (p == val || (*p != '\0' && *(p + 1) != '\0'))
772 printf (_("%s: Invalid specification `%s'\n"), com, val);
775 /* Search for a designator. */
776 switch (TOLOWER (*p))
787 result *= (long)1024 * 1024;
791 result *= (long)1024 * 1024 * 1024;
794 printf (_("%s: Invalid specification `%s'\n"), com, val);
801 /* Store the value of VAL to *OUT, allowing suffixes for minutes and
804 cmd_time (const char *com, const char *val, void *closure)
809 /* Search for digits and construct result. */
810 for (; *p && ISDIGIT (*p); p++)
811 result = (10 * result) + (*p - '0');
812 /* If no digits were found, or more than one character is following
814 if (p == val || (*p != '\0' && *(p + 1) != '\0'))
816 printf (_("%s: Invalid specification `%s'\n"), com, val);
819 /* Search for a suffix. */
820 switch (TOLOWER (*p))
834 /* Days (overflow on 16bit machines) */
842 printf (_("%s: Invalid specification `%s'\n"), com, val);
845 *(long *)closure = result;
849 /* Specialized helper functions, used by `commands' to handle some
850 options specially. */
852 static int check_user_specified_header PARAMS ((const char *));
855 cmd_spec_dirstruct (const char *com, const char *val, void *closure)
857 if (!cmd_boolean (com, val, &opt.dirstruct))
859 /* Since dirstruct behaviour is explicitly changed, no_dirstruct
860 must be affected inversely. */
862 opt.no_dirstruct = 0;
864 opt.no_dirstruct = 1;
869 cmd_spec_dotstyle (const char *com, const char *val, void *closure)
871 /* Retrieval styles. */
872 if (!strcasecmp (val, "default"))
874 /* Default style: 1K dots, 10 dots in a cluster, 50 dots in a
876 opt.dot_bytes = 1024;
877 opt.dot_spacing = 10;
878 opt.dots_in_line = 50;
880 else if (!strcasecmp (val, "binary"))
882 /* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots
884 opt.dot_bytes = 8192;
885 opt.dot_spacing = 16;
886 opt.dots_in_line = 48;
888 else if (!strcasecmp (val, "mega"))
890 /* "Mega" retrieval, for retrieving very long files; each dot is
891 64K, 8 dots in a cluster, 6 clusters (3M) in a line. */
892 opt.dot_bytes = 65536L;
894 opt.dots_in_line = 48;
896 else if (!strcasecmp (val, "giga"))
898 /* "Giga" retrieval, for retrieving very very *very* long files;
899 each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a
901 opt.dot_bytes = (1L << 20);
903 opt.dots_in_line = 32;
905 else if (!strcasecmp (val, "micro"))
907 /* "Micro" retrieval, for retrieving very small files (and/or
908 slow connections); each dot is 128 bytes, 8 dots in a
909 cluster, 6 clusters (6K) in a line. */
912 opt.dots_in_line = 48;
916 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
917 exec_name, com, val);
924 cmd_spec_header (const char *com, const char *val, void *closure)
928 /* Empty header means reset headers. */
929 FREE_MAYBE (opt.user_header);
930 opt.user_header = NULL;
936 if (!check_user_specified_header (val))
938 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
939 exec_name, com, val);
942 i = opt.user_header ? strlen (opt.user_header) : 0;
943 opt.user_header = (char *)xrealloc (opt.user_header, i + strlen (val)
945 strcpy (opt.user_header + i, val);
947 opt.user_header[i++] = '\r';
948 opt.user_header[i++] = '\n';
949 opt.user_header[i] = '\0';
955 cmd_spec_htmlify (const char *com, const char *val, void *closure)
957 int flag = cmd_boolean (com, val, &opt.htmlify);
958 if (flag && !opt.htmlify)
959 opt.remove_listing = 0;
964 cmd_spec_mirror (const char *com, const char *val, void *closure)
968 if (!cmd_boolean (com, val, &mirror))
973 if (!opt.no_dirstruct)
975 opt.timestamping = 1;
976 opt.reclevel = INFINITE_RECURSION;
977 opt.remove_listing = 0;
983 cmd_spec_recursive (const char *com, const char *val, void *closure)
985 if (!cmd_boolean (com, val, &opt.recursive))
989 if (opt.recursive && !opt.no_dirstruct)
996 cmd_spec_useragent (const char *com, const char *val, void *closure)
998 /* Just check for empty string and newline, so we don't throw total
999 junk to the server. */
1000 if (!*val || strchr (val, '\n'))
1002 fprintf (stderr, _("%s: %s: Invalid specification `%s'.\n"),
1003 exec_name, com, val);
1006 opt.useragent = xstrdup (val);
1010 /* Miscellaneous useful routines. */
1012 /* Return the integer value of a positive integer written in S, or -1
1013 if an error was encountered. */
1015 myatoi (const char *s)
1018 const char *orig = s;
1020 for (res = 0; *s && ISDIGIT (*s); s++)
1021 res = 10 * res + (*s - '0');
1022 if (*s || orig == s)
1028 #define ISODIGIT(x) ((x) >= '0' && (x) <= '7')
1031 check_user_specified_header (const char *s)
1035 for (p = s; *p && *p != ':' && !ISSPACE (*p); p++);
1036 /* The header MUST contain `:' preceded by at least one
1037 non-whitespace character. */
1038 if (*p != ':' || p == s)
1040 /* The header MUST NOT contain newlines. */
1041 if (strchr (s, '\n'))
1046 void cleanup_html_url PARAMS ((void));
1047 void downloaded_files_free PARAMS ((void));
1050 /* Free the memory allocated by global variables. */
1054 extern acc_t *netrc_list;
1056 recursive_cleanup ();
1058 free_netrc (netrc_list);
1061 cleanup_html_url ();
1062 downloaded_files_free ();
1064 FREE_MAYBE (opt.lfilename);
1065 xfree (opt.dir_prefix);
1066 FREE_MAYBE (opt.input_filename);
1067 FREE_MAYBE (opt.output_document);
1068 free_vec (opt.accepts);
1069 free_vec (opt.rejects);
1070 free_vec (opt.excludes);
1071 free_vec (opt.includes);
1072 free_vec (opt.domains);
1073 free_vec (opt.follow_tags);
1074 free_vec (opt.ignore_tags);
1075 xfree (opt.ftp_acc);
1076 FREE_MAYBE (opt.ftp_pass);
1077 FREE_MAYBE (opt.ftp_proxy);
1078 FREE_MAYBE (opt.https_proxy);
1079 FREE_MAYBE (opt.http_proxy);
1080 free_vec (opt.no_proxy);
1081 FREE_MAYBE (opt.useragent);
1082 FREE_MAYBE (opt.referer);
1083 FREE_MAYBE (opt.http_user);
1084 FREE_MAYBE (opt.http_passwd);
1085 FREE_MAYBE (opt.user_header);
1087 FREE_MAYBE (opt.sslcertkey);
1088 FREE_MAYBE (opt.sslcertfile);
1089 #endif /* HAVE_SSL */
1090 FREE_MAYBE (opt.bind_address);
1091 FREE_MAYBE (opt.cookies_input);
1092 FREE_MAYBE (opt.cookies_output);