]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_cf.cc
2.1 branch merge
[thirdparty/squid.git] / src / cache_cf.cc
CommitLineData
be335c22 1
30a4f2a8 2/*
c68e9c6b 3 * $Id: cache_cf.cc,v 1.310 1998/11/12 06:27:57 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 3 Configuration File Parsing
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
30a4f2a8 34 */
cf5fd929 35
44a47c6e 36#include "squid.h"
1df370e3 37
38#if SQUID_SNMP
a97cfa48 39#include "snmp.h"
1df370e3 40#endif
090089c4 41
8813e606 42static const char *const T_SECOND_STR = "second";
43static const char *const T_MINUTE_STR = "minute";
44static const char *const T_HOUR_STR = "hour";
45static const char *const T_DAY_STR = "day";
46static const char *const T_WEEK_STR = "week";
47static const char *const T_FORTNIGHT_STR = "fortnight";
48static const char *const T_MONTH_STR = "month";
49static const char *const T_YEAR_STR = "year";
50static const char *const T_DECADE_STR = "decade";
aa0a0c7c 51
9906e724 52static const char *const B_BYTES_STR = "bytes";
53static const char *const B_KBYTES_STR = "KB";
54static const char *const B_MBYTES_STR = "MB";
55static const char *const B_GBYTES_STR = "GB";
56
4db43fab 57static const char *const list_sep = ", \t\n\r";
090089c4 58
f5b8bbc4 59static void self_destruct(void);
caebbe00 60
f5b8bbc4 61static void configDoConfigure(void);
62static void parse_refreshpattern(refresh_t **);
63static int parseTimeUnits(const char *unit);
64static void parseTimeLine(time_t * tptr, const char *units);
65static void parse_string(char **);
66static void parse_wordlist(wordlist **);
67static void default_all(void);
68static void defaults_if_none(void);
69static int parse_line(char *);
70static void parseBytesLine(size_t * bptr, const char *units);
71static size_t parseBytesUnits(const char *unit);
f5b8bbc4 72static void free_all(void);
f0b19334 73static void requirePathnameExists(const char *name, const char *path);
ed7f5615 74static OBJH dump_config;
270b86af 75
24382924 76static void
0673c0ba 77self_destruct(void)
090089c4 78{
137ee196 79 fatalf("Bungled %s line %d: %s",
b8de7ebe 80 cfg_filename, config_lineno, config_input_line);
090089c4 81}
82
8203a132 83void
84wordlistDestroy(wordlist ** list)
0ffd22bc 85{
86 wordlist *w = NULL;
79d39a72 87 while ((w = *list) != NULL) {
b5639035 88 *list = w->next;
0ffd22bc 89 safe_free(w->key);
c68e9c6b 90 memFree(MEM_WORDLIST, w);
0ffd22bc 91 }
92 *list = NULL;
93}
94
c68e9c6b 95wordlist *
fe4e214f 96wordlistAdd(wordlist ** list, const char *key)
090089c4 97{
c68e9c6b 98 while (*list)
99 list = &(*list)->next;
100 *list = memAllocate(MEM_WORDLIST);
101 (*list)->key = xstrdup(key);
102 (*list)->next = NULL;
103 return *list;
090089c4 104}
105
137ee196 106void
eeb423fb 107wordlistCat(const wordlist * w, MemBuf * mb)
5da06f20 108{
5da06f20 109 while (NULL != w) {
137ee196 110 memBufPrintf(mb, "%s\n", w->key);
5da06f20 111 w = w->next;
112 }
5da06f20 113}
114
8203a132 115void
116intlistDestroy(intlist ** list)
92a6f4b1 117{
118 intlist *w = NULL;
119 intlist *n = NULL;
92a6f4b1 120 for (w = *list; w; w = n) {
121 n = w->next;
c68e9c6b 122 memFree(MEM_INTLIST, w);
92a6f4b1 123 }
124 *list = NULL;
125}
126
5db53b8f 127int
128intlistFind(intlist * list, int i)
129{
130 intlist *w = NULL;
131 for (w = list; w; w = w->next)
132 if (w->i == i)
133 return 1;
134 return 0;
135}
136
403279e0 137
3c5557f9 138/*
139 * Use this #define in all the parse*() functions. Assumes char *token is
140 * defined
141 */
090089c4 142
143#define GetInteger(var) \
144 token = strtok(NULL, w_space); \
30a4f2a8 145 if( token == NULL) \
3003c0f3 146 self_destruct(); \
090089c4 147 if (sscanf(token, "%d", &var) != 1) \
3003c0f3 148 self_destruct();
090089c4 149
270b86af 150int
151parseConfigFile(const char *file_name)
2546fcb3 152{
270b86af 153 FILE *fp = NULL;
154 char *token = NULL;
72121e8b 155 char *tmp_line;
0153d498 156 free_all();
157 default_all();
137ee196 158 if ((fp = fopen(file_name, "r")) == NULL)
159 fatalf("Unable to open configuration file: %s: %s",
270b86af 160 file_name, xstrerror());
270b86af 161 cfg_filename = file_name;
162 if ((token = strrchr(cfg_filename, '/')))
163 cfg_filename = token + 1;
164 memset(config_input_line, '\0', BUFSIZ);
165 config_lineno = 0;
166 while (fgets(config_input_line, BUFSIZ, fp)) {
167 config_lineno++;
168 if ((token = strchr(config_input_line, '\n')))
169 *token = '\0';
170 if (config_input_line[0] == '#')
171 continue;
172 if (config_input_line[0] == '\0')
173 continue;
174 debug(3, 5) ("Processing: '%s'\n", config_input_line);
72121e8b 175 tmp_line = xstrdup(config_input_line);
270b86af 176 if (!parse_line(tmp_line)) {
177 debug(3, 0) ("parseConfigFile: line %d unrecognized: '%s'\n",
178 config_lineno,
179 config_input_line);
180 }
72121e8b 181 safe_free(tmp_line);
270b86af 182 }
f0b19334 183 fclose(fp);
184 defaults_if_none();
185 configDoConfigure();
22f3fd98 186 cachemgrRegister("config",
187 "Current Squid Configuration",
188 dump_config,
1da3b90b 189 1, 1);
f0b19334 190 return 0;
191}
270b86af 192
f0b19334 193static void
194configDoConfigure(void)
195{
196 LOCAL_ARRAY(char, buf, BUFSIZ);
197 memset(&Config2, '\0', sizeof(SquidConfig2));
7021844c 198 /* init memory as early as possible */
199 memConfigure();
270b86af 200 /* Sanity checks */
a95856a0 201 if (Config.cacheSwap.swapDirs == NULL)
202 fatal("No cache_dir's specified in config file");
9fa8263f 203 /* calculate Config.Swap.maxSize */
f4e3fa54 204 storeDirConfigure();
f0b19334 205 if (Config.Swap.maxSize < (Config.Mem.maxSize >> 10))
206 fatal("cache_swap is lower than cache_mem");
84f42bac 207 if (Config.Announce.period > 0) {
208 Config.onoff.announce = 1;
209 } else if (Config.Announce.period < 1) {
f1dc9b30 210 Config.Announce.period = 86400 * 365; /* one year */
17a0a4ee 211 Config.onoff.announce = 0;
270b86af 212 }
f0b19334 213 if (Config.dnsChildren < 1)
214 fatal("No dnsservers allocated");
215 if (Config.dnsChildren > DefaultDnsChildrenMax) {
216 debug(3, 0) ("WARNING: dns_children was set to a bad value: %d\n",
270b86af 217 Config.dnsChildren);
f0b19334 218 debug(3, 0) ("Setting it to the maximum (%d).\n",
219 DefaultDnsChildrenMax);
270b86af 220 Config.dnsChildren = DefaultDnsChildrenMax;
221 }
222 if (Config.Program.redirect) {
223 if (Config.redirectChildren < 1) {
224 Config.redirectChildren = 0;
225 safe_free(Config.Program.redirect);
226 } else if (Config.redirectChildren > DefaultRedirectChildrenMax) {
f0b19334 227 debug(3, 0) ("WARNING: redirect_children was set to a bad value: %d\n",
270b86af 228 Config.redirectChildren);
f0b19334 229 debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultRedirectChildrenMax);
270b86af 230 Config.redirectChildren = DefaultRedirectChildrenMax;
231 }
fea2e6e0 232 }
73e67ee0 233 if (Config.Program.authenticate) {
234 if (Config.authenticateChildren < 1) {
235 Config.authenticateChildren = 0;
6c20b822 236 wordlistDestroy(&Config.Program.authenticate);
73e67ee0 237 } else if (Config.authenticateChildren > DefaultAuthenticateChildrenMax) {
238 debug(3, 0) ("WARNING: authenticate_children was set to a bad value: %d\n",
239 Config.authenticateChildren);
240 debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultAuthenticateChildrenMax);
241 Config.authenticateChildren = DefaultAuthenticateChildrenMax;
242 }
243 }
f1dc9b30 244 if (Config.Accel.host) {
a47b9029 245 snprintf(buf, BUFSIZ, "http://%s:%d", Config.Accel.host, Config.Accel.port);
246 Config2.Accel.prefix = xstrdup(buf);
247 Config2.Accel.on = 1;
f1dc9b30 248 }
249 if (Config.appendDomain)
250 if (*Config.appendDomain != '.')
251 fatal("append_domain must begin with a '.'");
270b86af 252 if (Config.errHtmlText == NULL)
253 Config.errHtmlText = xstrdup(null_string);
254 storeConfigure();
f1dc9b30 255 if (Config2.Accel.on && !strcmp(Config.Accel.host, "virtual"))
270b86af 256 vhost_mode = 1;
257 if (Config.Port.http == NULL)
258 fatal("No http_port specified!");
137ee196 259 snprintf(ThisCache, sizeof(ThisCache), "%s:%d (%s)",
98829f69 260 uniqueHostname(),
270b86af 261 (int) Config.Port.http->i,
137ee196 262 full_appname_string);
270b86af 263 if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF)
264 Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF;
265 if (Config.appendDomain)
266 Config.appendDomainLen = strlen(Config.appendDomain);
267 else
268 Config.appendDomainLen = 0;
f1dc9b30 269 safe_free(debug_options)
270 debug_options = xstrdup(Config.debugOptions);
22c653cd 271 if (Config.retry.timeout < 5)
272 fatal("minimum_retry_timeout must be at least 5 seconds");
273 if (Config.retry.maxtries > 10)
274 fatal("maximum_single_addr_tries cannot be larger than 10");
275 if (Config.retry.maxtries < 1) {
22c653cd 276 debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n");
5210854d 277 Config.retry.maxtries = 1;
278 }
279 if (Config.referenceAge < 300) {
280 debug(3, 0) ("WARNING: resetting 'reference_age' to 1 week\n");
281 Config.referenceAge = 86400 * 7;
22c653cd 282 }
f0b19334 283 requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
284 requirePathnameExists("cache_dns_program", Config.Program.dnsserver);
285 requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
286 if (Config.Program.redirect)
287 requirePathnameExists("redirect_program", Config.Program.redirect);
73e67ee0 288 if (Config.Program.authenticate)
6c20b822 289 requirePathnameExists("authenticate_program", Config.Program.authenticate->key);
f0b19334 290 requirePathnameExists("Icon Directory", Config.icons.directory);
291 requirePathnameExists("Error Directory", Config.errorDirectory);
9f60cfdf 292#if HTTP_VIOLATIONS
293 {
49c0f46d 294 const refresh_t *R;
295 for (R = Config.Refresh; R; R = R->next) {
296 if (!R->flags.override_expire)
297 continue;
298 debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n");
299 break;
300 }
301 for (R = Config.Refresh; R; R = R->next) {
302 if (!R->flags.override_lastmod)
303 continue;
304 debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n");
305 break;
306 }
9f60cfdf 307 }
308#endif
090089c4 309}
310
270b86af 311/* Parse a time specification from the config file. Store the
f1dc9b30 312 * result in 'tptr', after converting it to 'units' */
8203a132 313static void
a47b9029 314parseTimeLine(time_t * tptr, const char *units)
090089c4 315{
316 char *token;
270b86af 317 double d;
f1dc9b30 318 time_t m;
319 time_t u;
270b86af 320 if ((u = parseTimeUnits(units)) == 0)
3003c0f3 321 self_destruct();
270b86af 322 if ((token = strtok(NULL, w_space)) == NULL)
3003c0f3 323 self_destruct();
270b86af 324 d = atof(token);
325 m = u; /* default to 'units' if none specified */
10738561 326 if (0 == d)
327 (void) 0;
328 else if ((token = strtok(NULL, w_space)) == NULL)
a47b9029 329 debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n",
330 config_input_line, d, units);
9e975e4e 331 else if ((m = parseTimeUnits(token)) == 0)
a47b9029 332 self_destruct();
f1dc9b30 333 *tptr = m * d / u;
090089c4 334}
335
270b86af 336static int
337parseTimeUnits(const char *unit)
338{
339 if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR)))
340 return 1;
341 if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR)))
342 return 60;
343 if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR)))
344 return 3600;
345 if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR)))
346 return 86400;
347 if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR)))
348 return 86400 * 7;
349 if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR)))
350 return 86400 * 14;
351 if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR)))
352 return 86400 * 30;
353 if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR)))
354 return 86400 * 365.2522;
355 if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
356 return 86400 * 365.2522 * 10;
357 debug(3, 1) ("parseTimeUnits: unknown time unit '%s'\n", unit);
358 return 0;
359}
360
9906e724 361static void
9e975e4e 362parseBytesLine(size_t * bptr, const char *units)
9906e724 363{
364 char *token;
365 double d;
366 size_t m;
367 size_t u;
368 if ((u = parseBytesUnits(units)) == 0)
369 self_destruct();
370 if ((token = strtok(NULL, w_space)) == NULL)
371 self_destruct();
372 d = atof(token);
373 m = u; /* default to 'units' if none specified */
10738561 374 if (0 == d)
375 (void) 0;
4860dc1b 376 else if ((token = strtok(NULL, w_space)) == NULL)
9e975e4e 377 debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n",
378 config_input_line, d, units);
379 else if ((m = parseBytesUnits(token)) == 0)
380 self_destruct();
9906e724 381 *bptr = m * d / u;
382}
383
384static size_t
385parseBytesUnits(const char *unit)
386{
387 if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR)))
388 return 1;
389 if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR)))
a47b9029 390 return 1 << 10;
9906e724 391 if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR)))
a47b9029 392 return 1 << 20;
9906e724 393 if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
a47b9029 394 return 1 << 30;
9906e724 395 debug(3, 1) ("parseBytesUnits: unknown bytes unit '%s'\n", unit);
396 return 0;
397}
398
270b86af 399/*****************************************************************************
400 * Max
401 *****************************************************************************/
402
8203a132 403static void
9ef28b60 404dump_acl(StoreEntry * entry, const char *name, acl * ae)
090089c4 405{
56b63fa1 406 wordlist *w;
407 wordlist *v;
9ef28b60 408 while (ae != NULL) {
c68e9c6b 409 debug(3, 3) ("dump_acl: %s %s\n", name, ae->name);
9ef28b60 410 v = w = aclDumpGeneric(ae);
56b63fa1 411 while (v != NULL) {
c68e9c6b 412 debug(3, 3) ("dump_acl: %s %s %s\n", name, ae->name, v->key);
16300b58 413 storeAppendPrintf(entry, "%s %s %s %s\n",
414 name,
9ef28b60 415 ae->name,
416 aclTypeToStr(ae->type),
16300b58 417 v->key);
56b63fa1 418 v = v->next;
419 }
420 wordlistDestroy(&w);
9ef28b60 421 ae = ae->next;
56b63fa1 422 }
090089c4 423}
424
8203a132 425static void
9ef28b60 426parse_acl(acl ** ae)
090089c4 427{
9ef28b60 428 aclParseAclLine(ae);
f1dc9b30 429}
430
431static void
9ef28b60 432free_acl(acl ** ae)
f1dc9b30 433{
9ef28b60 434 aclDestroyAcls(ae);
090089c4 435}
436
8203a132 437static void
16300b58 438dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
30a4f2a8 439{
56b63fa1 440 acl_list *l;
441 while (head != NULL) {
505e35db 442 storeAppendPrintf(entry, "%s %s",
0cdcddb9 443 name,
505e35db 444 head->allow ? "Allow" : "Deny");
445 for (l = head->acl_list; l != NULL; l = l->next) {
446 storeAppendPrintf(entry, " %s%s",
447 l->op ? null_string : "!",
56b63fa1 448 l->acl->name);
16300b58 449 }
505e35db 450 storeAppendPrintf(entry, "\n");
56b63fa1 451 head = head->next;
452 }
30a4f2a8 453}
090089c4 454
8203a132 455static void
16300b58 456parse_acl_access(acl_access ** head)
090089c4 457{
270b86af 458 aclParseAccessLine(head);
090089c4 459}
460
0153d498 461static void
16300b58 462free_acl_access(acl_access ** head)
0153d498 463{
a47b9029 464 aclDestroyAccessList(head);
0153d498 465}
466
8203a132 467static void
a7d59104 468dump_address(StoreEntry * entry, const char *name, struct in_addr addr)
270b86af 469{
f53b06f9 470 storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr));
270b86af 471}
472
473static void
474parse_address(struct in_addr *addr)
090089c4 475{
0ee4272b 476 const struct hostent *hp;
270b86af 477 char *token = strtok(NULL, w_space);
478
30a4f2a8 479 if (token == NULL)
480 self_destruct();
429fdbec 481 if (safe_inet_addr(token, addr) == 1)
482 (void) 0;
ceb8994e 483 else if ((hp = gethostbyname(token))) /* dont use ipcache */
1d73e33a 484 *addr = inaddrFromHostent(hp);
30a4f2a8 485 else
3003c0f3 486 self_destruct();
090089c4 487}
488
0153d498 489static void
490free_address(struct in_addr *addr)
491{
a47b9029 492 memset(addr, '\0', sizeof(struct in_addr));
0153d498 493}
494
e90100aa 495static void
56b63fa1 496dump_cachedir(StoreEntry * entry, const char *name, cacheSwap swap)
e90100aa 497{
f53b06f9 498 SwapDir *s;
499 int i;
a7d59104 500 for (i = 0; i < swap.n_configured; i++) {
501 s = swap.swapDirs + i;
f53b06f9 502 storeAppendPrintf(entry, "%s %s %d %d %d\n",
503 name,
504 s->path,
a7d59104 505 s->max_size >> 10,
f53b06f9 506 s->l1,
507 s->l2);
508 }
509}
510
511static int
56b63fa1 512check_null_cachedir(cacheSwap swap)
f53b06f9 513{
514 return swap.swapDirs == NULL;
e90100aa 515}
516
53ad48e6 517static int
518check_null_string(char *s)
519{
520 return s == NULL;
521}
522
8203a132 523static void
16300b58 524parse_cachedir(cacheSwap * swap)
090089c4 525{
526 char *token;
7da279d6 527 char *path;
752c3b27 528 int i;
270b86af 529 int size;
530 int l1;
531 int l2;
c68e9c6b 532 int read_only = 0;
f1dc9b30 533 SwapDir *tmp = NULL;
534 if ((path = strtok(NULL, w_space)) == NULL)
752c3b27 535 self_destruct();
270b86af 536 GetInteger(i);
537 size = i << 10; /* Mbytes to kbytes */
893dbb06 538 if (size <= 0)
539 fatal("parse_cachedir: invalid size value");
270b86af 540 GetInteger(i);
541 l1 = i;
893dbb06 542 if (l1 <= 0)
543 fatal("parse_cachedir: invalid level 1 directories value");
270b86af 544 GetInteger(i);
545 l2 = i;
893dbb06 546 if (l2 <= 0)
547 fatal("parse_cachedir: invalid level 2 directories value");
270b86af 548 if ((token = strtok(NULL, w_space)))
549 if (!strcasecmp(token, "read-only"))
c68e9c6b 550 read_only = 1;
f1dc9b30 551 for (i = 0; i < swap->n_configured; i++) {
a47b9029 552 tmp = swap->swapDirs + i;
f1dc9b30 553 if (!strcmp(path, tmp->path)) {
554 /* just reconfigure it */
860ee7e3 555 if (size == tmp->max_size)
d61b4908 556 debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n",
be335c22 557 path, size);
860ee7e3 558 else
d61b4908 559 debug(3, 1) ("Cache dir '%s' size changed to %d KB\n",
be335c22 560 path, size);
a47b9029 561 tmp->max_size = size;
c68e9c6b 562 if (tmp->read_only != read_only)
be335c22 563 debug(3, 1) ("Cache dir '%s' now %s\n",
c68e9c6b 564 path, read_only ? "Read-Only" : "Read-Write");
565 tmp->read_only = read_only;
f1dc9b30 566 return;
567 }
568 }
569 if (swap->swapDirs == NULL) {
570 swap->n_allocated = 4;
571 swap->swapDirs = xcalloc(swap->n_allocated, sizeof(SwapDir));
572 }
573 if (swap->n_allocated == swap->n_configured) {
574 swap->n_allocated <<= 1;
575 tmp = xcalloc(swap->n_allocated, sizeof(SwapDir));
576 xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir));
577 xfree(swap->swapDirs);
578 swap->swapDirs = tmp;
579 }
f1dc9b30 580 tmp = swap->swapDirs + swap->n_configured;
581 tmp->path = xstrdup(path);
582 tmp->max_size = size;
583 tmp->l1 = l1;
584 tmp->l2 = l2;
c68e9c6b 585 tmp->read_only = read_only;
f1dc9b30 586 tmp->swaplog_fd = -1;
62607543 587 swap->n_configured++;
752c3b27 588}
589
8203a132 590static void
16300b58 591free_cachedir(cacheSwap * swap)
f1dc9b30 592{
a47b9029 593 SwapDir *s;
594 int i;
860ee7e3 595 /* DON'T FREE THESE FOR RECONFIGURE */
5cd39a10 596 if (reconfiguring)
860ee7e3 597 return;
a47b9029 598 for (i = 0; i < swap->n_configured; i++) {
599 s = swap->swapDirs + i;
f150dd4b 600 if (s->swaplog_fd > -1) {
601 file_close(s->swaplog_fd);
602 s->swaplog_fd = -1;
603 }
a47b9029 604 xfree(s->path);
605 filemapFreeMemory(s->map);
606 }
607 safe_free(swap->swapDirs);
608 swap->swapDirs = NULL;
609 swap->n_allocated = 0;
610 swap->n_configured = 0;
f1dc9b30 611}
612
505e35db 613const char *
614peer_type_str(const peer_t type)
615{
0cdcddb9 616 switch (type) {
505e35db 617 case PEER_PARENT:
618 return "parent";
619 break;
620 case PEER_SIBLING:
621 return "sibling";
622 break;
623 case PEER_MULTICAST:
624 return "multicast";
625 break;
626 default:
627 return "unknown";
628 break;
629 }
630}
631
f1dc9b30 632static void
a7d59104 633dump_peer(StoreEntry * entry, const char *name, peer * p)
98ffb7e4 634{
505e35db 635 domain_ping *d;
636 acl_access *a;
637 domain_type *t;
638 LOCAL_ARRAY(char, xname, 128);
d41de3c1 639 while (p != NULL) {
640 storeAppendPrintf(entry, "%s %s %s %d %d",
641 name,
642 p->host,
643 neighborTypeStr(p),
644 p->http_port,
399cabec 645 p->icp.port);
a369131d 646 dump_peer_options(entry, p);
505e35db 647 for (d = p->pinglist; d; d = d->next) {
648 storeAppendPrintf(entry, "cache_peer_domain %s %s%s\n",
649 p->host,
650 d->do_ping ? null_string : "!",
651 d->domain);
652 }
653 if ((a = p->access)) {
654 snprintf(xname, 128, "cache_peer_access %s", p->host);
655 dump_acl_access(entry, xname, p->access);
656 }
657 for (t = p->typelist; t; t = t->next) {
658 storeAppendPrintf(entry, "neighbor_type_domain %s %s %s\n",
659 p->host,
660 peer_type_str(t->type),
661 t->domain);
662 }
d41de3c1 663 p = p->next;
664 }
98ffb7e4 665}
666
8203a132 667static void
40a1495e 668parse_peer(peer ** head)
7813c6d5 669{
270b86af 670 char *token = NULL;
40a1495e 671 peer *p;
7813c6d5 672 int i;
40a1495e 673 ushortlist *u;
f9e5a344 674 const char *me = null_string; /* XXX */
40a1495e 675 p = xcalloc(1, sizeof(peer));
676 p->http_port = CACHE_HTTP_PORT;
399cabec 677 p->icp.port = CACHE_ICP_PORT;
40a1495e 678 p->weight = 1;
dc835977 679 p->stats.logged_state = PEER_ALIVE;
e481c2dc 680 if ((token = strtok(NULL, w_space)) == NULL)
270b86af 681 self_destruct();
40a1495e 682 p->host = xstrdup(token);
e481c2dc 683 if ((token = strtok(NULL, w_space)) == NULL)
270b86af 684 self_destruct();
40a1495e 685 p->type = parseNeighborType(token);
270b86af 686 GetInteger(i);
40a1495e 687 p->http_port = (u_short) i;
e8d185d2 688 GetInteger(i);
399cabec 689 p->icp.port = (u_short) i;
40a1495e 690 if (strcmp(p->host, me) == 0) {
691 for (u = Config.Port.http; u; u = u->next) {
692 if (p->http_port != u->i)
693 continue;
694 debug(15, 0) ("parse_peer: Peer looks like myself: %s %s/%d/%d\n",
399cabec 695 p->type, p->host, p->http_port, p->icp.port);
40a1495e 696 self_destruct();
697 }
698 }
270b86af 699 while ((token = strtok(NULL, w_space))) {
700 if (!strcasecmp(token, "proxy-only")) {
cd196bc8 701 p->options.proxy_only = 1;
270b86af 702 } else if (!strcasecmp(token, "no-query")) {
cd196bc8 703 p->options.no_query = 1;
8638fc66 704 } else if (!strcasecmp(token, "no-digest")) {
cd196bc8 705 p->options.no_digest = 1;
270b86af 706 } else if (!strcasecmp(token, "multicast-responder")) {
cd196bc8 707 p->options.mcast_responder = 1;
270b86af 708 } else if (!strncasecmp(token, "weight=", 7)) {
40a1495e 709 p->weight = atoi(token + 7);
0103c4c1 710 } else if (!strcasecmp(token, "closest-only")) {
cd196bc8 711 p->options.closest_only = 1;
270b86af 712 } else if (!strncasecmp(token, "ttl=", 4)) {
40a1495e 713 p->mcast.ttl = atoi(token + 4);
714 if (p->mcast.ttl < 0)
715 p->mcast.ttl = 0;
716 if (p->mcast.ttl > 128)
717 p->mcast.ttl = 128;
0103c4c1 718 } else if (!strcasecmp(token, "default")) {
cd196bc8 719 p->options.default_parent = 1;
0103c4c1 720 } else if (!strcasecmp(token, "round-robin")) {
cd196bc8 721 p->options.roundrobin = 1;
dc9d133b 722#if USE_HTCP
0103c4c1 723 } else if (!strcasecmp(token, "htcp")) {
cd196bc8 724 p->options.htcp = 1;
dc9d133b 725#endif
0103c4c1 726 } else if (!strcasecmp(token, "no-netdb-exchange")) {
cd196bc8 727 p->options.no_netdb_exchange = 1;
afd88fbe 728#if USE_CARP
729 } else if (!strncasecmp(token, "carp-load-factor=", 17)) {
730 if (p->type != PEER_PARENT)
0cdcddb9 731 debug(3, 0) ("parse_peer: Ignoring carp-load-factor for non-parent %s/%d\n", p->host, p->http_port);
732 else
733 p->carp.load_factor = atof(token + 17);
95e36d02 734#endif
735#if DELAY_POOLS
736 } else if (!strcasecmp(token, "no-delay")) {
cd196bc8 737 p->options.no_delay = 1;
afd88fbe 738#endif
c68e9c6b 739 } else if (!strncasecmp(token, "login=", 6)) {
740 p->login = xstrdup(token + 6);
270b86af 741 } else {
40a1495e 742 debug(3, 0) ("parse_peer: token='%s'\n", token);
270b86af 743 self_destruct();
744 }
745 }
40a1495e 746 if (p->weight < 1)
747 p->weight = 1;
399cabec 748 p->icp.version = ICP_VERSION_CURRENT;
98829f69 749 p->tcp_up = PEER_TCP_MAGIC_COUNT;
afd88fbe 750#if USE_CARP
751 if (p->carp.load_factor) {
0cdcddb9 752 /*
753 * calculate this peers hash for use in CARP
754 */
755 p->carp.hash = 0;
756 for (token = p->host; *token != 0; token++)
757 p->carp.hash += (p->carp.hash << 19) + *token;
afd88fbe 758 }
759#endif
3f6c0fb2 760 cbdataAdd(p, MEM_NONE);
0153d498 761 while (*head != NULL)
762 head = &(*head)->next;
763 *head = p;
40a1495e 764 Config.npeers++;
0153d498 765}
766
767static void
40a1495e 768free_peer(peer ** P)
0153d498 769{
40a1495e 770 peer *p;
79d39a72 771 while ((p = *P) != NULL) {
a47b9029 772 *P = p->next;
40a1495e 773 peerDestroy(p);
a47b9029 774 }
987c67d1 775 Config.npeers = 0;
270b86af 776}
777
778static void
a7d59104 779dump_cachemgrpasswd(StoreEntry * entry, const char *name, cachemgr_passwd * list)
270b86af 780{
d41de3c1 781 wordlist *w;
782 while (list != NULL) {
783 storeAppendPrintf(entry, "%s XXXXXXXXXX", name);
784 for (w = list->actions; w != NULL; w = w->next) {
785 storeAppendPrintf(entry, " %s", w->key);
786 }
787 storeAppendPrintf(entry, "\n");
788 list = list->next;
789 }
270b86af 790}
791
792static void
a47b9029 793parse_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 794{
795 char *passwd = NULL;
796 wordlist *actions = NULL;
22f3fd98 797 cachemgr_passwd *p;
798 cachemgr_passwd **P;
270b86af 799 parse_string(&passwd);
800 parse_wordlist(&actions);
22f3fd98 801 p = xcalloc(1, sizeof(cachemgr_passwd));
802 p->passwd = passwd;
803 p->actions = actions;
804 for (P = head; *P; P = &(*P)->next);
805 *P = p;
270b86af 806}
807
808static void
a47b9029 809free_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 810{
a47b9029 811 cachemgr_passwd *p;
79d39a72 812 while ((p = *head) != NULL) {
a47b9029 813 *head = p->next;
814 xfree(p->passwd);
22f3fd98 815 wordlistDestroy(&p->actions);
a47b9029 816 xfree(p);
817 }
270b86af 818}
819
8203a132 820static void
16300b58 821dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var)
270b86af 822{
d41de3c1 823 acl_name_list *a;
824 while (var != NULL) {
02922e76 825 storeAppendPrintf(entry, "%s %s", name, var->err_page_name);
d41de3c1 826 for (a = var->acl_list; a != NULL; a = a->next)
827 storeAppendPrintf(entry, " %s", a->name);
828 storeAppendPrintf(entry, "\n");
829 var = var->next;
830 }
270b86af 831}
832
833static void
16300b58 834parse_denyinfo(acl_deny_info_list ** var)
6e40f263 835{
f1dc9b30 836 aclParseDenyInfoLine(var);
6e40f263 837}
403279e0 838
1273d501 839void
a47b9029 840free_denyinfo(acl_deny_info_list ** list)
3c5557f9 841{
56b63fa1 842 acl_deny_info_list *a = NULL;
843 acl_deny_info_list *a_next = NULL;
844 acl_name_list *l = NULL;
845 acl_name_list *l_next = NULL;
1273d501 846 for (a = *list; a; a = a_next) {
a47b9029 847 for (l = a->acl_list; l; l = l_next) {
848 l_next = l->next;
849 safe_free(l);
850 }
851 a_next = a->next;
852 safe_free(a);
1273d501 853 }
854 *list = NULL;
270b86af 855}
856
857static void
505e35db 858parse_peer_access(void)
270b86af 859{
860 char *host = NULL;
505e35db 861 peer *p;
270b86af 862 if (!(host = strtok(NULL, w_space)))
863 self_destruct();
0cdcddb9 864 if ((p = peerFindByName(host)) == NULL) {
865 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
866 cfg_filename, config_lineno, host);
867 return;
868 }
505e35db 869 aclParseAccessLine(&p->access);
270b86af 870}
871
270b86af 872static void
873parse_hostdomain(void)
874{
875 char *host = NULL;
876 char *domain = NULL;
877 if (!(host = strtok(NULL, w_space)))
878 self_destruct();
f1dc9b30 879 while ((domain = strtok(NULL, list_sep))) {
880 domain_ping *l = NULL;
881 domain_ping **L = NULL;
40a1495e 882 peer *p;
883 if ((p = peerFindByName(host)) == NULL) {
43c3424b 884 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
f1dc9b30 885 cfg_filename, config_lineno, host);
886 continue;
887 }
56b63fa1 888 l = xcalloc(1, sizeof(domain_ping));
f1dc9b30 889 l->do_ping = 1;
890 if (*domain == '!') { /* check for !.edu */
891 l->do_ping = 0;
892 domain++;
893 }
894 l->domain = xstrdup(domain);
895 for (L = &(p->pinglist); *L; L = &((*L)->next));
896 *L = l;
897 }
270b86af 898}
899
900static void
901parse_hostdomaintype(void)
902{
903 char *host = NULL;
904 char *type = NULL;
905 char *domain = NULL;
906 if (!(host = strtok(NULL, w_space)))
907 self_destruct();
908 if (!(type = strtok(NULL, w_space)))
909 self_destruct();
f1dc9b30 910 while ((domain = strtok(NULL, list_sep))) {
911 domain_type *l = NULL;
912 domain_type **L = NULL;
40a1495e 913 peer *p;
914 if ((p = peerFindByName(host)) == NULL) {
43c3424b 915 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
f1dc9b30 916 cfg_filename, config_lineno, host);
917 return;
918 }
56b63fa1 919 l = xcalloc(1, sizeof(domain_type));
f1dc9b30 920 l->type = parseNeighborType(type);
921 l->domain = xstrdup(domain);
922 for (L = &(p->typelist); *L; L = &((*L)->next));
923 *L = l;
924 }
270b86af 925}
926
927static void
a7d59104 928dump_httpanonymizer(StoreEntry * entry, const char *name, int var)
270b86af 929{
930 switch (var) {
931 case ANONYMIZER_NONE:
f0b19334 932 storeAppendPrintf(entry, "%s off\n", name);
270b86af 933 break;
934 case ANONYMIZER_STANDARD:
f0b19334 935 storeAppendPrintf(entry, "%s paranoid\n", name);
270b86af 936 break;
937 case ANONYMIZER_PARANOID:
f0b19334 938 storeAppendPrintf(entry, "%s standard\n", name);
270b86af 939 break;
940 }
941}
942
943static void
944parse_httpanonymizer(int *var)
fa562c67 945{
946 char *token;
947 token = strtok(NULL, w_space);
948 if (token == NULL)
bba6fa8f 949 self_destruct();
fa562c67 950 if (!strcasecmp(token, "off"))
270b86af 951 *var = ANONYMIZER_NONE;
fa562c67 952 else if (!strcasecmp(token, "paranoid"))
270b86af 953 *var = ANONYMIZER_PARANOID;
fa562c67 954 else
270b86af 955 *var = ANONYMIZER_STANDARD;
956}
957
641941c0 958
270b86af 959static void
a7d59104 960dump_ushortlist(StoreEntry * entry, const char *name, ushortlist * u)
090089c4 961{
270b86af 962 while (u) {
f53b06f9 963 storeAppendPrintf(entry, "%s %d\n", name, (int) u->i);
270b86af 964 u = u->next;
965 }
966}
090089c4 967
f53b06f9 968static int
969check_null_ushortlist(ushortlist * u)
970{
971 return u == NULL;
972}
973
270b86af 974static void
975parse_ushortlist(ushortlist ** P)
976{
977 char *token;
978 int i;
979 ushortlist *u;
980 ushortlist **U;
981 while ((token = strtok(NULL, w_space))) {
982 if (sscanf(token, "%d", &i) != 1)
983 self_destruct();
984 if (i < 0)
985 i = 0;
986 u = xcalloc(1, sizeof(ushortlist));
987 u->i = (u_short) i;
988 for (U = P; *U; U = &(*U)->next);
989 *U = u;
090089c4 990 }
270b86af 991}
090089c4 992
0153d498 993static void
a47b9029 994free_ushortlist(ushortlist ** P)
0153d498 995{
a47b9029 996 ushortlist *u;
79d39a72 997 while ((u = *P) != NULL) {
a47b9029 998 *P = u->next;
999 xfree(u);
1000 }
0153d498 1001}
1002
270b86af 1003static void
a7d59104 1004dump_int(StoreEntry * entry, const char *name, int var)
270b86af 1005{
f53b06f9 1006 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 1007}
c1c29eb6 1008
270b86af 1009static void
1010parse_int(int *var)
1011{
1012 char *token;
1013 int i;
270b86af 1014 GetInteger(i);
1015 *var = i;
1016}
090089c4 1017
0153d498 1018static void
1019free_int(int *var)
1020{
a47b9029 1021 *var = 0;
0153d498 1022}
1023
270b86af 1024static void
a7d59104 1025dump_onoff(StoreEntry * entry, const char *name, int var)
270b86af 1026{
f53b06f9 1027 storeAppendPrintf(entry, "%s %s\n", name, var ? "on" : "off");
270b86af 1028}
090089c4 1029
270b86af 1030static void
1031parse_onoff(int *var)
1032{
1033 char *token = strtok(NULL, w_space);
090089c4 1034
270b86af 1035 if (token == NULL)
1036 self_destruct();
1037 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
1038 *var = 1;
1039 else
1040 *var = 0;
1041}
e90100aa 1042
0153d498 1043#define free_onoff free_int
f1dc9b30 1044#define free_httpanonymizer free_int
f1dc9b30 1045#define dump_eol dump_string
1046#define free_eol free_string
30a4f2a8 1047
270b86af 1048static void
a7d59104 1049dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head)
270b86af 1050{
d41de3c1 1051 while (head != NULL) {
9f60cfdf 1052 storeAppendPrintf(entry, "%s%s %s %d %d%% %d\n",
c3f6d204 1053 name,
1054 head->flags.icase ? " -i" : null_string,
1055 head->pattern,
1056 (int) head->min / 60,
1057 (int) (100.0 * head->pct + 0.5),
9f60cfdf 1058 (int) head->max / 60);
1059#if HTTP_VIOLATIONS
1060 if (head->flags.override_expire)
1061 storeAppendPrintf(entry, " override-expire");
1062 if (head->flags.override_lastmod)
1063 storeAppendPrintf(entry, " override-lastmod");
1064 if (head->flags.reload_into_ims)
1065 storeAppendPrintf(entry, " reload-into-ims");
1066 if (head->flags.ignore_reload)
1067 storeAppendPrintf(entry, " ignore-reload");
1068#endif
1069 storeAppendPrintf(entry, "\n");
d41de3c1 1070 head = head->next;
1071 }
270b86af 1072}
090089c4 1073
270b86af 1074static void
f1dc9b30 1075parse_refreshpattern(refresh_t ** head)
270b86af 1076{
f1dc9b30 1077 char *token;
1078 char *pattern;
1079 time_t min = 0;
c3f6d204 1080 double pct = 0.0;
f1dc9b30 1081 time_t max = 0;
9f60cfdf 1082#if HTTP_VIOLATIONS
1dfa1d81 1083 int override_expire = 0;
1084 int override_lastmod = 0;
cbe3a719 1085 int reload_into_ims = 0;
1086 int ignore_reload = 0;
9f60cfdf 1087#endif
f1dc9b30 1088 int i;
1089 refresh_t *t;
1090 regex_t comp;
1091 int errcode;
1092 int flags = REG_EXTENDED | REG_NOSUB;
1093 if ((token = strtok(NULL, w_space)) == NULL)
1094 self_destruct();
1095 if (strcmp(token, "-i") == 0) {
1096 flags |= REG_ICASE;
1097 token = strtok(NULL, w_space);
1098 } else if (strcmp(token, "+i") == 0) {
1099 flags &= ~REG_ICASE;
1100 token = strtok(NULL, w_space);
1101 }
1102 if (token == NULL)
1103 self_destruct();
1104 pattern = xstrdup(token);
1105 GetInteger(i); /* token: min */
1106 min = (time_t) (i * 60); /* convert minutes to seconds */
1107 GetInteger(i); /* token: pct */
c3f6d204 1108 pct = (double) i / 100.0;
f1dc9b30 1109 GetInteger(i); /* token: max */
1110 max = (time_t) (i * 60); /* convert minutes to seconds */
1dfa1d81 1111 /* Options */
1112 while ((token = strtok(NULL, w_space)) != NULL) {
9f60cfdf 1113#if HTTP_VIOLATIONS
1dfa1d81 1114 if (!strcmp(token, "override-expire"))
1115 override_expire = 1;
255d6021 1116 else if (!strcmp(token, "override-lastmod"))
1dfa1d81 1117 override_lastmod = 1;
cbe3a719 1118 else if (!strcmp(token, "reload-into-ims")) {
1119 reload_into_ims = 1;
1120 refresh_nocache_hack = 1;
1121 /* tell client_side.c that this is used */
1122 } else if (!strcmp(token, "ignore-reload")) {
1123 ignore_reload = 1;
1124 refresh_nocache_hack = 1;
1125 /* tell client_side.c that this is used */
1126 } else
9f60cfdf 1127#endif
cbe3a719 1128 debug(22, 0) ("redreshAddToList: Unknown option '%s': %s\n",
1dfa1d81 1129 pattern, token);
1130 }
f1dc9b30 1131 if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
1132 char errbuf[256];
1133 regerror(errcode, &comp, errbuf, sizeof errbuf);
1134 debug(22, 0) ("%s line %d: %s\n",
1135 cfg_filename, config_lineno, config_input_line);
1136 debug(22, 0) ("refreshAddToList: Invalid regular expression '%s': %s\n",
1137 pattern, errbuf);
1138 return;
1139 }
c3f6d204 1140 pct = pct < 0.0 ? 0.0 : pct;
f1dc9b30 1141 max = max < 0 ? 0 : max;
1142 t = xcalloc(1, sizeof(refresh_t));
1143 t->pattern = (char *) xstrdup(pattern);
1144 t->compiled_pattern = comp;
1145 t->min = min;
c3f6d204 1146 t->pct = pct;
f1dc9b30 1147 t->max = max;
c3f6d204 1148 if (flags & REG_ICASE)
1149 t->flags.icase = 1;
9f60cfdf 1150#if HTTP_VIOLATIONS
1dfa1d81 1151 if (override_expire)
1152 t->flags.override_expire = 1;
1153 if (override_lastmod)
1154 t->flags.override_lastmod = 1;
cbe3a719 1155 if (reload_into_ims)
1156 t->flags.reload_into_ims = 1;
1157 if (ignore_reload)
1158 t->flags.ignore_reload = 1;
9f60cfdf 1159#endif
f1dc9b30 1160 t->next = NULL;
1161 while (*head)
1162 head = &(*head)->next;
1163 *head = t;
1164 safe_free(pattern);
270b86af 1165}
090089c4 1166
270b86af 1167static void
a47b9029 1168free_refreshpattern(refresh_t ** head)
270b86af 1169{
f1dc9b30 1170 refresh_t *t;
79d39a72 1171 while ((t = *head) != NULL) {
f1dc9b30 1172 *head = t->next;
1173 safe_free(t->pattern);
1174 regfree(&t->compiled_pattern);
1175 safe_free(t);
1176 }
270b86af 1177}
12b9e9b1 1178
270b86af 1179static void
a7d59104 1180dump_string(StoreEntry * entry, const char *name, char *var)
270b86af 1181{
f53b06f9 1182 if (var != NULL)
a7d59104 1183 storeAppendPrintf(entry, "%s %s\n", name, var);
270b86af 1184}
98ffb7e4 1185
270b86af 1186static void
0153d498 1187parse_string(char **var)
270b86af 1188{
1189 char *token = strtok(NULL, w_space);
270b86af 1190 safe_free(*var);
1191 if (token == NULL)
1192 self_destruct();
1193 *var = xstrdup(token);
1194}
b15e6857 1195
0153d498 1196static void
1197free_string(char **var)
1198{
027acbaf 1199 safe_free(*var);
0153d498 1200}
caebbe00 1201
270b86af 1202static void
f1dc9b30 1203parse_eol(char *volatile *var)
270b86af 1204{
1205 char *token = strtok(NULL, null_string);
270b86af 1206 safe_free(*var);
f1dc9b30 1207 if (token == NULL)
1208 self_destruct();
270b86af 1209 *var = xstrdup(token);
1210}
090089c4 1211
270b86af 1212static void
a7d59104 1213dump_time_t(StoreEntry * entry, const char *name, time_t var)
090089c4 1214{
f53b06f9 1215 storeAppendPrintf(entry, "%s %d seconds\n", name, (int) var);
090089c4 1216}
1217
270b86af 1218static void
a47b9029 1219parse_time_t(time_t * var)
0ffd22bc 1220{
f1dc9b30 1221 parseTimeLine(var, T_SECOND_STR);
0ffd22bc 1222}
1223
270b86af 1224static void
a47b9029 1225free_time_t(time_t * var)
270b86af 1226{
a47b9029 1227 *var = 0;
270b86af 1228}
9906e724 1229
1230static void
a7d59104 1231dump_size_t(StoreEntry * entry, const char *name, size_t var)
1b635117 1232{
f53b06f9 1233 storeAppendPrintf(entry, "%s %d\n", name, (int) var);
1b635117 1234}
1235
1236static void
a7d59104 1237dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 1238{
f53b06f9 1239 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
9906e724 1240}
1241
1242static void
a7d59104 1243dump_kb_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 1244{
f53b06f9 1245 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_KBYTES_STR);
9906e724 1246}
1247
1248static void
a47b9029 1249parse_size_t(size_t * var)
1b635117 1250{
1251 char *token;
1252 int i;
1253 GetInteger(i);
1254 *var = (size_t) i;
1255}
1256
1257static void
1258parse_b_size_t(size_t * var)
9906e724 1259{
1260 parseBytesLine(var, B_BYTES_STR);
1261}
1262
1263static void
a47b9029 1264parse_kb_size_t(size_t * var)
9906e724 1265{
1266 parseBytesLine(var, B_KBYTES_STR);
1267}
1268
1269static void
a47b9029 1270free_size_t(size_t * var)
9906e724 1271{
a47b9029 1272 *var = 0;
9906e724 1273}
1274
1b635117 1275#define free_b_size_t free_size_t
9906e724 1276#define free_kb_size_t free_size_t
1277#define free_mb_size_t free_size_t
1278#define free_gb_size_t free_size_t
090089c4 1279
8203a132 1280static void
a7d59104 1281dump_ushort(StoreEntry * entry, const char *name, u_short var)
090089c4 1282{
f53b06f9 1283 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 1284}
090089c4 1285
0153d498 1286static void
a47b9029 1287free_ushort(u_short * u)
0153d498 1288{
1289 *u = 0;
1290}
1291
270b86af 1292static void
1293parse_ushort(u_short * var)
1294{
1295 char *token;
1296 int i;
090089c4 1297
270b86af 1298 GetInteger(i);
1299 if (i < 0)
1300 i = 0;
1301 *var = (u_short) i;
090089c4 1302}
1303
270b86af 1304static void
a7d59104 1305dump_wordlist(StoreEntry * entry, const char *name, wordlist * list)
270b86af 1306{
270b86af 1307 while (list != NULL) {
f53b06f9 1308 storeAppendPrintf(entry, "%s %s\n", name, list->key);
270b86af 1309 list = list->next;
429fdbec 1310 }
429fdbec 1311}
1312
270b86af 1313static void
1314parse_wordlist(wordlist ** list)
429fdbec 1315{
270b86af 1316 char *token;
270b86af 1317 while ((token = strtok(NULL, w_space)))
1318 wordlistAdd(list, token);
429fdbec 1319}
270b86af 1320
f8d9f54a 1321static int
5da06f20 1322check_null_wordlist(wordlist * w)
f8d9f54a 1323{
1324 return w == NULL;
1325}
1326
0153d498 1327#define free_wordlist wordlistDestroy
270b86af 1328
d548ee64 1329#define free_uri_whitespace free_int
1330
1331static void
1332parse_uri_whitespace(int *var)
1333{
1334 char *token = strtok(NULL, w_space);
1335 if (token == NULL)
1336 self_destruct();
1337 if (!strcasecmp(token, "deny"))
1338 *var = URI_WHITESPACE_DENY;
1339 else if (!strcasecmp(token, "allow"))
1340 *var = URI_WHITESPACE_ALLOW;
1341 else if (!strcasecmp(token, "encode"))
1342 *var = URI_WHITESPACE_ENCODE;
1343 else if (!strcasecmp(token, "chop"))
1344 *var = URI_WHITESPACE_CHOP;
1345 else
1346 self_destruct();
1347}
1348
1349
1350static void
1351dump_uri_whitespace(StoreEntry * entry, const char *name, int var)
1352{
1353 char *s;
1354 if (var == URI_WHITESPACE_ALLOW)
1355 s = "allow";
1356 else if (var == URI_WHITESPACE_ENCODE)
1357 s = "encode";
1358 else if (var == URI_WHITESPACE_CHOP)
1359 s = "chop";
1360 else
1361 s = "deny";
1362 storeAppendPrintf(entry, "%s %s\n", name, s);
1363}
1364
270b86af 1365#include "cf_parser.c"
f1dc9b30 1366
1367peer_t
1368parseNeighborType(const char *s)
1369{
1370 if (!strcasecmp(s, "parent"))
1371 return PEER_PARENT;
1372 if (!strcasecmp(s, "neighbor"))
1373 return PEER_SIBLING;
1374 if (!strcasecmp(s, "neighbour"))
1375 return PEER_SIBLING;
1376 if (!strcasecmp(s, "sibling"))
1377 return PEER_SIBLING;
1378 if (!strcasecmp(s, "multicast"))
1379 return PEER_MULTICAST;
1380 debug(15, 0) ("WARNING: Unknown neighbor type: %s\n", s);
1381 return PEER_SIBLING;
1382}
f150dd4b 1383
1384void
1385configFreeMemory(void)
1386{
23ff6968 1387 free_all();
f150dd4b 1388}
f0b19334 1389
1390static void
1391requirePathnameExists(const char *name, const char *path)
1392{
1393 struct stat sb;
f0b19334 1394 assert(path != NULL);
137ee196 1395 if (stat(path, &sb) < 0)
1396 fatalf("%s: %s", path, xstrerror());
f0b19334 1397}