static int check_null_access_log(CustomLog *customlog_definitions);
static void dump_access_log(StoreEntry * entry, const char *name, CustomLog * definitions);
static void free_access_log(CustomLog ** definitions);
+static bool setLogformat(CustomLog *cl, const char *name, const bool dieWhenMissing);
static void update_maxobjsize(void);
static void configDoConfigure(void);
static void
update_maxobjsize(void)
{
- int i;
int64_t ms = -1;
- for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
+ // determine the maximum size object that can be stored to disk
+ for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
assert (Config.cacheSwap.swapDirs[i].getRaw());
- if (dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->
- max_objsize > ms)
- ms = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->max_objsize;
+ const int64_t storeMax = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->maxObjectSize();
+ if (ms < storeMax)
+ ms = storeMax;
}
+
+ // Ensure that we do not discard objects which could be stored only in memory.
+ // It is governed by maximum_object_size_in_memory (for now)
+ // TODO: update this to check each in-memory location (SMP and local memory limits differ)
+ if (ms < static_cast<int64_t>(Config.Store.maxInMemObjSize))
+ ms = Config.Store.maxInMemObjSize;
+
store_maxobjsize = ms;
}
static void
SetConfigFilename(char const *file_name, bool is_pipe)
{
- cfg_filename = file_name;
-
- char const *token;
-
if (is_pipe)
cfg_filename = file_name + 1;
- else if ((token = strrchr(cfg_filename, '/')))
- cfg_filename = token + 1;
+ else
+ cfg_filename = file_name;
}
static const char*
if ((token = strchr(new_file_name, '"')))
*token = '\0';
- cfg_filename = new_file_name;
+ SetConfigFilename(new_file_name, false);
}
config_lineno = new_lineno;
fclose(fp);
}
- cfg_filename = orig_cfg_filename;
+ SetConfigFilename(orig_cfg_filename, false);
config_lineno = orig_config_lineno;
xfree(tmp_line);
memConfigure();
/* Sanity checks */
+ Config.cacheSwap.n_strands = 0; // no diskers by default
if (Config.cacheSwap.swapDirs == NULL) {
/* Memory-only cache probably in effect. */
/* turn off the cache rebuild delays... */
if (Config.Announce.period > 0) {
Config.onoff.announce = 1;
- } else if (Config.Announce.period < 1) {
+ } else {
Config.Announce.period = 86400 * 365; /* one year */
Config.onoff.announce = 0;
}
}
}
+ if (Config.Program.store_id) {
+ if (Config.storeIdChildren.n_max < 1) {
+ Config.storeIdChildren.n_max = 0;
+ wordlistDestroy(&Config.Program.store_id);
+ }
+ }
+
if (Config.appendDomain)
if (*Config.appendDomain != '.')
fatal("append_domain must begin with a '.'");
if (Config.Program.redirect)
requirePathnameExists("redirect_program", Config.Program.redirect->key);
+ if (Config.Program.store_id)
+ requirePathnameExists("store_id_program", Config.Program.store_id->key);
+
requirePathnameExists("Icon Directory", Config.icons.directory);
if (Config.errorDirectory)
(uint32_t)Config.maxRequestBufferSize, (uint32_t)Config.maxRequestHeaderSize);
}
+ /*
+ * Disable client side request pipelining if client_persistent_connections OFF.
+ * Waste of resources queueing any pipelined requests when the first will close the connection.
+ */
+ if (Config.pipeline_max_prefetch > 0 && !Config.onoff.client_pconns) {
+ debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " << Config.pipeline_max_prefetch <<
+ " requires client_persistent_connections ON. Forced pipeline_prefetch 0.");
+ Config.pipeline_max_prefetch = 0;
+ }
+
#if USE_AUTH
/*
* disable client side request pipelining. There is a race with
* pipelining OFF, the client may fail to authenticate, but squid's
* state will be preserved.
*/
- if (Config.onoff.pipeline_prefetch) {
+ if (Config.pipeline_max_prefetch > 0) {
Auth::Config *nego = Auth::Config::Find("Negotiate");
Auth::Config *ntlm = Auth::Config::Find("NTLM");
if ((nego && nego->active()) || (ntlm && ntlm->active())) {
- debugs(3, DBG_IMPORTANT, "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced OFF.");
- Config.onoff.pipeline_prefetch = 0;
+ debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced pipeline_prefetch 0.");
+ Config.pipeline_max_prefetch = 0;
}
}
#endif
}
#endif
-#if USE_SSL
/**
* Parse bytes from a string.
* Similar to the parseBytesLine function but parses the string value instead of
if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2)
self_destruct();
}
-#endif
static size_t
parseBytesUnits(const char *unit)
fs = find_fstype(type_str);
- if (fs < 0)
- self_destruct();
+ if (fs < 0) {
+ debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: This proxy does not support the '" << type_str << "' cache type. Ignoring.");
+ return;
+ }
/* reconfigure existing dir */
p->connection_auth = 2; /* auto */
while ((token = strtok(NULL, w_space))) {
- if (!strcasecmp(token, "proxy-only")) {
+ if (!strcmp(token, "proxy-only")) {
p->options.proxy_only = true;
- } else if (!strcasecmp(token, "no-query")) {
+ } else if (!strcmp(token, "no-query")) {
p->options.no_query = true;
- } else if (!strcasecmp(token, "background-ping")) {
+ } else if (!strcmp(token, "background-ping")) {
p->options.background_ping = true;
- } else if (!strcasecmp(token, "no-digest")) {
+ } else if (!strcmp(token, "no-digest")) {
p->options.no_digest = true;
- } else if (!strcasecmp(token, "no-tproxy")) {
+ } else if (!strcmp(token, "no-tproxy")) {
p->options.no_tproxy = true;
- } else if (!strcasecmp(token, "multicast-responder")) {
+ } else if (!strcmp(token, "multicast-responder")) {
p->options.mcast_responder = true;
#if PEER_MULTICAST_SIBLINGS
- } else if (!strcasecmp(token, "multicast-siblings")) {
+ } else if (!strcmp(token, "multicast-siblings")) {
p->options.mcast_siblings = true;
#endif
- } else if (!strncasecmp(token, "weight=", 7)) {
+ } else if (!strncmp(token, "weight=", 7)) {
p->weight = xatoi(token + 7);
- } else if (!strncasecmp(token, "basetime=", 9)) {
+ } else if (!strncmp(token, "basetime=", 9)) {
p->basetime = xatoi(token + 9);
- } else if (!strcasecmp(token, "closest-only")) {
+ } else if (!strcmp(token, "closest-only")) {
p->options.closest_only = true;
- } else if (!strncasecmp(token, "ttl=", 4)) {
+ } else if (!strncmp(token, "ttl=", 4)) {
p->mcast.ttl = xatoi(token + 4);
if (p->mcast.ttl < 0)
if (p->mcast.ttl > 128)
p->mcast.ttl = 128;
- } else if (!strcasecmp(token, "default")) {
+ } else if (!strcmp(token, "default")) {
p->options.default_parent = true;
- } else if (!strcasecmp(token, "round-robin")) {
+ } else if (!strcmp(token, "round-robin")) {
p->options.roundrobin = true;
- } else if (!strcasecmp(token, "weighted-round-robin")) {
+ } else if (!strcmp(token, "weighted-round-robin")) {
p->options.weighted_roundrobin = true;
#if USE_HTCP
- } else if (!strcasecmp(token, "htcp")) {
+ } else if (!strcmp(token, "htcp")) {
p->options.htcp = true;
- } else if (!strncasecmp(token, "htcp=", 5) || !strncasecmp(token, "htcp-", 5)) {
+ } else if (!strncmp(token, "htcp=", 5) || !strncmp(token, "htcp-", 5)) {
/* Note: The htcp- form is deprecated, replaced by htcp= */
p->options.htcp = true;
char *tmp = xstrdup(token+5);
*nextmode = '\0';
++nextmode;
}
- if (!strcasecmp(mode, "no-clr")) {
+ if (!strcmp(mode, "no-clr")) {
if (p->options.htcp_only_clr)
fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
p->options.htcp_no_clr = true;
- } else if (!strcasecmp(mode, "no-purge-clr")) {
+ } else if (!strcmp(mode, "no-purge-clr")) {
p->options.htcp_no_purge_clr = true;
- } else if (!strcasecmp(mode, "only-clr")) {
+ } else if (!strcmp(mode, "only-clr")) {
if (p->options.htcp_no_clr)
fatalf("parse_peer: can't set htcp no-clr and only-clr simultaneously");
p->options.htcp_only_clr = true;
- } else if (!strcasecmp(mode, "forward-clr")) {
+ } else if (!strcmp(mode, "forward-clr")) {
p->options.htcp_forward_clr = true;
- } else if (!strcasecmp(mode, "oldsquid")) {
+ } else if (!strcmp(mode, "oldsquid")) {
p->options.htcp_oldsquid = true;
} else {
fatalf("invalid HTCP mode '%s'", mode);
}
safe_free(tmp);
#endif
- } else if (!strcasecmp(token, "no-netdb-exchange")) {
+ } else if (!strcmp(token, "no-netdb-exchange")) {
p->options.no_netdb_exchange = true;
- } else if (!strcasecmp(token, "carp")) {
+ } else if (!strcmp(token, "carp")) {
if (p->type != PEER_PARENT)
fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port);
p->options.carp = true;
- } else if (!strncasecmp(token, "carp-key=", 9)) {
+ } else if (!strncmp(token, "carp-key=", 9)) {
if (p->options.carp != true)
fatalf("parse_peer: carp-key specified on non-carp peer %s/%d\n", p->host, p->http_port);
p->options.carp_key.set = true;
for (; key; key = nextkey) {
nextkey=strchr(key,',');
if (nextkey) ++nextkey; // skip the comma, any
- if (0==strncasecmp(key,"scheme",6)) {
+ if (0==strncmp(key,"scheme",6)) {
p->options.carp_key.scheme = true;
- } else if (0==strncasecmp(key,"host",4)) {
+ } else if (0==strncmp(key,"host",4)) {
p->options.carp_key.host = true;
- } else if (0==strncasecmp(key,"port",4)) {
+ } else if (0==strncmp(key,"port",4)) {
p->options.carp_key.port = true;
- } else if (0==strncasecmp(key,"path",4)) {
+ } else if (0==strncmp(key,"path",4)) {
p->options.carp_key.path = true;
- } else if (0==strncasecmp(key,"params",6)) {
+ } else if (0==strncmp(key,"params",6)) {
p->options.carp_key.params = true;
} else {
fatalf("invalid carp-key '%s'",key);
}
}
- } else if (!strcasecmp(token, "userhash")) {
+ } else if (!strcmp(token, "userhash")) {
#if USE_AUTH
if (p->type != PEER_PARENT)
fatalf("parse_peer: non-parent userhash peer %s/%d\n", p->host, p->http_port);
#else
fatalf("parse_peer: userhash requires authentication. peer %s/%d\n", p->host, p->http_port);
#endif
- } else if (!strcasecmp(token, "sourcehash")) {
+ } else if (!strcmp(token, "sourcehash")) {
if (p->type != PEER_PARENT)
fatalf("parse_peer: non-parent sourcehash peer %s/%d\n", p->host, p->http_port);
p->options.sourcehash = true;
- } else if (!strcasecmp(token, "no-delay")) {
+ } else if (!strcmp(token, "no-delay")) {
#if USE_DELAY_POOLS
p->options.no_delay = true;
#else
debugs(0, DBG_CRITICAL, "WARNING: cache_peer option 'no-delay' requires --enable-delay-pools");
#endif
- } else if (!strncasecmp(token, "login=", 6)) {
+ } else if (!strncmp(token, "login=", 6)) {
p->login = xstrdup(token + 6);
rfc1738_unescape(p->login);
- } else if (!strncasecmp(token, "connect-timeout=", 16)) {
+ } else if (!strncmp(token, "connect-timeout=", 16)) {
p->connect_timeout = xatoi(token + 16);
- } else if (!strncasecmp(token, "connect-fail-limit=", 19)) {
+ } else if (!strncmp(token, "connect-fail-limit=", 19)) {
p->connect_fail_limit = xatoi(token + 19);
#if USE_CACHE_DIGESTS
- } else if (!strncasecmp(token, "digest-url=", 11)) {
+ } else if (!strncmp(token, "digest-url=", 11)) {
p->digest_url = xstrdup(token + 11);
#endif
- } else if (!strcasecmp(token, "allow-miss")) {
+ } else if (!strcmp(token, "allow-miss")) {
p->options.allow_miss = true;
- } else if (!strncasecmp(token, "max-conn=", 9)) {
+ } else if (!strncmp(token, "max-conn=", 9)) {
p->max_conn = xatoi(token + 9);
- } else if (!strcasecmp(token, "originserver")) {
+ } else if (!strcmp(token, "originserver")) {
p->options.originserver = true;
- } else if (!strncasecmp(token, "name=", 5)) {
+ } else if (!strncmp(token, "name=", 5)) {
safe_free(p->name);
if (token[5])
p->name = xstrdup(token + 5);
- } else if (!strncasecmp(token, "forceddomain=", 13)) {
+ } else if (!strncmp(token, "forceddomain=", 13)) {
safe_free(p->domain);
if (token[13])
p->connection_auth = 1;
} else if (strcmp(token, "connection-auth=auto") == 0) {
p->connection_auth = 2;
+ } else if (token[0] == '#') {
+ // start of a text comment. stop reading this line.
+ break;
} else {
- debugs(3, DBG_CRITICAL, "parse_peer: token='" << token << "'");
- self_destruct();
+ debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Ignoring unknown cache_peer option '" << token << "'");
}
}
if (token == NULL)
self_destruct();
- if (!strcasecmp(token, "on")) {
+ if (!strcmp(token, "on")) {
*var = 1;
- } else if (!strcasecmp(token, "enable")) {
+ } else if (!strcmp(token, "enable")) {
debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use 'on'.");
*var = 1;
- } else if (!strcasecmp(token, "off")) {
+ } else if (!strcmp(token, "off")) {
*var = 0;
- } else if (!strcasecmp(token, "disable")) {
+ } else if (!strcmp(token, "disable")) {
debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use 'off'.");
*var = 0;
} else {
if (token == NULL)
self_destruct();
- if (!strcasecmp(token, "on")) {
+ if (!strcmp(token, "on")) {
*var = 1;
- } else if (!strcasecmp(token, "enable")) {
+ } else if (!strcmp(token, "enable")) {
debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use value 'on'.");
*var = 1;
- } else if (!strcasecmp(token, "warn")) {
+ } else if (!strcmp(token, "warn")) {
*var = -1;
- } else if (!strcasecmp(token, "off")) {
+ } else if (!strcmp(token, "off")) {
*var = 0;
- } else if (!strcasecmp(token, "disable")) {
+ } else if (!strcmp(token, "disable")) {
debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use value 'off'.");
*var = 0;
} else {
#define free_tristate free_int
+void
+parse_pipelinePrefetch(int *var)
+{
+ char *token = ConfigParser::strtokFile();
+
+ if (token == NULL)
+ self_destruct();
+
+ if (!strcmp(token, "on")) {
+ debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'pipeline_prefetch on' is deprecated. Please update to use 1 (or a higher number).");
+ *var = 1;
+ } else if (!strcmp(token, "off")) {
+ debugs(0, DBG_PARSE_NOTE(2), "WARNING: 'pipeline_prefetch off' is deprecated. Please update to use '0'.");
+ *var = 0;
+ } else {
+ ConfigParser::strtokFileUndo();
+ parse_int(var);
+ }
+}
+
+#define free_pipelinePrefetch free_int
+#define dump_pipelinePrefetch dump_int
+
static void
dump_refreshpattern(StoreEntry * entry, const char *name, RefreshPattern * head)
{
if (token == NULL)
self_destruct();
- if (!strcasecmp(token, "strip"))
+ if (!strcmp(token, "strip"))
*var = URI_WHITESPACE_STRIP;
- else if (!strcasecmp(token, "deny"))
+ else if (!strcmp(token, "deny"))
*var = URI_WHITESPACE_DENY;
- else if (!strcasecmp(token, "allow"))
+ else if (!strcmp(token, "allow"))
*var = URI_WHITESPACE_ALLOW;
- else if (!strcasecmp(token, "encode"))
+ else if (!strcmp(token, "encode"))
*var = URI_WHITESPACE_ENCODE;
- else if (!strcasecmp(token, "chop"))
+ else if (!strcmp(token, "chop"))
*var = URI_WHITESPACE_CHOP;
else {
debugs(0, DBG_PARSE_NOTE(2), "ERROR: Invalid option '" << token << "': 'uri_whitespace' accepts 'strip', 'deny', 'allow', 'encode', and 'chop'.");
peer_t
parseNeighborType(const char *s)
{
- if (!strcasecmp(s, "parent"))
+ if (!strcmp(s, "parent"))
return PEER_PARENT;
- if (!strcasecmp(s, "neighbor"))
+ if (!strcmp(s, "neighbor"))
return PEER_SIBLING;
- if (!strcasecmp(s, "neighbour"))
+ if (!strcmp(s, "neighbour"))
return PEER_SIBLING;
- if (!strcasecmp(s, "sibling"))
+ if (!strcmp(s, "sibling"))
return PEER_SIBLING;
- if (!strcasecmp(s, "multicast"))
+ if (!strcmp(s, "multicast"))
return PEER_MULTICAST;
debugs(15, DBG_CRITICAL, "WARNING: Unknown neighbor type: " << s);
self_destruct();
}
s->flags.accelSurrogate = true;
- s->vhost = 1;
+ s->vhost = true;
} else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
if (s->flags.accelSurrogate || s->flags.tproxyIntercept) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Intercept mode requires its own interception port. It cannot be shared with other modes.");
s->flags.tproxyIntercept = true;
Ip::Interceptor.StartTransparency();
/* Log information regarding the port modes under transparency. */
- debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s);
- debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)");
+ debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");
if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work.");
debugs(3, DBG_CRITICAL, "WARNING: http(s)_port: vhost option is deprecated. Use 'accel' mode flag instead.");
}
s->flags.accelSurrogate = true;
- s->vhost = 1;
+ s->vhost = true;
} else if (strcmp(token, "no-vhost") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: no-vhost option requires Acceleration mode flag.");
}
- s->vhost = 0;
+ s->vhost = false;
} else if (strcmp(token, "vport") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: allow-direct option requires Acceleration mode flag.");
self_destruct();
}
- s->allow_direct = 1;
+ s->allow_direct = true;
} else if (strcmp(token, "act-as-origin") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: act-as-origin option requires Acceleration mode flag.");
} else
- s->actAsOrigin = 1;
+ s->actAsOrigin = true;
} else if (strcmp(token, "ignore-cc") == 0) {
#if !USE_HTTP_VIOLATIONS
if (!s->flags.accelSurrogate) {
self_destruct();
}
#endif
- s->ignore_cc = 1;
+ s->ignore_cc = true;
} else if (strncmp(token, "name=", 5) == 0) {
safe_free(s->name);
s->name = xstrdup(token + 5);
} else if (strcmp(token, "connection-auth=on") == 0) {
s->connection_auth_disabled = false;
} else if (strncmp(token, "disable-pmtu-discovery=", 23) == 0) {
- if (!strcasecmp(token + 23, "off"))
+ if (!strcmp(token + 23, "off"))
s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
- else if (!strcasecmp(token + 23, "transparent"))
+ else if (!strcmp(token + 23, "transparent"))
s->disable_pmtu_discovery = DISABLE_PMTU_TRANSPARENT;
- else if (!strcasecmp(token + 23, "always"))
+ else if (!strcmp(token + 23, "always"))
s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
else
self_destruct();
self_destruct();
}
} else if (strcmp(token, "tcpkeepalive") == 0) {
- s->tcp_keepalive.enabled = 1;
+ s->tcp_keepalive.enabled = true;
} else if (strncmp(token, "tcpkeepalive=", 13) == 0) {
char *t = token + 13;
- s->tcp_keepalive.enabled = 1;
- s->tcp_keepalive.idle = xatoui(t);
+ s->tcp_keepalive.enabled = true;
+ s->tcp_keepalive.idle = xatoui(t,',');
t = strchr(t, ',');
if (t) {
++t;
- s->tcp_keepalive.interval = xatoui(t);
+ s->tcp_keepalive.interval = xatoui(t,',');
t = strchr(t, ',');
}
if (t) {
++t;
s->tcp_keepalive.timeout = xatoui(t);
- // t = strchr(t, ','); // not really needed, left in as documentation
}
#if USE_SSL
- } else if (strcasecmp(token, "sslBump") == 0) {
+ } else if (strcmp(token, "sslBump") == 0) {
debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
"in http_port. Use 'ssl-bump' instead.");
s->flags.tunnelSslBumping = true;
}
#if USE_SSL
- if (strcasecmp(protocol, "https") == 0) {
+ if (strcmp(protocol, "https") == 0) {
/* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */
const bool hijacked = s->flags.isIntercepted();
if (s->flags.tunnelSslBumping && !hijacked) {
#include "AccessLogEntry.h"
+/**
+ * We support several access_log configuration styles:
+ *
+ * #1: Deprecated ancient style without an explicit logging module:
+ * access_log /var/log/access.log
+ *
+ * #2: The "none" logging module (i.e., no logging [of matching transactions]):
+ * access_log none [acl ...]
+ *
+ * #3: Configurable logging module without named options:
+ * Logformat or the first ACL name, whichever comes first, may not contain '='.
+ * If no explicit logformat name is given, the first ACL name, if any,
+ * should not be an existing logformat name or it will be treated as such.
+ * access_log module:place [logformat_name] [acl ...]
+ *
+ * #4: Configurable logging module with name=value options such as logformat=x:
+ * The first ACL name may not contain '='.
+ * access_log module:place [option ...] [acl ...]
+ *
+ */
static void
parse_access_log(CustomLog ** logs)
{
- const char *filename, *logdef_name;
-
CustomLog *cl = (CustomLog *)xcalloc(1, sizeof(*cl));
- if ((filename = strtok(NULL, w_space)) == NULL) {
+ // default buffer size and fatal settings
+ cl->bufferSize = 8*MAX_URL;
+ cl->fatal = true;
+
+ /* determine configuration style */
+
+ const char *filename = strtok(NULL, w_space);
+ if (!filename) {
self_destruct();
return;
}
return;
}
- if ((logdef_name = strtok(NULL, w_space)) == NULL)
- logdef_name = "squid";
+ cl->filename = xstrdup(filename);
+ cl->type = Log::Format::CLF_UNKNOWN;
+
+ const char *token = ConfigParser::strtokFile();
+ if (!token) { // style #1
+ // no options to deal with
+ } else if (!strchr(token, '=')) { // style #3
+ // if logformat name is not recognized,
+ // put back the token; it must be an ACL name
+ if (!setLogformat(cl, token, false))
+ ConfigParser::strtokFileUndo();
+ } else { // style #4
+ do {
+ if (strncasecmp(token, "on-error=", 9) == 0) {
+ if (strncasecmp(token+9, "die", 3) == 0) {
+ cl->fatal = true;
+ } else if (strncasecmp(token+9, "drop", 4) == 0) {
+ cl->fatal = false;
+ } else {
+ debugs(3, DBG_CRITICAL, "Unknown value for on-error '" <<
+ token << "' expected 'drop' or 'die'");
+ self_destruct();
+ }
+ } else if (strncasecmp(token, "buffer-size=", 12) == 0) {
+ parseBytesOptionValue(&cl->bufferSize, B_BYTES_STR, token+12);
+ } else if (strncasecmp(token, "logformat=", 10) == 0) {
+ setLogformat(cl, token+10, true);
+ } else if (!strchr(token, '=')) {
+ // put back the token; it must be an ACL name
+ ConfigParser::strtokFileUndo();
+ break; // done with name=value options, now to ACLs
+ } else {
+ debugs(3, DBG_CRITICAL, "Unknown access_log option " << token);
+ self_destruct();
+ }
+ } while ((token = ConfigParser::strtokFile()) != NULL);
+ }
+
+ // set format if it has not been specified explicitly
+ if (cl->type == Log::Format::CLF_UNKNOWN)
+ setLogformat(cl, "squid", true);
- debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'");
+ aclParseAclList(LegacyParser, &cl->aclList);
- cl->filename = xstrdup(filename);
+ while (*logs)
+ logs = &(*logs)->next;
+
+ *logs = cl;
+}
+
+/// sets CustomLog::type and, if needed, CustomLog::lf
+/// returns false iff there is no named log format
+static bool
+setLogformat(CustomLog *cl, const char *logdef_name, const bool dieWhenMissing)
+{
+ assert(cl);
+ assert(logdef_name);
+
+ debugs(3, 9, "possible " << cl->filename << " logformat: " << logdef_name);
+
+ if (cl->type != Log::Format::CLF_UNKNOWN) {
+ debugs(3, DBG_CRITICAL, "Second logformat name in one access_log: " <<
+ logdef_name << " " << cl->type << " ? " << Log::Format::CLF_NONE);
+ self_destruct();
+ return false;
+ }
/* look for the definition pointer corresponding to this name */
Format::Format *lf = Log::TheConfig.logformats;
cl->type = Log::Format::CLF_USERAGENT;
} else if (strcmp(logdef_name, "referrer") == 0) {
cl->type = Log::Format::CLF_REFERER;
- } else {
+ } else if (dieWhenMissing) {
debugs(3, DBG_CRITICAL, "Log format '" << logdef_name << "' is not defined");
self_destruct();
- return;
+ return false;
+ } else {
+ return false;
}
- aclParseAclList(LegacyParser, &cl->aclList);
-
- while (*logs)
- logs = &(*logs)->next;
-
- *logs = cl;
+ return true;
}
static int