sqcwa-0.3/ 0040755 0001750 0001750 00000000000 07636206455 011557 5 ustar cprov cprov sqcwa-0.3/Makefile 0100644 0001750 0001750 00000001144 07631451331 013202 0 ustar cprov cprov CFLAGS=-Wall -O2
all: sqcwa
distclean: clean
rm -fv *~
clean:
rm -fv *.o sqcwa
sqcwa: url.o sqclient.o htmlchk.o sqcwa.o watchlog.o daemon.o
install: sqcwa
mkdir -p $(DESTDIR)/usr/sbin/
install -m 0755 sqcwa $(DESTDIR)/usr/sbin/sqcwa
mkdir -p $(DESTDIR)/etc/init.d/
install -m 0755 sqcwa.init.d $(DESTDIR)/etc/init.d/sqcwa
uninstall:
rm -fv $(DESTDIR)/usr/sbin/sqcwa $(DESTDIR)/etc/init.d/sqcwa
# squid in Debian starts at sequence 30. lets start sqcwa
# before squid is running (sequence 31) and stop it before
# squid dies (sequence 29).
# update-rc.d sqcwa start 31 2 3 4 5 . stop 29 0 1 6 .
sqcwa-0.3/README 0100644 0001750 0001750 00000004231 07631447777 012445 0 ustar cprov cprov sqcwa -- workaround for squid not caching pages with
or others
Copyright (C) 2003 Pedro Zorzenon Neto
José Roberto Monteiro
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-1307 USA
--
This program reads squid/access.log, analyses it and searches inside
all text/html objects for some tags, and if found, tells
squidclient to purge the page.
This program is in TESTING stage.
To use it, install squid and squidclient in the computer, and
execute the following command:
sqcwa /var/log/squid/access.log
It will expect that you have installed the program client from squid
in /usr/bin/squidclient. If you do not have it there, then use a
symbolic link or change SQCLIENT.H in the sources.
It will expect to find squid running in localhost tcp port 3128.
Note: this program will only run if executed in the same
computer where squid is installed.
I'd apreciate your comments about this program. This is a TESTING
version and we need to know how it is working. Write to
with subject sqcwa.
We tried to make this program without any security hole, but we are not
sure about it.
Known side effects of using it:
- increases CPU load (not too much. in out tests, less than 1%
in a pentium 2 300MHz, with 5 browsers using proxy)
- does not work if someone navigates from localhost
- increase access.log lines with accesses from localhost
(check and purge access)
SQCWA means SQuid Cache Work-Around
sqcwa-0.3/sqcwa.c 0100644 0001750 0001750 00000011244 07631441763 013036 0 ustar cprov cprov /*
sqcwa -- workaround for squid not caching pages with
or others
Copyright (C) 2003 Pedro Zorzenon Neto
José Roberto Monteiro
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-1307 USA
*/
/* memory debug */
//#define MEMDEBUG
/* verbose mode, usefull for debug */
//#define SQCWA_VERBOSE
/* undefine to run in the command line for debugging */
#define SQCWA_DAEMON_MODE
#define PIDBASEFILENAME "sqcwa"
/* run with privileges of user 'proxy'
* Debian systems, its uid and gid are 13
* if you do not want the program to drop
* privileges, use UID -1 and GID -1.
* drop privileges is only enabled in daemon_mode */
#define SQCWA_PROXY_UID 13
#define SQCWA_PROXY_GID 13
/* PID file */
#define SQCWA_VERSION "0.3"
#include "common.h"
#include "htmlchk.h"
#include "sqclient.h"
#include "watchlog.h"
#include "daemon.h"
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char * argv[]) {
char * ss, * sn, * si, * sdata[4];
int i, error;
int http_code;
htmlchk_t * ht;
watchlog_t * wl;
#ifdef SQCWA_DAEMON_MODE
run_daemon_run (PIDBASEFILENAME, SQCWA_PROXY_UID, SQCWA_PROXY_GID);
#endif
/* IMPROVE compare argv to --version, -v, --help, -h */
fprintf(stderr,"sqcwa - SQuid Cache WorkAround\n"
"Version: " SQCWA_VERSION "\n"
"Website: http://www.autsens.com/sqcwa/\n"
"Usage: sqcwa [logfilename]\n"
"\n"
"sqcwa is running now...\n");
ht = htmlchk_init ();
if (argc>1)
{ /* user defined logfile */
wl = watchlog_init (argv[1]);
}
else
{ /* default logfile */
fprintf(stderr,"WARNING: you did not specify a logfilename\n"
" will use '/var/log/squid/access.log'\n");
wl = watchlog_init ("/var/log/squid/access.log");
}
// while ((ss = fgets(s, LOGLINEMAXSIZE, stdin))) {
while (1) {
int idata = 0;
// fprintf(stderr,"will getline\n");
watchlog_getline(wl);
// fprintf(stderr," gotline %s\n", wl->data);
ss = wl->data;
#ifdef MEMDEBUG
fprintf(stderr,"memory allocated: %d\n",mallinfo().arena);
#endif
#ifdef SQCWA_VERBOSE
fprintf(stderr,"\nfound log line: %s",ss);
#endif
error = 0;
// s[LOGLINEMAXSIZE-1] = '\0'; // end line safety
//if (strlen(s) >= LOGLINEMAXSIZE) // verify line size
// continue; // skips if it has the maximum size
//sn = ss = strdup(s); // copies line
sn = ss;
for (i = 0; i < 4; i++)
sdata[i] = NULL;
i = 0;
while ((si = strsep(& sn, " \t\n\r"))) {
if (i > 10) {
error = 1;
break;
}
if (si && strlen(si)) {
switch (i) {
case 2:
case 3:
case 6:
case 9:
sdata[idata++] = strdup(si);
break;
}
i++;
}
}
if (i < 10) {
error |= 2;
}
if (! error) {
http_code = -1;
for (i = 0; i < strlen(sdata[1]) - 1; i++) {
if (sdata[1][i] == '/') {
sdata[1][i+2] = '\0';
http_code = atoi(sdata[1]+i+1);
}
}
if (strcmp(sdata[0], "127.0.0.1") != 0 &&
strcmp(sdata[3], "text/html") == 0 &&
(http_code == 2 || http_code == 3)) {
#ifdef SQCWA_VERBOSE
fprintf(stderr," will open and check this html file. decision = ");
#endif
if (htmlchk_pagestate(ht,sdata[2]) == 2)
{
#ifdef SQCWA_VERBOSE
fprintf(stderr,"need to PURGE\n");
#endif
sqclient_purge_from_cache(sdata[2]);
}
else
{
#ifdef SQCWA_VERBOSE
fprintf(stderr,"nothing to do\n");
#endif
}
}
else
{
#ifdef SQCWA_VERBOSE
fprintf(stderr," no need to check this logline\n");
/* "IP = %s HTTP Code = %d "
" Mime = %s\nURL = %s\n",
sdata[0], http_code, sdata[3], sdata[2]); */
#endif
}
}
else {
fprintf(stderr," Error parsing logfile line. error code: %d\n", error);
}
for (i = 0; i < 4; i++)
if (sdata[i])
free(sdata[i]);
//free(ss);
}
htmlchk_destroy(ht);
watchlog_destroy(wl);
return 0;
}
sqcwa-0.3/sqclient.c 0100644 0001750 0001750 00000004463 07631415275 013546 0 ustar cprov cprov /*
sqclient -- gets a page from squid cache or purge it
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#include "htmlchk.h"
#include "sqclient.h"
#include "url.h"
#include
#include
#include
#include
#include
#include
#include
/* debug purposes */
//#define SQCLIENT_VERBOSE
int sqclient_retrieve_if_in_cache (char * url, char * outfile) {
int i;
char * s;
char * urlf;
urlf = malloc ((strlen(url)*3)+1);
assert (urlf != NULL);
url_filter (url, urlf);
s = malloc (strlen(urlf)+200);
assert (s != NULL);
sprintf(s, SQUIDCLIENT " "
SQUIDCLIENTARGS " "
" -m GET "
"-H \"Cache-control: Only-if-cached\\n\" "
"'%s' "
"> %s 2>/dev/null", urlf, outfile);
#ifdef SQCLIENT_VERBOSE
fprintf(stderr,"sqclient: checking cache: %s\n",urlf);
#endif
i=system(s);
if (i!=0)
{
fprintf(stderr,"sqclient: system call failed. ERR:%d CMD:%s\n",i,s);
}
free(urlf);
free(s);
if (i == 0)
{
return 1;
}
return 0;
}
void sqclient_purge_from_cache(char * url) {
int i;
char * s;
char * urlf;
#ifdef SQCLIENT_VERBOSE
fprintf(stderr,"sqclient: PURGING from cache: %s\n",url);
#endif
urlf = malloc ((strlen(url)*3)+1);
assert (urlf != NULL);
url_filter (url, urlf);
s = malloc (strlen(urlf)+200);
assert (s != NULL);
sprintf(s, SQUIDCLIENT " "
SQUIDCLIENTARGS " "
"-m PURGE "
"'%s' "
"> /dev/null 2>&1", urlf);
i=system(s);
if (i!=0)
{
fprintf(stderr,"sqclient: system call failed. ERR:%d CMD:%s\n",i,s);
}
free(urlf);
free(s);
}
sqcwa-0.3/Changelog 0100644 0001750 0001750 00000000533 07631451707 013364 0 ustar cprov cprov sqcwa (0.3)
* Added daemon feature.
* Added logfile watch feature.
* Changed from three numbers (0.0.2) to two numbers (0.3) version.
-- Pedro Zorzenon Neto Wed, 5 Mar 2003 16:44:51 -0300
sqcwa (0.0.2)
* Memory leak bugfix in htmlchk.c
-- Pedro Zorzenon Neto Thu, 30 Jan 2003 11:38:10 -0200
sqcwa-0.3/watchlog.h 0100644 0001750 0001750 00000003026 07631442164 013530 0 ustar cprov cprov /*
watchlog -- reads lines from logfile. checks if name has changed
and if file has new data.
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#ifndef _WATCHLOG_H
#define _WATCHLOG_H
#include /* for FILE type */
struct watchlog {
char * fn; /* logfile name */
struct stat * fs; /* logfile status */
int is_at_eof; /* indicates that fileposition is at eof */
char * data; /* last line read from logfile */
FILE * fh; /* logfile handle */
};
#define watchlog_t struct watchlog
/* this function does not fail. it retries if failed and returns
* only when it succeeds */
watchlog_t * watchlog_init (char * logfilename);
/* this function blocks the program until there is data available */
void watchlog_getline (watchlog_t * self);
void watchlog_destroy (watchlog_t * self);
#endif
sqcwa-0.3/common.h 0100644 0001750 0001750 00000000160 07631350613 013201 0 ustar cprov cprov #ifndef _COMMON_H
#define _COMMON_H
/* maximun size of a squid log line */
#define LOGLINEMAXSIZE 8200
#endif
sqcwa-0.3/htmlchk.c 0100644 0001750 0001750 00000013651 07616224216 013351 0 ustar cprov cprov /*
htmlchk -- checks if page has directives to explicit disable caching
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#include "htmlchk.h"
#include "sqclient.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define TMPFILE_TIMEOUT 50
#define BUFSIZE 32768
/* testing and debug purposes
#define HTMLCHKTEST
#define VERBOSE */
htmlchk_t * htmlchk_init (void) {
htmlchk_t * self;
char * fn = NULL;
int maxtry = TMPFILE_TIMEOUT;
while ( (fn==NULL) && (maxtry>0) )
{
int fd;
/* I want "tmpnam", not "mkstemp", ignore warning when compiling */
fn = tmpnam(NULL);
fd = open(fn, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd == -1)
{
/* open error */
maxtry--;
fn=NULL;
}
else
{
close(fd);
}
}
if (fn==NULL)
{
fprintf(stderr, "Could not create a unique temporary file.\n");
abort();
}
self = malloc (sizeof(htmlchk_t));
assert(self != NULL);
self->tmpfile = malloc (strlen(fn)+1);
assert(self->tmpfile != NULL);
strcpy(self->tmpfile, fn);
return self;
}
int htmlchk_pagestate (htmlchk_t * self, char * url) {
int comment = 0;
int state=-1;
char *buf;
ssize_t size;
int i, fd;
i = sqclient_retrieve_if_in_cache (url, self->tmpfile);
if (i != 1)
{
/* did not find page in cache */
return 0;
}
/* page is in cache, lets scan it */
fd = open (self->tmpfile, O_RDONLY);
if ( fd == -1 )
{
fprintf(stderr, "could not open html tmpfile for scanning.\n");
return -1;
}
buf = calloc ( BUFSIZE, 1);
size = read (fd, buf, BUFSIZE-7); /* 7 is the lucky number :-) */
for (i=0; i", buf+i, 3) == 0)
{
comment=0;
i+=3;
}
if (comment==0) {
if (*(buf+i)=='<')
{
int tagbegin=i;
int tagend=i;
while ( (tagend<(BUFSIZE-1)) &&
( *(buf+tagend) != '>') )
{
tagend++;
if (*(buf+tagend)=='<')
{
/* found '<' inside a tag... */
tagend=BUFSIZE;
}
}
if ( (tagend!=BUFSIZE) &&
( (tagend-tagbegin) > 2 ) )
{
/* tag has begin and end */
int j;
int k=0;
char *meta;
meta = malloc (tagend-tagbegin-1);
for (j=(tagbegin+1); j0x2F) && (c<0x3A) ) ||
( (c>0x40) && (c<0x5B) ) ||
( (c>0x60) && (c<0x7B) ) )
{
*(meta+k)=c;
k++;
}
}
*(meta+k)=0; /* end of string */
if ( (strcasecmp("/head",meta)==0) ||
(strcasecmp("body",meta)==0) )
{
/* or found...
* will not find outside or inside */
#ifdef VERBOSE
fprintf(stderr, "end of element or begin of "
" element found\n");
#endif
state=1;
}
if ( strcasecmp("metahttp-equiv=pragmacontent=no-cache",
meta)==0)
{
/* found the right tag */
#ifdef VERBOSE
fprintf(stderr, " found\n");
#endif
state=2;
}
if ( strcasecmp("metahttp-equiv=cache-controlcontent=no-cache",
meta)==0)
{
/* found the right tag */
#ifdef VERBOSE
fprintf(stderr, " found\n");
#endif
state=2;
}
if ( strcasecmp("metahttp-equiv=expirescontent=0",
meta)==0)
{
/* found the right tag */
#ifdef VERBOSE
fprintf(stderr, " found\n");
#endif
state=2;
}
if ( strcasecmp("metahttp-equiv=expirescontent=-1",
meta)==0)
{
/* found the right tag */
#ifdef VERBOSE
fprintf(stderr, " found\n");
#endif
state=2;
}
free(meta);
i=tagend+1;
}
}
}
if (state != -1)
{
break;
}
} /* end of for (i=0; itmpfile != NULL)
{
remove(self->tmpfile);
free(self->tmpfile);
}
free(self);
}
}
#ifdef HTMLCHKTEST
int main() {
struct htmlchk *ht;
char url[1024];
int i;
ht=htmlchk_init();
printf("htmlchk tmpfilename: '%s'\n", ht->tmpfile);
strcpy (url, "http://www.autsens.com/teste-0.htm");
i = htmlchk_pagestate (ht, url);
printf ("htmlchk %s pagestate=%d\n", url, i);
if (i == 2)
{
printf("state is 2, purging from cache\n");
sqclient_purge_from_cache(url);
}
printf("\n");
strcpy (url, "http://www.autsens.com/teste-3.htm");
i = htmlchk_pagestate (ht, url);
printf ("htmlchk %s pagestate=%d\n", url, i);
if (i == 2)
{
printf("state is 2, purging from cache\n");
sqclient_purge_from_cache(url);
}
htmlchk_destroy(ht);
return 0;
}
#endif
sqcwa-0.3/watchlog.c 0100644 0001750 0001750 00000016727 07631417723 013542 0 ustar cprov cprov /*
watchlog -- reads lines from logfile. checks if name has changed
and if file has new data.
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
/* NOTA: I tried to use "Interrupt I/O" described in libc info page
* with SIGIO and O_ASYNC, but my try was not successful.
* then I used a pool mode with file attributes, checking if file
* size has changed or if file has changed by a logrotate
* (device/inode) */
//#define WATCHLOG_DEBUG
//#define WATCHLOG_TEST
#include "watchlog.h"
#include "common.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define AT_BOF 1 /* begin-of-file */
#define AT_EOF 2 /* end-of-file */
#define WATCHLOG_INIT_CAN_ABORT /* watchlog_init will abort program
* if could not find the logfile.
* if not defined, watchlog_init will
* retry to open file every 10 senconds */
/* private functions */
int stat_withretry (char * fn, struct stat * fs);
FILE * logfile_open (watchlog_t * self, int where);
/* end of private functions */
watchlog_t * watchlog_init (char * logfilename) {
watchlog_t * self;
self = malloc (sizeof (watchlog_t));
assert (self != NULL);
self->fn = malloc (sizeof(char) * (strlen (logfilename) + 1));
assert (self->fn != NULL);
strcpy (self->fn, logfilename);
self->fs = malloc (sizeof (struct stat));
assert (self->fs != NULL);
self->data = malloc (sizeof(char) * LOGLINEMAXSIZE);
assert(self->data != NULL);
strcpy(self->data,"");
self->fh = NULL;
#ifdef WATCHLOG_INIT_CAN_ABORT
if (stat(self->fn, self->fs) != 0) {
fprintf(stderr,"logfile name: %s\n", self->fn);
perror("logfile open: stat");
abort();
}
#endif
while (self->fh == NULL)
{
stat_withretry (self->fn, self->fs);
self->fh = logfile_open (self, AT_EOF);
if (self->fh == NULL)
{
/* open failed */
sleep (1);
}
}
self->is_at_eof = 1;
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_init\n");
#endif
return self;
}
void watchlog_destroy (watchlog_t * self) {
if (self != NULL)
{
if (self->fh != NULL)
{
fclose (self->fh);
}
if (self->fn != NULL)
{
free (self->fn);
}
if (self->data != NULL)
{
free (self->data);
}
free(self);
}
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_destroy\n");
#endif
}
int stat_withretry (char * fn, struct stat * fs) {
int firsttime = 1;
int retval = -1;
int no_need_to_retry = 1;
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_stat_withretry begin\n");
#endif
while (retval != 0)
{
retval=stat(fn, fs);
if (retval != 0)
{
/* something failed. wait sometime before retry */
#ifdef WATCHLOG_DEBUG
perror("stat");
fprintf(stderr,"filename %s\n",fn);
fprintf(stderr,"watchlog_stat_withretry retry\n");
#endif
no_need_to_retry = 0;
if (firsttime)
{
sleep(1);
}
else
{
sleep(10);
}
}
firsttime = 0;
}
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_stat_withretry end '%d'\n", no_need_to_retry);
#endif
return no_need_to_retry;
}
FILE * logfile_open (watchlog_t * self, int where) {
FILE * fh;
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_logfile_open begin\n");
#endif
/* open log file */
fh = fopen(self->fn, "r");
if (fh == NULL)
{
/* open failed */
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_logfile_open failed\n");
#endif
return NULL;
}
switch (where) {
case AT_BOF:
/* nothing to do, fopen already opens at begin-of-file */
break;
case AT_EOF:
/* go to end-of-file */
if ( fseek (fh, 0, SEEK_END) != 0 )
{
/* end-of-file failed */
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_logfile_fseek failed\n");
#endif
fclose (fh);
fh = NULL;
}
break;
default:
assert(0);
}
return fh;
}
void watchlog_getline (watchlog_t * self) {
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_getline begin\n");
#endif
if (self->is_at_eof == 0)
{
/* there is data available */
if (feof (self->fh))
{
/* just a protection. should never enter here */
assert(0);
self->is_at_eof = 1;
clearerr (self->fh); /* clear eof flag */
watchlog_getline(self);
return;
}
if (fgets(self->data, LOGLINEMAXSIZE, self->fh) != NULL)
{
self->is_at_eof = 0;
#ifdef WATCHLOG_DEBUG
printf("getline: %s",self->data);
#endif
return;
}
else
{
/* could not read... then should be at eof */
self->is_at_eof = 1;
if (feof(self->fh))
{
clearerr (self->fh); /* clear eof flag */
}
watchlog_getline(self);
return;
}
return;
}
else
{
/* need to check if there is data available */
struct stat * fsn;
fsn = malloc(sizeof(struct stat));
assert (fsn != NULL);
while (1) {
int need_reopen = 0;
int has_newdata = 0;
if (stat_withretry(self->fn, fsn) == 0)
{
need_reopen = 1;
}
else if (memcmp(fsn, self->fs, sizeof(struct stat)) != 0)
{
/* something has changed */
if ( (fsn->st_dev != self->fs->st_dev) ||
(fsn->st_ino != self->fs->st_ino) ||
(fsn->st_size < self->fs->st_size) ) /* file is shorter */
{
/* file device or inode has changed */
need_reopen=1;
}
else if (fsn->st_size != self->fs->st_size)
{
/* file size has changed */
has_newdata = 1;
}
}
memcpy(self->fs, fsn, sizeof(struct stat));
if (need_reopen == 1)
{
/* we need to reopen the file */
fclose (self->fh);
self->fh = NULL;
while (self->fh == NULL)
{
stat_withretry (self->fn, fsn);
self->fh = logfile_open (self, AT_BOF);
if (self->fh == NULL)
{
/* open failed */
sleep (1);
}
}
fprintf(stderr,"WARNING: lost logfile handler. will reopen "
"logfile now -- this occours when file is truncated "
"or when file inode changes (maybe it was just "
"'logrotate' doing its job).\n");
/* file is reopened now and fileposition is at BOF */
/* lets assume that the file is new, then we need to parse
* data from its begin */
has_newdata = 1;
}
if (has_newdata == 1)
{
if (fgets(self->data, LOGLINEMAXSIZE, self->fh) != NULL)
{
self->is_at_eof = 0;
#ifdef WATCHLOG_DEBUG
fprintf(stderr,"watchlog_getline: %s",self->data);
#endif
free(fsn);
return;
}
else
{
/* could not read... then should be at eof */
if (feof(self->fh))
{
clearerr (self->fh); /* clear eof flag */
}
}
}
sleep (2); /* prevents too much resource usage */
}
}
}
#ifdef WATCHLOG_TEST
int main() {
watchlog_t * wl;
wl = watchlog_init("/tmp/mylog");
while (1) {
watchlog_getline(wl);
printf("gotdata: %s",wl->data);
}
return 0;
}
#endif
sqcwa-0.3/htmlchk.h 0100644 0001750 0001750 00000002675 07616003273 013360 0 ustar cprov cprov /*
htmlchk -- checks if page has directives to explicit disable caching
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#ifndef _HTMLCHK_H
#define _HTMLCHK_H
struct htmlchk {
char * tmpfile;
};
typedef struct htmlchk htmlchk_t;
/* returns a pointer to htmlchk_t */
htmlchk_t * htmlchk_init (void);
/* destroy htmlchk struct */
void htmlchk_destroy (htmlchk_t * self);
/* retrieves page from cache and checks if it contains patterns
* asking not to be cached
*
* returns:
* -1 = error occoured
* 0 = page is not in cache, or could not be retrieved
* 1 = page is in cache and does not need to be removed
* 2 = page is in cache and asks to be removed
*/
int htmlchk_pagestate (htmlchk_t * self, char * url);
#endif /* _HTMLCHK_H */
sqcwa-0.3/sqcwa.init.d 0100755 0001750 0001750 00000002204 07631436213 013772 0 ustar cprov cprov #! /bin/sh
#
# this init.d script was build from an example found at
# /etc/init.d/skeleton in a Debian GNU system.
# the skeleton file was:
# Written by Miquel van Smoorenburg .
# Modified for Debian GNU/Linux
# by Ian Murdock .
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/sqcwa
NAME=sqcwa
DESC="Squid Cache Workaround"
SQUIDLOG=/var/log/squid/access.log
test -x $DAEMON || exit 0
set -e
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON -- $SQUIDLOG
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME "
start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON
echo "."
;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
sleep 1
start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON -- $SQUIDLOG
echo "."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
sqcwa-0.3/url.h 0100644 0001750 0001750 00000002015 07616003335 012513 0 ustar cprov cprov /*
url -- filters url for characters that would confuse shell
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#ifndef _URL_H
#define _URL_H
/* WARNING: urlfil size must be at least 3 times urlunf size */
/* filters url for characters that would confuse shell */
void url_filter (char * urlunf, char * urlfil);
#endif
sqcwa-0.3/sqclient.h 0100644 0001750 0001750 00000002332 07616005173 013537 0 ustar cprov cprov /*
sqclient -- gets a page from squid cache or purge it
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#ifndef _SQCLIENT_H
#define _SQCLIENT_H
#define SQUIDCLIENT "/usr/bin/squidclient"
/* IMPORTANT: just use it from localhost, never change to other host */
#define SQUIDCLIENTARGS "-h localhost -p 3128"
/* returns 1 if successfully retrieved page
* returns 0 if could not retrieve */
int sqclient_retrieve_if_in_cache (char * url, char * outfile);
void sqclient_purge_from_cache(char * url);
#endif /* _SQCLIENT_H */
sqcwa-0.3/daemon.c 0100644 0001750 0001750 00000004772 07631441422 013163 0 ustar cprov cprov /*
daemon -- functions for running as daemon
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#include "daemon.h"
#include
#include
#include
#include
#include
void run_daemon_run (char * name, int uid, int gid) {
daemon_fork();
daemon_pid (name);
daemon_drop (uid, gid);
daemon_tty ();
daemon_null ();
}
void daemon_fork (void) {
pid_t pid;
pid = fork ();
if (pid<0)
{
perror("fork error");
abort();
}
if (pid != 0)
{
/* parent will terminate */
exit(0);
}
/* this is the child */
}
void daemon_pid (char * name) {
FILE * fh;
char * s;
s = malloc( sizeof(char)*
( strlen(DAEMON_PIDPREFIX) +
strlen(name) +
strlen(DAEMON_PIDSUFFIX) + 1 ));
assert(s != NULL);
sprintf(s, "%s%s%s", DAEMON_PIDPREFIX, name, DAEMON_PIDSUFFIX);
/* write to PID file */
fh=fopen(s, "w");
/* we will continue without errors if PID file failed */
if (fh != NULL)
{
fprintf(fh, "%d\n", getpid());
fclose(fh);
}
free(s);
}
void daemon_drop (int uid, int gid) {
if (gid != -1)
{
setgid (gid);
}
if (uid != -1)
{
setuid (uid);
}
}
void daemon_tty (void) {
/* lets remove the controlling tty */
if (setsid() == -1)
{
/* failed */
perror("setsid error");
abort();
}
}
void daemon_null (void) {
FILE * fh;
/* redirect stdin, stdout, stderr to /dev/null */
fh=freopen("/dev/null", "r", stdin);
if (fh == NULL) {
perror("could not redirect stdin:");
abort();
}
fh=freopen("/dev/null", "w", stdout);
if (fh == NULL) {
perror("could not redirect stdout:");
abort();
}
fh=freopen("/dev/null", "w", stderr);
if (fh == NULL) {
perror("could not redirect stderr:");
abort();
}
}
sqcwa-0.3/daemon.h 0100644 0001750 0001750 00000002754 07631441156 013172 0 ustar cprov cprov /*
daemon -- functions for running as daemon
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#ifndef _DAEMON_H
#define _DAEMON_H
#define DAEMON_PIDPREFIX "/var/run/"
#define DAEMON_PIDSUFFIX ".pid"
void daemon_fork (void); /* forks, terminate parent, child continues */
void daemon_pid (char * name); /* creates /var/run/NAME.pid file */
void daemon_drop (int uid, int gid); /* drop root privileges */
void daemon_tty (void); /* detaches from controlling tty */
void daemon_null (void); /* redirect stdin, stdout, stderr to /dev/null */
/* inspired by the movie Forest Gump */
void run_daemon_run (char * name, int uid, int gid); /* executes _fork,
_pid, _drop, _tty
and _null */
/* if you do not want run_daemon_run to drop privileges, call it
* with uid=-1 and gid=-1 */
#endif
sqcwa-0.3/url.c 0100644 0001750 0001750 00000002325 07616003403 012506 0 ustar cprov cprov /*
url -- filters url for characters that would confuse shell
Copyright (C) 2003 Pedro Zorzenon Neto
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-1307 USA
*/
#include "url.h"
#include
void url_filter (char * urlunf, char * urlfil) {
int i;
int j=0;
unsigned char c;
for (i=0; i