📄 cache_cf.c
字号:
/* * $Id: cache_cf.c,v 1.324.2.4 1999/04/19 00:14:34 wessels Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#if SQUID_SNMP#include "snmp.h"#endifstatic const char *const T_SECOND_STR = "second";static const char *const T_MINUTE_STR = "minute";static const char *const T_HOUR_STR = "hour";static const char *const T_DAY_STR = "day";static const char *const T_WEEK_STR = "week";static const char *const T_FORTNIGHT_STR = "fortnight";static const char *const T_MONTH_STR = "month";static const char *const T_YEAR_STR = "year";static const char *const T_DECADE_STR = "decade";static const char *const B_BYTES_STR = "bytes";static const char *const B_KBYTES_STR = "KB";static const char *const B_MBYTES_STR = "MB";static const char *const B_GBYTES_STR = "GB";static const char *const list_sep = ", \t\n\r";static int http_header_first = 0;static void self_destruct(void);static void configDoConfigure(void);static void parse_refreshpattern(refresh_t **);static int parseTimeUnits(const char *unit);static void parseTimeLine(time_t * tptr, const char *units);static void parse_ushort(u_short * var);static void parse_string(char **);static void parse_wordlist(wordlist **);static void default_all(void);static void defaults_if_none(void);static int parse_line(char *);static void parseBytesLine(size_t * bptr, const char *units);static size_t parseBytesUnits(const char *unit);static void free_all(void);static void requirePathnameExists(const char *name, const char *path);static OBJH dump_config;static void dump_http_header(StoreEntry * entry, const char *name, HttpHeaderMask header);static void parse_http_header(HttpHeaderMask * header);static void free_http_header(HttpHeaderMask * header);static voidself_destruct(void){ fatalf("Bungled %s line %d: %s", cfg_filename, config_lineno, config_input_line);}voidwordlistDestroy(wordlist ** list){ wordlist *w = NULL; while ((w = *list) != NULL) { *list = w->next; safe_free(w->key); memFree(w, MEM_WORDLIST); } *list = NULL;}wordlist *wordlistAdd(wordlist ** list, const char *key){ while (*list) list = &(*list)->next; *list = memAllocate(MEM_WORDLIST); (*list)->key = xstrdup(key); (*list)->next = NULL; return *list;}voidwordlistCat(const wordlist * w, MemBuf * mb){ while (NULL != w) { memBufPrintf(mb, "%s\n", w->key); w = w->next; }}wordlist *wordlistDup(const wordlist * w){ wordlist *D = NULL; while (NULL != w) { wordlistAdd(&D, w->key); w = w->next; } return D;}voidintlistDestroy(intlist ** list){ intlist *w = NULL; intlist *n = NULL; for (w = *list; w; w = n) { n = w->next; memFree(w, MEM_INTLIST); } *list = NULL;}intintlistFind(intlist * list, int i){ intlist *w = NULL; for (w = list; w; w = w->next) if (w->i == i) return 1; return 0;}/* * Use this #define in all the parse*() functions. Assumes char *token is * defined */#define GetInteger(var) \ token = strtok(NULL, w_space); \ if( token == NULL) \ self_destruct(); \ if (sscanf(token, "%d", &var) != 1) \ self_destruct();intparseConfigFile(const char *file_name){ FILE *fp = NULL; char *token = NULL; char *tmp_line; int err_count = 0; free_all(); default_all(); if ((fp = fopen(file_name, "r")) == NULL) fatalf("Unable to open configuration file: %s: %s", file_name, xstrerror()); cfg_filename = file_name; if ((token = strrchr(cfg_filename, '/'))) cfg_filename = token + 1; memset(config_input_line, '\0', BUFSIZ); config_lineno = 0; while (fgets(config_input_line, BUFSIZ, fp)) { config_lineno++; if ((token = strchr(config_input_line, '\n'))) *token = '\0'; if (config_input_line[0] == '#') continue; if (config_input_line[0] == '\0') continue; debug(3, 5) ("Processing: '%s'\n", config_input_line); tmp_line = xstrdup(config_input_line); if (!parse_line(tmp_line)) { debug(3, 0) ("parseConfigFile: line %d unrecognized: '%s'\n", config_lineno, config_input_line); err_count++; } safe_free(tmp_line); } fclose(fp); defaults_if_none(); configDoConfigure(); cachemgrRegister("config", "Current Squid Configuration", dump_config, 1, 1); return err_count;}static voidconfigDoConfigure(void){ LOCAL_ARRAY(char, buf, BUFSIZ); memset(&Config2, '\0', sizeof(SquidConfig2)); /* init memory as early as possible */ memConfigure(); /* Sanity checks */ if (Config.cacheSwap.swapDirs == NULL) fatal("No cache_dir's specified in config file"); /* calculate Config.Swap.maxSize */ storeDirConfigure(); if (Config.Swap.maxSize < (Config.memMaxSize >> 10)) fatal("cache_swap is lower than cache_mem"); if (Config.Announce.period > 0) { Config.onoff.announce = 1; } else if (Config.Announce.period < 1) { Config.Announce.period = 86400 * 365; /* one year */ Config.onoff.announce = 0; } if (Config.dnsChildren < 1) fatal("No dnsservers allocated"); if (Config.dnsChildren > DefaultDnsChildrenMax) { debug(3, 0) ("WARNING: dns_children was set to a bad value: %d\n", Config.dnsChildren); debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultDnsChildrenMax); Config.dnsChildren = DefaultDnsChildrenMax; } if (Config.Program.redirect) { if (Config.redirectChildren < 1) { Config.redirectChildren = 0; safe_free(Config.Program.redirect); } else if (Config.redirectChildren > DefaultRedirectChildrenMax) { debug(3, 0) ("WARNING: redirect_children was set to a bad value: %d\n", Config.redirectChildren); debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultRedirectChildrenMax); Config.redirectChildren = DefaultRedirectChildrenMax; } } if (Config.Program.authenticate) { if (Config.authenticateChildren < 1) { Config.authenticateChildren = 0; wordlistDestroy(&Config.Program.authenticate); } else if (Config.authenticateChildren > DefaultAuthenticateChildrenMax) { debug(3, 0) ("WARNING: authenticate_children was set to a bad value: %d\n", Config.authenticateChildren); debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultAuthenticateChildrenMax); Config.authenticateChildren = DefaultAuthenticateChildrenMax; } } if (Config.Accel.host) { snprintf(buf, BUFSIZ, "http://%s:%d", Config.Accel.host, Config.Accel.port); Config2.Accel.prefix = xstrdup(buf); Config2.Accel.on = 1; } if (Config.appendDomain) if (*Config.appendDomain != '.') fatal("append_domain must begin with a '.'"); if (Config.errHtmlText == NULL) Config.errHtmlText = xstrdup(null_string); storeConfigure(); if (Config2.Accel.on && !strcmp(Config.Accel.host, "virtual")) vhost_mode = 1; if (Config.Port.http == NULL) fatal("No http_port specified!"); snprintf(ThisCache, sizeof(ThisCache), "%s:%d (%s)", uniqueHostname(), (int) Config.Port.http->i, full_appname_string); /* * the extra space is for loop detection in client_side.c -- we search * for substrings in the Via header. */ snprintf(ThisCache2, sizeof(ThisCache), " %s:%d (%s)", uniqueHostname(), (int) Config.Port.http->i, full_appname_string); if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF) Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF; if (Config.appendDomain) Config.appendDomainLen = strlen(Config.appendDomain); else Config.appendDomainLen = 0; safe_free(debug_options) debug_options = xstrdup(Config.debugOptions); if (Config.retry.timeout < 5) fatal("minimum_retry_timeout must be at least 5 seconds"); if (Config.retry.maxtries > 10) fatal("maximum_single_addr_tries cannot be larger than 10"); if (Config.retry.maxtries < 1) { debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n"); Config.retry.maxtries = 1; } if (Config.referenceAge < 300) { debug(3, 0) ("WARNING: resetting 'reference_age' to 1 week\n"); Config.referenceAge = 86400 * 7; } requirePathnameExists("MIME Config Table", Config.mimeTablePathname); requirePathnameExists("cache_dns_program", Config.Program.dnsserver); requirePathnameExists("unlinkd_program", Config.Program.unlinkd); if (Config.Program.redirect) requirePathnameExists("redirect_program", Config.Program.redirect); if (Config.Program.authenticate) requirePathnameExists("authenticate_program", Config.Program.authenticate->key); requirePathnameExists("Icon Directory", Config.icons.directory); requirePathnameExists("Error Directory", Config.errorDirectory);#if HTTP_VIOLATIONS { const refresh_t *R; for (R = Config.Refresh; R; R = R->next) { if (!R->flags.override_expire) continue; debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n"); break; } for (R = Config.Refresh; R; R = R->next) { if (!R->flags.override_lastmod) continue; debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n"); break; } }#endif if (Config.Wais.relayHost) { if (Config.Wais.peer) cbdataFree(Config.Wais.peer); Config.Wais.peer = memAllocate(MEM_PEER); cbdataAdd(Config.Wais.peer, peerDestroy, MEM_PEER); Config.Wais.peer->host = xstrdup(Config.Wais.relayHost); Config.Wais.peer->http_port = Config.Wais.relayPort; }}/* Parse a time specification from the config file. Store the * result in 'tptr', after converting it to 'units' */static voidparseTimeLine(time_t * tptr, const char *units){ char *token; double d; time_t m; time_t u; if ((u = parseTimeUnits(units)) == 0) self_destruct(); if ((token = strtok(NULL, w_space)) == NULL) self_destruct(); d = atof(token); m = u; /* default to 'units' if none specified */ if (0 == d) (void) 0; else if ((token = strtok(NULL, w_space)) == NULL) debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", config_input_line, d, units); else if ((m = parseTimeUnits(token)) == 0) self_destruct(); *tptr = m * d / u;}static intparseTimeUnits(const char *unit){ if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR))) return 1; if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR))) return 60; if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR))) return 3600; if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR))) return 86400; if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR))) return 86400 * 7; if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR))) return 86400 * 14; if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR))) return 86400 * 30; if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR))) return 86400 * 365.2522; if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR))) return 86400 * 365.2522 * 10; debug(3, 1) ("parseTimeUnits: unknown time unit '%s'\n", unit); return 0;}static voidparseBytesLine(size_t * bptr, const char *units){ char *token; double d; size_t m; size_t u; if ((u = parseBytesUnits(units)) == 0) self_destruct(); if ((token = strtok(NULL, w_space)) == NULL) self_destruct(); d = atof(token); m = u; /* default to 'units' if none specified */ if (0 == d) (void) 0; else if ((token = strtok(NULL, w_space)) == NULL) debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n", config_input_line, d, units); else if ((m = parseBytesUnits(token)) == 0) self_destruct(); *bptr = m * d / u;}static size_tparseBytesUnits(const char *unit){ if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR))) return 1; if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR))) return 1 << 10; if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR))) return 1 << 20; if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR))) return 1 << 30; debug(3, 1) ("parseBytesUnits: unknown bytes unit '%s'\n", unit); return 0;}/***************************************************************************** * Max *****************************************************************************/static voiddump_acl(StoreEntry * entry, const char *name, acl * ae){ wordlist *w; wordlist *v; while (ae != NULL) { debug(3, 3) ("dump_acl: %s %s\n", name, ae->name); v = w = aclDumpGeneric(ae); while (v != NULL) { debug(3, 3) ("dump_acl: %s %s %s\n", name, ae->name, v->key); storeAppendPrintf(entry, "%s %s %s %s\n", name, ae->name, aclTypeToStr(ae->type), v->key); v = v->next; } wordlistDestroy(&w); ae = ae->next; }}static voidparse_acl(acl ** ae){ aclParseAclLine(ae);}static voidfree_acl(acl ** ae){ aclDestroyAcls(ae);}static voiddump_acl_access(StoreEntry * entry, const char *name, acl_access * head){ acl_list *l; while (head != NULL) { storeAppendPrintf(entry, "%s %s", name, head->allow ? "Allow" : "Deny"); for (l = head->acl_list; l != NULL; l = l->next) { storeAppendPrintf(entry, " %s%s", l->op ? null_string : "!", l->acl->name); } storeAppendPrintf(entry, "\n"); head = head->next; }}static voidparse_acl_access(acl_access ** head){ aclParseAccessLine(head);}static voidfree_acl_access(acl_access ** head){ aclDestroyAccessList(head);}static voiddump_address(StoreEntry * entry, const char *name, struct in_addr addr){ storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr));}static voidparse_address(struct in_addr *addr){ const struct hostent *hp; char *token = strtok(NULL, w_space); if (token == NULL) self_destruct(); if (safe_inet_addr(token, addr) == 1) (void) 0; else if ((hp = gethostbyname(token))) /* dont use ipcache */ *addr = inaddrFromHostent(hp); else self_destruct();}static voidfree_address(struct in_addr *addr){ memset(addr, '\0', sizeof(struct in_addr));}#if DELAY_POOLS/* do nothing - free_delay_pool_count is the magic free function. * this is why delay_pool_count isn't just marked TYPE: ushort */#define free_delay_pool_class(X)#define free_delay_pool_access(X)#define free_delay_pool_rates(X)#define dump_delay_pool_class(X, Y, Z)#define dump_delay_pool_access(X, Y, Z)#define dump_delay_pool_rates(X, Y, Z)static voidfree_delay_pool_count(delayConfig * cfg){ int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -