From: rousskov <>
Date: Thu, 26 Feb 1998 06:56:51 +0000 (+0000)
Subject: - Fixed(?) time-tick bug in stat.c. StatCounters where copied in a wrong way
X-Git-Tag: SQUID_3_0_PRE1~3983
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d8035662731fb90a9995af64e22a390a673c14a;p=thirdparty%2Fsquid.git
- Fixed(?) time-tick bug in stat.c. StatCounters where copied in a wrong way
resulting in using the same set of pointers in two objects.
- Added Squid "signature" to all ERR_ pages. The signature is hard-
-coded and is added on-the-fly. The signature may use %-escapes.
Added interface to add more hard-coded responses if needed (see
errorpage.c::error_hard_text).
- Both default and configured directories are searched for ERR_ pages
now. Configured directory is, of course, searched first. This allows
you to customize a subset of ERR_ pages (in a separate directory)
without danger of getting other copies out of sync.
---
diff --git a/ChangeLog b/ChangeLog
index daac8cafbb..92873ce926 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+ - Added Squid "signature" to all ERR_ pages. The signature is hard-
+ -coded and is added on-the-fly. The signature may use %-escapes.
+ Added interface to add more hard-coded responses if needed (see
+ errorpage.c::error_hard_text).
+ - Both default and configured directories are searched for ERR_ pages
+ now. Configured directory is, of course, searched first. This allows
+ you to customize a subset of ERR_ pages (in a separate directory)
+ without danger of getting other copies out of sync.
- Security controls for the SNMP agent added. Besides communities
(like password) and views (part of tree accessible), the snmp_acl
config option can be used to do acl based access checks per
diff --git a/src/defines.h b/src/defines.h
index b0901051fa..3b2aa2f16e 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -209,3 +209,6 @@
#if 0
#define STAT_LOG_HIST_BINS 300
#endif
+
+/* were to look for errors if config path fails */
+#define DEFAULT_SQUID_ERROR_DIR "/usr/local/squid/etc/errors"
diff --git a/src/enums.h b/src/enums.h
index aec7b69adf..ddf3387e3f 100644
--- a/src/enums.h
+++ b/src/enums.h
@@ -45,6 +45,7 @@ typedef enum {
ERR_ACCESS_DENIED,
ERR_CACHE_ACCESS_DENIED,
ERR_CACHE_MGR_ACCESS_DENIED,
+ ERR_SQUID_SIGNATURE, /* not really an error */
ERR_MAX
} err_type;
diff --git a/src/errorpage.cc b/src/errorpage.cc
index 71d9fd1409..b48dc0566e 100644
--- a/src/errorpage.cc
+++ b/src/errorpage.cc
@@ -1,6 +1,6 @@
/*
- * $Id: errorpage.cc,v 1.117 1998/02/21 00:56:54 rousskov Exp $
+ * $Id: errorpage.cc,v 1.118 1998/02/25 23:56:53 rousskov Exp $
*
* DEBUG: section 4 Error Generation
* AUTHOR: Duane Wessels
@@ -38,16 +38,31 @@
#include "squid.h"
+/*
+ * note: hard coded error messages are not appended with %S automagically
+ * to give you more control on the format
+ */
+static const struct { err_type type; const char *text; } error_hard_text[] = {
+ { ERR_SQUID_SIGNATURE,
+ "\n
\n"
+ "
\n"
+ "Generated on %T by %s@%h"
+ }
+};
+static const int error_hard_text_count = sizeof(error_hard_text)/sizeof(*error_hard_text);
static char *error_text[ERR_MAX];
-static const char *errorBuildContent(ErrorState * err, int *len);
+static char *errorTryLoadText(err_type type, const char *dir);
+static char *errorLoadText(err_type type);
+static const char *errorFindHardText(err_type type);
+static MemBuf errorBuildContent(ErrorState * err);
static const char *errorConvert(char token, ErrorState * err);
static CWCB errorSendComplete;
/*
* Function: errorInitialize
*
- * Abstract: This function reads in the error messages formats, and stores
+ * Abstract: This function finds the error messages formats, and stores
* them in error_text[];
*
* Global effects:
@@ -57,25 +72,71 @@ void
errorInitialize(void)
{
err_type i;
+ const char *text;
+ /* find this one first so we can append it to others in errorTryLoadText() */
+ for (i = ERR_NONE + 1; i < ERR_MAX; i++) {
+ safe_free(error_text[i]);
+ /* hard-coded ? */
+ if ((text = errorFindHardText(i)))
+ error_text[i] = xstrdup(text);
+ else
+ error_text[i] = errorLoadText(i);
+ assert(error_text[i]);
+ }
+}
+
+static const char *
+errorFindHardText(err_type type)
+{
+ int i;
+ for (i = 0; i < error_hard_text_count; i++)
+ if (error_hard_text[i].type == type)
+ return error_hard_text[i].text;
+ return NULL;
+}
+
+
+static char *
+errorLoadText(err_type type)
+{
+ /* test configured location */
+ char *text = errorTryLoadText(type, Config.errorDirectory);
+ /* test default location if failed */
+ if (!text && strcmp(Config.errorDirectory, DEFAULT_SQUID_ERROR_DIR))
+ text = errorTryLoadText(type, DEFAULT_SQUID_ERROR_DIR);
+ /* giving up if failed */
+ if (!text)
+ fatal("failed to find or read error text file.");
+ return text;
+}
+
+static char *
+errorTryLoadText(err_type type, const char *dir)
+{
int fd;
char path[MAXPATHLEN];
struct stat sb;
- for (i = ERR_NONE + 1; i < ERR_MAX; i++) {
- snprintf(path, MAXPATHLEN, "%s/%s",
- Config.errorDirectory, err_type_str[i]);
- fd = file_open(path, O_RDONLY, NULL, NULL, NULL);
- if (fd < 0) {
- debug(4, 0) ("errorInitialize: %s: %s\n", path, xstrerror());
- fatal("Failed to open error text file");
- }
- if (fstat(fd, &sb) < 0)
- fatal("fstat() failed on error text file");
- safe_free(error_text[i]);
- error_text[i] = xcalloc(sb.st_size + 1, 1);
- if (read(fd, error_text[i], sb.st_size) != sb.st_size)
- fatal("failed to fully read error text file");
- file_close(fd);
+ char *text;
+
+ snprintf(path, MAXPATHLEN, "%s/%s",
+ dir, err_type_str[type]);
+ fd = file_open(path, O_RDONLY, NULL, NULL, NULL);
+ if (fd < 0 || fstat(fd, &sb) < 0) {
+ debug(4, 0) ("errorTryLoadText: '%s': %s\n", path, xstrerror());
+ if (fd >= 0)
+ file_close(fd);
+ return NULL;
}
+ text = xcalloc(sb.st_size + 2 + 1, 1);
+ if (read(fd, text, sb.st_size) != sb.st_size) {
+ debug(4, 0) ("errorTryLoadText: failed to fully read: '%s': %s\n",
+ path, xstrerror());
+ xfree(text);
+ text = NULL;
+ }
+ file_close(fd);
+ strcat(text, "%S"); /* add signature */
+ return text;
}
void
@@ -232,9 +293,9 @@ errorStateFree(ErrorState * err)
#define CVT_BUF_SZ 512
/*
- * B - URL with FTP %2f hack x
- * c - Squid error code
- * d - seconds elapsed since request received
+ * B - URL with FTP %2f hack x
+ * c - Squid error code x
+ * d - seconds elapsed since request received x
* e - errno x
* E - strerror() x
* f - FTP request line x
@@ -248,6 +309,8 @@ errorStateFree(ErrorState * err)
* p - URL port # x
* P - Protocol x
* R - Full HTTP Request x
+ * S - squid signature from ERR_SIGNATURE x
+ * s - caching proxy software with version x
* t - local time x
* T - UTC x
* U - URL without password x
@@ -326,6 +389,24 @@ errorConvert(char token, ErrorState * err)
case 'R':
p = err->request_hdrs ? err->request_hdrs : "[no request]";
break;
+ case 's':
+ p = full_appname_string;
+ break;
+ case 'S':
+ /* signature may contain %-escapes, recursion */
+ if (err->type != ERR_SQUID_SIGNATURE) {
+ const err_type saved_et = err->type;
+ MemBuf mb;
+ err->type = ERR_SQUID_SIGNATURE;
+ mb = errorBuildContent(err);
+ snprintf(buf, CVT_BUF_SZ, "%s", mb.buf);
+ memBufClean(&mb);
+ err->type = saved_et;
+ } else {
+ /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */
+ p = "[%S]";
+ }
+ break;
case 't':
xstrncpy(buf, mkhttpdlogtime(&squid_curtime), 128);
break;
@@ -363,29 +444,39 @@ errorConvert(char token, ErrorState * err)
HttpReply *
errorBuildReply(ErrorState *err)
{
- int clen;
HttpReply *rep = httpReplyCreate();
- const char *content = errorBuildContent(err, &clen);
+ MemBuf content = errorBuildContent(err);
/* no LMT for error pages; error pages expire immediately */
- httpReplySetHeaders(rep, 1.0, err->http_status, NULL, "text/html", clen, 0, squid_curtime);
- httpBodySet(&rep->body, content, clen+1, NULL);
+ httpReplySetHeaders(rep, 1.0, err->http_status, NULL, "text/html", content.size, 0, squid_curtime);
+ httpBodySet(&rep->body, content.buf, content.size+1, NULL);
+ memBufClean(&content);
return rep;
}
-static const char *
-errorBuildContent(ErrorState * err, int *len)
+static MemBuf
+errorBuildContent(ErrorState * err)
{
+ MemBuf content;
+#if 0 /* use MemBuf so we can support recursion; const pointers: no xstrdup */
LOCAL_ARRAY(char, content, ERROR_BUF_SZ);
int clen;
char *m;
char *mx;
char *p;
+#endif
+ const char *m;
+ const char *p;
const char *t;
assert(err != NULL);
assert(err->type > ERR_NONE && err->type < ERR_MAX);
+#if 0 /* use MemBuf so we can support recursion */
mx = m = xstrdup(error_text[err->type]);
- clen = 0;
+#endif
+ memBufDefInit(&content);
+ m = error_text[err->type];
+ assert(m);
while ((p = strchr(m, '%'))) {
+#if 0 /* use MemBuf so we can support recursion */
*p = '\0'; /* terminate */
xstrncpy(content + clen, m, ERROR_BUF_SZ - clen); /* copy */
clen += (p - m); /* advance */
@@ -398,7 +489,13 @@ errorBuildContent(ErrorState * err, int *len)
clen += strlen(t); /* advance */
if (clen >= ERROR_BUF_SZ)
break;
+#endif
+ memBufAppend(&content, m, p - m); /* copy */
+ t = errorConvert(*++p, err); /* convert */
+ memBufPrintf(&content, "%s", t); /* copy */
+ m = p + 1; /* advance */
}
+#if 0 /* use MemBuf so we can support recursion */
if (clen < ERROR_BUF_SZ && m != NULL) {
xstrncpy(content + clen, m, ERROR_BUF_SZ - clen);
clen += strlen(m);
@@ -411,6 +508,10 @@ errorBuildContent(ErrorState * err, int *len)
if (len)
*len = clen;
xfree(mx);
+#endif
+ if (*m)
+ memBufPrintf(&content, "%s", m); /* copy tail */
+ assert(content.size == strlen(content.buf));
return content;
}
diff --git a/src/stat.cc b/src/stat.cc
index 7e8766a192..f3c2cd3214 100644
--- a/src/stat.cc
+++ b/src/stat.cc
@@ -1,6 +1,6 @@
/*
- * $Id: stat.cc,v 1.207 1998/02/25 09:54:01 rousskov Exp $
+ * $Id: stat.cc,v 1.208 1998/02/25 23:56:54 rousskov Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
@@ -114,6 +114,7 @@ static const char *describeTimestamps(const StoreEntry *);
static void statAvgTick(void *notused);
static void statAvgDump(StoreEntry *, int minutes);
static void statCountersInit(StatCounters *);
+static void statCountersInitSpecial(StatCounters *);
static void statCountersClean(StatCounters *);
static void statCountersCopy(StatCounters *dest, const StatCounters *orig);
static void statCountersDump(StoreEntry * sentry);
@@ -653,7 +654,9 @@ statInit(void)
{
int i;
debug(18, 5) ("statInit: Initializing...\n");
+#if 0 /* we do it in statCountersInit */
memset(CountHist, '\0', N_COUNT_HIST * sizeof(StatCounters));
+#endif
for (i = 0; i < N_COUNT_HIST; i++)
statCountersInit(&CountHist[i]);
statCountersInit(&Counter);
@@ -706,12 +709,20 @@ statAvgTick(void *notused)
NCountHist++;
}
-/* add special cases here as they arrive */
static void
statCountersInit(StatCounters *C)
{
assert(C);
+ memset(C, 0, sizeof(*C));
C->timestamp = current_time;
+
+ statCountersInitSpecial(C);
+}
+
+/* add special cases here as they arrive */
+static void
+statCountersInitSpecial(StatCounters *C)
+{
/*
* HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
*/
@@ -749,12 +760,12 @@ void
statCountersCopy(StatCounters *dest, const StatCounters *orig)
{
assert(dest && orig);
- /* prepare space where to copy */
- statCountersInit(dest);
- /* this should take care of most of the fields */
+ /* this should take care of all the fields, but "special" ones */
memcpy(dest, orig, sizeof(*dest));
- /* now handle spacial cases */
- /* note: we assume that histogram capacities do not change */
+ /* prepare space where to copy special entries */
+ statCountersInitSpecial(dest);
+ /* now handle special cases */
+ /* note: we assert that histogram capacities do not change */
statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
diff --git a/src/structs.h b/src/structs.h
index a4333c13c6..024c68b709 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -974,7 +974,7 @@ struct _StatHist {
/*
* if you add a field to StatCounters,
- * you MUST sync statCountersInit, statCountersClean, and statCountersCopy
+ * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy
*/
struct _StatCounters {
struct {