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