-const char loaders_rcs[] = "$Id: loaders.c,v 1.39 2002/03/07 03:46:17 oes Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.49 2002/04/19 16:53:25 jongfoster Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
* unload files that are no longer in use.
*
* Copyright : Written by and Copyright (C) 2001 the SourceForge
- * IJBSWA team. http://ijbswa.sourceforge.net
+ * Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
* by and Copyright (C) 1997 Anonymous Coders and
*
* Revisions :
* $Log: loaders.c,v $
+ * Revision 1.49 2002/04/19 16:53:25 jongfoster
+ * Optimize away a function call by using an equivalent macro
+ *
+ * Revision 1.48 2002/04/05 00:56:09 gliptak
+ * Correcting typo to clean up on realloc failure
+ *
+ * Revision 1.47 2002/03/26 22:29:55 swa
+ * we have a new homepage!
+ *
+ * Revision 1.46 2002/03/24 13:25:43 swa
+ * name change related issues
+ *
+ * Revision 1.45 2002/03/16 23:54:06 jongfoster
+ * Adding graceful termination feature, to help look for memory leaks.
+ * If you enable this (which, by design, has to be done by hand
+ * editing config.h) and then go to http://i.j.b/die, then the program
+ * will exit cleanly after the *next* request. It should free all the
+ * memory that was used.
+ *
+ * Revision 1.44 2002/03/16 21:51:00 jongfoster
+ * Fixing free(NULL).
+ *
+ * Revision 1.43 2002/03/16 20:28:34 oes
+ * Added descriptions to the filters so users will know what they select in the cgi editor
+ *
+ * Revision 1.42 2002/03/13 00:27:05 jongfoster
+ * Killing warnings
+ *
+ * Revision 1.41 2002/03/12 01:42:50 oes
+ * Introduced modular filters
+ *
+ * Revision 1.40 2002/03/08 17:46:04 jongfoster
+ * Fixing int/size_t warnings
+ *
* Revision 1.39 2002/03/07 03:46:17 oes
* Fixed compiler warnings
*
{
struct file_list *fl, *nfl;
struct client_state *csp, *ncsp;
+ int i;
/* clear all of the file's active flags */
for ( fl = files->next; NULL != fl; fl = fl->next )
fl->active = 0;
}
- for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
+ for (csp = clients; csp && (NULL != (ncsp = csp->next)) ; csp = csp->next)
{
if (ncsp->flags & CSP_FLAG_ACTIVE)
{
*/
ncsp->config->config_file_list->active = 1;
- if (ncsp->actions_list) /* actions files */
+ for (i = 0; i < MAX_ACTION_FILES; i++)
{
- ncsp->actions_list->active = 1;
+ if (ncsp->actions_list[i]) /* actions files */
+ {
+ ncsp->actions_list[i]->active = 1;
+ }
}
if (ncsp->rlist) /* pcrsjob files */
freez(ncsp);
/* are there any more in sequence after it? */
- if( !(ncsp = csp->next) )
+ if( (ncsp = csp->next) == NULL)
break;
}
}
}
- for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
+ for (fl = files; fl && ((nfl = fl->next) != NULL) ; fl = fl->next)
{
if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
{
#define CHAR_CR '\r' /* ASCII 13 */
#define CHAR_LF '\n' /* ASCII 10 */
- while (FOREVER)
+ for (;;)
{
- ch = fgetc(fp);
+ ch = getc(fp);
if (ch == EOF)
{
if (len > 0)
if (++len >= buflen)
{
buflen += BUFFER_SIZE;
- if (NULL == (p = realloc(buf, buflen)));
+ if (NULL == (p = realloc(buf, buflen)))
{
free(buf);
return JB_ERR_MEMORY;
* the caller cares about "raw" or just "data").
*/
- free(raw);
- free(prefix);
- free(data);
+ freez(raw);
+ freez(prefix);
+ freez(data);
return JB_ERR_FILE;
}
}
else
{
- free(raw);
+ freez(raw);
}
if (prefix_out)
{
}
else
{
- free(prefix);
+ freez(prefix);
}
if (data_out)
{
}
else
{
- free(data);
+ freez(data);
}
return JB_ERR_OK;
}
*********************************************************************/
static void unload_trustfile(void *f)
{
- struct block_spec *b = (struct block_spec *)f;
- if (b == NULL) return;
+ struct block_spec *cur = (struct block_spec *)f;
+ struct block_spec *next;
- unload_trustfile(b->next); /* Stack is cheap, isn't it? */
+ while (cur != NULL)
+ {
+ next = cur->next;
- free_url_spec(b->url);
+ free_url_spec(cur->url);
+ free(cur);
- freez(b);
+ cur = next;
+ }
}
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function : unload_current_trust_file
+ *
+ * Description : Unloads current trust file - reset to state at
+ * beginning of program.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void unload_current_trust_file(void)
+{
+ if (current_trustfile)
+ {
+ current_trustfile->unloader = unload_trustfile;
+ current_trustfile = NULL;
+ }
+}
+#endif /* FEATURE_GRACEFUL_TERMINATION */
+
+
/*********************************************************************
*
* Function : load_trustfile
reject = 0;
p = buf;
q = p+1;
- while ((*p++ = *q++))
+ while ((*p++ = *q++) != '\0')
{
/* nop */
}
*
* Function : unload_re_filterfile
*
- * Description : Unload the re_filter list.
+ * Description : Unload the re_filter list by freeing all chained
+ * re_filterfile specs and their data.
*
* Parameters :
* 1 : f = the data structure associated with the filterfile.
*********************************************************************/
static void unload_re_filterfile(void *f)
{
- struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
+ struct re_filterfile_spec *a, *b = (struct re_filterfile_spec *)f;
- if (b == NULL)
+ while (b != NULL)
{
- return;
- }
+ a = b->next;
+
+ destroy_list(b->patterns);
+ pcrs_free_joblist(b->joblist);
+ freez(b->name);
+ freez(b->description);
+ freez(b);
- destroy_list(b->patterns);
- pcrs_free_joblist(b->joblist);
- freez(b);
+ b = a;
+ }
return;
}
+
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function : unload_current_re_filterfile
+ *
+ * Description : Unloads current re_filter file - reset to state at
+ * beginning of program.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void unload_current_re_filterfile(void)
+{
+ if (current_re_filterfile)
+ {
+ current_re_filterfile->unloader = unload_re_filterfile;
+ current_re_filterfile = NULL;
+ }
+}
+#endif
+
+
/*********************************************************************
*
* Function : load_re_filterfile
*
- * Description : Load the re_filterfile. Each non-comment, non-empty
- * line is instantly added to the joblist, which is
- * a chained list of pcrs_job structs.
+ * Description : Load the re_filterfile.
+ * Generate a chained list of re_filterfile_spec's from
+ * the "FILTER: " blocks, compiling all their substitutions
+ * into chained lists of pcrs_job structs.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
{
FILE *fp;
- struct re_filterfile_spec *bl;
+ struct re_filterfile_spec *new_bl, *bl = NULL;
struct file_list *fs;
char buf[BUFFER_SIZE];
unsigned long linenum = 0;
pcrs_job *dummy;
+ /*
+ * No need to reload if unchanged
+ */
if (!check_file_changed(current_re_filterfile, csp->config->re_filterfile, &fs))
{
- /* No need to load */
if (csp)
{
csp->rlist = current_re_filterfile;
goto load_re_filterfile_error;
}
- fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
- if (bl == NULL)
- {
- goto load_re_filterfile_error;
- }
-
- /* Open the file or fail */
+ /*
+ * Open the file or fail
+ */
if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
{
goto load_re_filterfile_error;
}
- /* Read line by line */
+ /*
+ * Read line by line
+ */
while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL)
{
- enlist( bl->patterns, buf );
-
- /* We have a meaningful line -> make it a job */
- if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
+ /*
+ * If this is the head of a new filter block, make it a
+ * re_filterfile spec of its own and chain it to the list:
+ */
+ if (strncmp(buf, "FILTER:", 7) == 0)
{
- log_error(LOG_LEVEL_RE_FILTER,
- "Adding re_filter job %s failed with error %d.", buf, error);
+ new_bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
+ if (new_bl == NULL)
+ {
+ goto load_re_filterfile_error;
+ }
+
+ new_bl->name = chomp(buf + 7);
+
+ if (NULL != (new_bl->description = strchr(new_bl->name, ' ')))
+ {
+ *new_bl->description++ = '\0';
+ new_bl->description = strdup(chomp(new_bl->description));
+ }
+ else
+ {
+ new_bl->description = strdup("No description available for this filter");
+ }
+
+ new_bl->name = strdup(chomp(new_bl->name));
+
+ /*
+ * If this is the first filter block, chain it
+ * to the file_list rather than its (nonexistant)
+ * predecessor
+ */
+ if (fs->f == NULL)
+ {
+ fs->f = new_bl;
+ }
+ else
+ {
+ bl->next = new_bl;
+ }
+ bl = new_bl;
+
+ log_error(LOG_LEVEL_RE_FILTER, "Reading in filter \"%s\" (\"%s\")", bl->name, bl->description);
+
continue;
}
+
+ /*
+ * Else, save the expression, make it a pcrs_job
+ * and chain it into the current filter's joblist
+ */
+ if (bl != NULL)
+ {
+ enlist(bl->patterns, buf);
+
+ if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
+ {
+ log_error(LOG_LEVEL_RE_FILTER,
+ "Adding re_filter job %s to filter %s failed with error %d.", buf, bl->name, error);
+ continue;
+ }
+ else
+ {
+ dummy->next = bl->joblist;
+ bl->joblist = dummy;
+ log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s to filter %s succeeded.", buf, bl->name);
+ }
+ }
else
{
- dummy->next = bl->joblist;
- bl->joblist = dummy;
- log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s succeeded.", buf);
+ log_error(LOG_LEVEL_ERROR, "Ignoring job %s outside filter block in %s, line %d", buf, csp->config->re_filterfile, linenum);
}
}
fclose(fp);
- /* the old one is now obsolete */
+ /*
+ * Schedule the now-obsolete old data for unloading
+ */
if ( NULL != current_re_filterfile )
{
current_re_filterfile->unloader = unload_re_filterfile;
}
+ /*
+ * Chain this file into the global list of loaded files
+ */
fs->next = files->next;
files->next = fs;
current_re_filterfile = fs;