1 const char loaders_rcs[] = "$Id: loaders.c,v 1.46 2002/03/24 13:25:43 swa Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
6 * Purpose : Functions to load and unload the various
7 * configuration files. Also contains code to manage
8 * the list of active loaders, and to automatically
9 * unload files that are no longer in use.
11 * Copyright : Written by and Copyright (C) 2001 the SourceForge
12 * Privoxy team. http://www.privoxy.org/
14 * Based on the Internet Junkbuster originally written
15 * by and Copyright (C) 1997 Anonymous Coders and
16 * Junkbusters Corporation. http://www.junkbusters.com
18 * This program is free software; you can redistribute it
19 * and/or modify it under the terms of the GNU General
20 * Public License as published by the Free Software
21 * Foundation; either version 2 of the License, or (at
22 * your option) any later version.
24 * This program is distributed in the hope that it will
25 * be useful, but WITHOUT ANY WARRANTY; without even the
26 * implied warranty of MERCHANTABILITY or FITNESS FOR A
27 * PARTICULAR PURPOSE. See the GNU General Public
28 * License for more details.
30 * The GNU General Public License should be included with
31 * this file. If not, you can view it at
32 * http://www.gnu.org/copyleft/gpl.html
33 * or write to the Free Software Foundation, Inc., 59
34 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * Revision 1.46 2002/03/24 13:25:43 swa
39 * name change related issues
41 * Revision 1.45 2002/03/16 23:54:06 jongfoster
42 * Adding graceful termination feature, to help look for memory leaks.
43 * If you enable this (which, by design, has to be done by hand
44 * editing config.h) and then go to http://i.j.b/die, then the program
45 * will exit cleanly after the *next* request. It should free all the
46 * memory that was used.
48 * Revision 1.44 2002/03/16 21:51:00 jongfoster
51 * Revision 1.43 2002/03/16 20:28:34 oes
52 * Added descriptions to the filters so users will know what they select in the cgi editor
54 * Revision 1.42 2002/03/13 00:27:05 jongfoster
57 * Revision 1.41 2002/03/12 01:42:50 oes
58 * Introduced modular filters
60 * Revision 1.40 2002/03/08 17:46:04 jongfoster
61 * Fixing int/size_t warnings
63 * Revision 1.39 2002/03/07 03:46:17 oes
64 * Fixed compiler warnings
66 * Revision 1.38 2002/03/06 22:54:35 jongfoster
67 * Automated function-comment nitpicking.
69 * Revision 1.37 2002/03/03 15:07:49 oes
70 * Re-enabled automatic config reloading
72 * Revision 1.36 2002/01/22 23:46:18 jongfoster
73 * Moving edit_read_line() and simple_read_line() to loaders.c, and
74 * extending them to support reading MS-DOS, Mac and UNIX style files
77 * Modifying read_config_line() (without changing it's prototype) to
78 * be a trivial wrapper for edit_read_line(). This means that we have
79 * one function to read a line and handle comments, which is common
80 * between the initialization code and the edit interface.
82 * Revision 1.35 2002/01/17 21:03:08 jongfoster
83 * Moving all our URL and URL pattern parsing code to urlmatch.c.
85 * Renaming free_url to free_url_spec, since it frees a struct url_spec.
87 * Revision 1.34 2001/12/30 14:07:32 steudten
88 * - Add signal handling (unix)
89 * - Add SIGHUP handler (unix)
90 * - Add creation of pidfile (unix)
91 * - Add action 'top' in rc file (RH)
92 * - Add entry 'SIGNALS' to manpage
93 * - Add exit message to logfile (unix)
95 * Revision 1.33 2001/11/13 00:16:38 jongfoster
96 * Replacing references to malloc.h with the standard stdlib.h
97 * (See ANSI or K&R 2nd Ed)
99 * Revision 1.32 2001/11/07 00:02:13 steudten
100 * Add line number in error output for lineparsing for
101 * actionsfile and configfile.
102 * Special handling for CLF added.
104 * Revision 1.31 2001/10/26 17:39:01 oes
105 * Removed csp->referrer
106 * Moved ijb_isspace and ijb_tolower to project.h
108 * Revision 1.30 2001/10/25 03:40:48 david__schmidt
109 * Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
110 * threads to call select() simultaneously. So, it's time to do a real, live,
111 * native OS/2 port. See defines for __EMX__ (the porting layer) vs. __OS2__
112 * (native). Both versions will work, but using __OS2__ offers multi-threading.
114 * Revision 1.29 2001/10/23 21:38:53 jongfoster
115 * Adding error-checking to create_url_spec()
117 * Revision 1.28 2001/10/07 15:40:39 oes
118 * Replaced 6 boolean members of csp with one bitmap (csp->flags)
120 * Revision 1.27 2001/09/22 16:36:59 jongfoster
121 * Removing unused parameter fs from read_config_line()
123 * Revision 1.26 2001/09/22 14:05:22 jongfoster
124 * Bugfix: Multiple escaped "#" characters in a configuration
125 * file are now permitted.
126 * Also removing 3 unused headers.
128 * Revision 1.25 2001/09/13 22:44:03 jongfoster
129 * Adding {} to an if statement
131 * Revision 1.24 2001/07/30 22:08:36 jongfoster
132 * Tidying up #defines:
133 * - All feature #defines are now of the form FEATURE_xxx
134 * - Permanently turned off WIN_GUI_EDIT
135 * - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
137 * Revision 1.23 2001/07/20 15:51:54 oes
138 * Fixed indentation of prepocessor commands
140 * Revision 1.22 2001/07/20 15:16:17 haroon
141 * - per Guy's suggestion, added a while loop in sweep() to catch not just
142 * the last inactive CSP but all other consecutive inactive CSPs after that
145 * Revision 1.21 2001/07/18 17:26:24 oes
146 * Changed to conform to new pcrs interface
148 * Revision 1.20 2001/07/17 13:07:01 oes
149 * Fixed segv when last line in config files
150 * lacked a terminating (\r)\n
152 * Revision 1.19 2001/07/13 14:01:54 oes
153 * Removed all #ifdef PCRS
155 * Revision 1.18 2001/06/29 21:45:41 oes
156 * Indentation, CRLF->LF, Tab-> Space
158 * Revision 1.17 2001/06/29 13:31:51 oes
161 * Revision 1.16 2001/06/09 10:55:28 jongfoster
162 * Changing BUFSIZ ==> BUFFER_SIZE
164 * Revision 1.15 2001/06/07 23:14:14 jongfoster
165 * Removing ACL and forward file loaders - these
166 * files have been merged into the config file.
167 * Cosmetic: Moving unloader funcs next to their
168 * respective loader funcs
170 * Revision 1.14 2001/06/01 03:27:04 oes
171 * Fixed line continuation problem
173 * Revision 1.13 2001/05/31 21:28:49 jongfoster
174 * Removed all permissionsfile code - it's now called the actions
175 * file, and (almost) all the code is in actions.c
177 * Revision 1.12 2001/05/31 17:32:31 oes
179 * - Enhanced domain part globbing with infix and prefix asterisk
180 * matching and optional unanchored operation
182 * Revision 1.11 2001/05/29 23:25:24 oes
184 * - load_config_line() and load_permissions_file() now use chomp()
186 * Revision 1.10 2001/05/29 09:50:24 jongfoster
187 * Unified blocklist/imagelist/permissionslist.
188 * File format is still under discussion, but the internal changes
191 * Also modified interceptor behaviour:
192 * - We now intercept all URLs beginning with one of the following
193 * prefixes (and *only* these prefixes):
195 * * http://ijbswa.sf.net/config/
196 * * http://ijbswa.sourceforge.net/config/
197 * - New interceptors "home page" - go to http://i.j.b/ to see it.
198 * - Internal changes so that intercepted and fast redirect pages
199 * are not replaced with an image.
200 * - Interceptors now have the option to send a binary page direct
201 * to the client. (i.e. ijb-send-banner uses this)
202 * - Implemented show-url-info interceptor. (Which is why I needed
203 * the above interceptors changes - a typical URL is
204 * "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
205 * The previous mechanism would not have intercepted that, and
206 * if it had been intercepted then it then it would have replaced
209 * Revision 1.9 2001/05/26 17:12:07 jongfoster
210 * Fatal errors loading configuration files now give better error messages.
212 * Revision 1.8 2001/05/26 00:55:20 jongfoster
213 * Removing duplicated code. load_forwardfile() now uses create_url_spec()
215 * Revision 1.7 2001/05/26 00:28:36 jongfoster
216 * Automatic reloading of config file.
217 * Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
218 * Most of the global variables have been moved to a new
219 * struct configuration_spec, accessed through csp->config->globalname
220 * Most of the globals remaining are used by the Win32 GUI.
222 * Revision 1.6 2001/05/23 12:27:33 oes
224 * Fixed ugly indentation of my last changes
226 * Revision 1.5 2001/05/23 10:39:05 oes
227 * - Added support for escaping the comment character
228 * in config files by a backslash
229 * - Added support for line continuation in config
231 * - Fixed a buffer overflow bug with long config lines
233 * Revision 1.4 2001/05/22 18:56:28 oes
236 * Revision 1.3 2001/05/20 01:21:20 jongfoster
237 * Version 2.9.4 checkin.
238 * - Merged popupfile and cookiefile, and added control over PCRS
239 * filtering, in new "permissionsfile".
240 * - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
241 * file error you now get a message box (in the Win32 GUI) rather
242 * than the program exiting with no explanation.
243 * - Made killpopup use the PCRS MIME-type checking and HTTP-header
245 * - Removed tabs from "config"
246 * - Moved duplicated url parsing code in "loaders.c" to a new funcition.
247 * - Bumped up version number.
249 * Revision 1.2 2001/05/17 23:01:01 oes
250 * - Cleaned CRLF's from the sources and related files
252 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
253 * Initial import of version 2.9.3 source tree
256 *********************************************************************/
263 #include <sys/types.h>
266 #include <sys/stat.h>
270 #if !defined(_WIN32) && !defined(__OS2__)
280 #include "miscutil.h"
283 #include "urlmatch.h"
285 const char loaders_h_rcs[] = LOADERS_H_VERSION;
288 * Currently active files.
289 * These are also entered in the main linked list of files.
293 static struct file_list *current_trustfile = NULL;
294 #endif /* def FEATURE_TRUST */
296 static struct file_list *current_re_filterfile = NULL;
300 /*********************************************************************
304 * Description : Basically a mark and sweep garbage collector, it is run
305 * (by the parent thread) every once in a while to reclaim memory.
307 * It uses a mark and sweep strategy:
308 * 1) mark all files as inactive
310 * 2) check with each client:
311 * if it is active, mark its files as active
312 * if it is inactive, free its resources
314 * 3) free the resources of all of the files that
315 * are still marked as inactive (and are obsolete).
317 * N.B. files that are not obsolete don't have an unloader defined.
323 *********************************************************************/
326 struct file_list *fl, *nfl;
327 struct client_state *csp, *ncsp;
329 /* clear all of the file's active flags */
330 for ( fl = files->next; NULL != fl; fl = fl->next )
335 for (csp = clients; csp && (NULL != (ncsp = csp->next)) ; csp = csp->next)
337 if (ncsp->flags & CSP_FLAG_ACTIVE)
339 /* mark this client's files as active */
342 * Always have a configuration file.
343 * (Also note the slightly non-standard extra
346 ncsp->config->config_file_list->active = 1;
348 if (ncsp->actions_list) /* actions files */
350 ncsp->actions_list->active = 1;
353 if (ncsp->rlist) /* pcrsjob files */
355 ncsp->rlist->active = 1;
359 if (ncsp->tlist) /* trust files */
361 ncsp->tlist->active = 1;
363 #endif /* def FEATURE_TRUST */
368 * this client is not active, release its resources
369 * and the ones of all inactive clients that might
373 while (!(ncsp->flags & CSP_FLAG_ACTIVE))
375 csp->next = ncsp->next;
377 freez(ncsp->ip_addr_str);
378 freez(ncsp->my_ip_addr_str);
379 freez(ncsp->my_hostname);
380 freez(ncsp->x_forwarded);
381 freez(ncsp->iob->buf);
383 free_http_request(ncsp->http);
385 destroy_list(ncsp->headers);
386 destroy_list(ncsp->cookie_list);
388 free_current_action(ncsp->action);
390 #ifdef FEATURE_STATISTICS
392 if (ncsp->flags & CSP_FLAG_REJECTED)
396 #endif /* def FEATURE_STATISTICS */
400 /* are there any more in sequence after it? */
401 if( (ncsp = csp->next) == NULL)
407 for (fl = files; fl && ((nfl = fl->next) != NULL) ; fl = fl->next)
409 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
411 fl->next = nfl->next;
413 (nfl->unloader)(nfl->f);
415 freez(nfl->filename);
424 /*********************************************************************
426 * Function : check_file_changed
428 * Description : Helper function to check if a file needs reloading.
429 * If "current" is still current, return it. Otherwise
430 * allocates a new (zeroed) "struct file_list", fills
431 * in the disk file name and timestamp, and returns it.
434 * 1 : current = The file_list currently being used - will
435 * be checked to see if it is out of date.
436 * May be NULL (which is treated as out of
438 * 2 : filename = Name of file to check.
439 * 3 : newfl = New file list. [Output only]
440 * This will be set to NULL, OR a struct
441 * file_list newly allocated on the
442 * heap, with the filename and lastmodified
443 * fields filled, and all others zeroed.
445 * Returns : If file unchanged: 0 (and sets newfl == NULL)
446 * If file changed: 1 and sets newfl != NULL
447 * On error: 1 and sets newfl == NULL
449 *********************************************************************/
450 int check_file_changed(const struct file_list * current,
451 const char * filename,
452 struct file_list ** newfl)
454 struct file_list *fs;
455 struct stat statbuf[1];
459 if (stat(filename, statbuf) < 0)
461 /* Error, probably file not found. */
466 && (current->lastmodified == statbuf->st_mtime)
467 && (0 == strcmp(current->filename, filename)))
472 fs = (struct file_list *)zalloc(sizeof(struct file_list));
475 /* Out of memory error */
479 fs->filename = strdup(filename);
480 fs->lastmodified = statbuf->st_mtime;
482 if (fs->filename == NULL)
484 /* Out of memory error */
493 /*********************************************************************
495 * Function : simple_read_line
497 * Description : Read a single line from a file and return it.
498 * This is basically a version of fgets() that malloc()s
499 * it's own line buffer. Note that the buffer will
500 * always be a multiple of BUFFER_SIZE bytes long.
501 * Therefore if you are going to keep the string for
502 * an extended period of time, you should probably
503 * strdup() it and free() the original, to save memory.
507 * 1 : dest = destination for newly malloc'd pointer to
508 * line data. Will be set to NULL on error.
509 * 2 : fp = File to read from
510 * 3 : newline = Standard for newlines in the file.
511 * Will be unchanged if it's value on input is not
513 * On output, may be changed from NEWLINE_UNKNOWN to
514 * actual convention in file.
516 * Returns : JB_ERR_OK on success
517 * JB_ERR_MEMORY on out-of-memory
518 * JB_ERR_FILE on EOF.
520 *********************************************************************/
521 jb_err simple_read_line(FILE *fp, char **dest, int *newline)
524 size_t buflen = BUFFER_SIZE;
528 int realnewline = NEWLINE_UNKNOWN;
530 if (NULL == (buf = malloc(buflen)))
532 return JB_ERR_MEMORY;
538 * Character codes. If you have a wierd compiler and the following are
539 * incorrect, you also need to fix NEWLINE() in loaders.h
541 #define CHAR_CR '\r' /* ASCII 13 */
542 #define CHAR_LF '\n' /* ASCII 10 */
562 else if (ch == CHAR_CR)
567 if (*newline == NEWLINE_UNKNOWN)
569 *newline = NEWLINE_DOS;
578 if (*newline == NEWLINE_UNKNOWN)
580 *newline = NEWLINE_MAC;
585 if (*newline == NEWLINE_UNKNOWN)
587 *newline = realnewline;
591 else if (ch == CHAR_LF)
595 if (*newline == NEWLINE_UNKNOWN)
597 *newline = NEWLINE_UNIX;
612 buflen += BUFFER_SIZE;
613 if (NULL == (p = realloc(buf, buflen)));
616 return JB_ERR_MEMORY;
625 /*********************************************************************
627 * Function : edit_read_line
629 * Description : Read a single non-empty line from a file and return
630 * it. Trims comments, leading and trailing whitespace
631 * and respects escaping of newline and comment char.
632 * Provides the line in 2 alternative forms: raw and
634 * - raw is the raw data read from the file. If the
635 * line is not modified, then this should be written
637 * - prefix is any comments and blank lines that were
638 * read from the file. If the line is modified, then
639 * this should be written out to the file followed
640 * by the modified data. (If this string is non-empty
641 * then it will have a newline at the end).
642 * - data is the actual data that will be parsed
643 * further by appropriate routines.
644 * On EOF, the 3 strings will all be set to NULL and
645 * 0 will be returned.
648 * 1 : fp = File to read from
649 * 2 : raw_out = destination for newly malloc'd pointer to
650 * raw line data. May be NULL if you don't want it.
651 * 3 : prefix_out = destination for newly malloc'd pointer to
652 * comments. May be NULL if you don't want it.
653 * 4 : data_out = destination for newly malloc'd pointer to
654 * line data with comments and leading/trailing spaces
655 * removed, and line continuation performed. May be
656 * NULL if you don't want it.
657 * 5 : newline = Standard for newlines in the file.
658 * On input, set to value to use or NEWLINE_UNKNOWN.
659 * On output, may be changed from NEWLINE_UNKNOWN to
660 * actual convention in file. May be NULL if you
662 * 6 : line_number = Line number in file. In "lines" as
663 * reported by a text editor, not lines containing data.
665 * Returns : JB_ERR_OK on success
666 * JB_ERR_MEMORY on out-of-memory
667 * JB_ERR_FILE on EOF.
669 *********************************************************************/
670 jb_err edit_read_line(FILE *fp,
675 unsigned long *line_number)
677 char *p; /* Temporary pointer */
678 char *linebuf; /* Line read from file */
679 char *linestart; /* Start of linebuf, usually first non-whitespace char */
680 int contflag = 0; /* Nonzero for line continuation - i.e. line ends '\' */
681 int is_empty = 1; /* Flag if not got any data yet */
682 char *raw = NULL; /* String to be stored in raw_out */
683 char *prefix = NULL; /* String to be stored in prefix_out */
684 char *data = NULL; /* String to be stored in data_out */
685 int scrapnewline; /* Used for (*newline) if newline==NULL */
686 jb_err rval = JB_ERR_OK;
689 assert(raw_out || data_out);
690 assert(newline == NULL
691 || *newline == NEWLINE_UNKNOWN
692 || *newline == NEWLINE_UNIX
693 || *newline == NEWLINE_DOS
694 || *newline == NEWLINE_MAC);
698 scrapnewline = NEWLINE_UNKNOWN;
699 newline = &scrapnewline;
702 /* Set output parameters to NULL */
716 /* Set string variables to new, empty strings. */
720 if ((raw = malloc(1)) == NULL)
722 return JB_ERR_MEMORY;
728 if ((prefix = malloc(1)) == NULL)
731 return JB_ERR_MEMORY;
737 if ((data = malloc(1)) == NULL)
741 return JB_ERR_MEMORY;
746 /* Main loop. Loop while we need more data & it's not EOF. */
748 while ( (contflag || is_empty)
749 && (JB_ERR_OK == (rval = simple_read_line(fp, &linebuf, newline))))
757 string_append(&raw,linebuf);
758 if (string_append(&raw,NEWLINE(*newline)))
763 return JB_ERR_MEMORY;
767 /* Line continuation? Trim escape and set flag. */
768 p = linebuf + strlen(linebuf) - 1;
769 contflag = ((*linebuf != '\0') && (*p == '\\'));
775 /* Trim leading spaces if we're at the start of the line */
779 /* Trim leading spaces */
780 while (*linestart && isspace((int)(unsigned char)*linestart))
786 /* Handle comment characters. */
788 while ((p = strchr(p, '#')) != NULL)
790 /* Found a comment char.. */
791 if ((p != linebuf) && (*(p-1) == '\\'))
793 /* ..and it's escaped, left-shift the line over the escape. */
795 while ((*q = *(q + 1)) != '\0')
799 /* Now scan from just after the "#". */
803 /* Real comment. Save it... */
806 /* Special case: Line only contains a comment, so all the
807 * previous whitespace is considered part of the comment.
808 * Undo the whitespace skipping, if any.
815 string_append(&prefix,p);
816 if (string_append(&prefix, NEWLINE(*newline)))
821 return JB_ERR_MEMORY;
825 /* ... and chop off the rest of the line */
828 } /* END while (there's a # character) */
830 /* Write to the buffer */
836 if (string_append(&data, linestart))
841 return JB_ERR_MEMORY;
847 } /* END while(we need more data) */
849 /* Handle simple_read_line() errors - ignore EOF */
850 if ((rval != JB_ERR_OK) && (rval != JB_ERR_FILE))
858 if (raw ? (*raw == '\0') : is_empty)
860 /* EOF and no data there. (Definition of "data" depends on whether
861 * the caller cares about "raw" or just "data").
872 /* Got at least some data */
874 /* Remove trailing whitespace */
887 *prefix_out = prefix;
906 /*********************************************************************
908 * Function : read_config_line
910 * Description : Read a single non-empty line from a file and return
911 * it. Trims comments, leading and trailing whitespace
912 * and respects escaping of newline and comment char.
915 * 1 : buf = Buffer to use.
916 * 2 : buflen = Size of buffer in bytes.
917 * 3 : fp = File to read from
918 * 4 : linenum = linenumber in file
920 * Returns : NULL on EOF or error
921 * Otherwise, returns buf.
923 *********************************************************************/
924 char *read_config_line(char *buf, size_t buflen, FILE *fp, unsigned long *linenum)
928 err = edit_read_line(fp, NULL, NULL, &buf2, NULL, linenum);
931 if (err == JB_ERR_MEMORY)
933 log_error(LOG_LEVEL_FATAL, "Out of memory loading a config file");
940 assert(strlen(buf2) + 1U < buflen);
941 strncpy(buf, buf2, buflen - 1);
943 buf[buflen - 1] = '\0';
950 /*********************************************************************
952 * Function : unload_trustfile
954 * Description : Unloads a trustfile.
957 * 1 : f = the data structure associated with the trustfile.
961 *********************************************************************/
962 static void unload_trustfile(void *f)
964 struct block_spec *cur = (struct block_spec *)f;
965 struct block_spec *next;
971 free_url_spec(cur->url);
980 #ifdef FEATURE_GRACEFUL_TERMINATION
981 /*********************************************************************
983 * Function : unload_current_trust_file
985 * Description : Unloads current trust file - reset to state at
986 * beginning of program.
992 *********************************************************************/
993 void unload_current_trust_file(void)
995 if (current_trustfile)
997 current_trustfile->unloader = unload_trustfile;
998 current_trustfile = NULL;
1001 #endif /* FEATURE_GRACEFUL_TERMINATION */
1004 /*********************************************************************
1006 * Function : load_trustfile
1008 * Description : Read and parse a trustfile and add to files list.
1011 * 1 : csp = Current client state (buffers, headers, etc...)
1013 * Returns : 0 => Ok, everything else is an error.
1015 *********************************************************************/
1016 int load_trustfile(struct client_state *csp)
1020 struct block_spec *b, *bl;
1021 struct url_spec **tl;
1023 char buf[BUFFER_SIZE], *p, *q;
1024 int reject, trusted;
1025 struct file_list *fs;
1026 unsigned long linenum = 0;
1028 if (!check_file_changed(current_trustfile, csp->config->trustfile, &fs))
1030 /* No need to load */
1033 csp->tlist = current_trustfile;
1039 goto load_trustfile_error;
1042 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1045 goto load_trustfile_error;
1048 if ((fp = fopen(csp->config->trustfile, "r")) == NULL)
1050 goto load_trustfile_error;
1053 tl = csp->config->trust_list;
1055 while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL)
1071 while ((*p++ = *q++) != '\0')
1077 /* skip blank lines */
1083 /* allocate a new node */
1084 if ((b = zalloc(sizeof(*b))) == NULL)
1087 goto load_trustfile_error;
1090 /* add it to the list */
1096 /* Save the URL pattern */
1097 if (create_url_spec(b->url, buf))
1100 goto load_trustfile_error;
1104 * save a pointer to URL's spec in the list of trusted URL's, too
1109 /* FIXME BUFFER OVERFLOW if >=64 entries */
1117 /* the old one is now obsolete */
1118 if (current_trustfile)
1120 current_trustfile->unloader = unload_trustfile;
1123 fs->next = files->next;
1125 current_trustfile = fs;
1134 load_trustfile_error:
1135 log_error(LOG_LEVEL_FATAL, "can't load trustfile '%s': %E",
1136 csp->config->trustfile);
1140 #endif /* def FEATURE_TRUST */
1143 /*********************************************************************
1145 * Function : unload_re_filterfile
1147 * Description : Unload the re_filter list by freeing all chained
1148 * re_filterfile specs and their data.
1151 * 1 : f = the data structure associated with the filterfile.
1155 *********************************************************************/
1156 static void unload_re_filterfile(void *f)
1158 struct re_filterfile_spec *a, *b = (struct re_filterfile_spec *)f;
1164 destroy_list(b->patterns);
1165 pcrs_free_joblist(b->joblist);
1167 freez(b->description);
1177 #ifdef FEATURE_GRACEFUL_TERMINATION
1178 /*********************************************************************
1180 * Function : unload_current_re_filterfile
1182 * Description : Unloads current re_filter file - reset to state at
1183 * beginning of program.
1189 *********************************************************************/
1190 void unload_current_re_filterfile(void)
1192 if (current_re_filterfile)
1194 current_re_filterfile->unloader = unload_re_filterfile;
1195 current_re_filterfile = NULL;
1201 /*********************************************************************
1203 * Function : load_re_filterfile
1205 * Description : Load the re_filterfile.
1206 * Generate a chained list of re_filterfile_spec's from
1207 * the "FILTER: " blocks, compiling all their substitutions
1208 * into chained lists of pcrs_job structs.
1211 * 1 : csp = Current client state (buffers, headers, etc...)
1213 * Returns : 0 => Ok, everything else is an error.
1215 *********************************************************************/
1216 int load_re_filterfile(struct client_state *csp)
1220 struct re_filterfile_spec *new_bl, *bl = NULL;
1221 struct file_list *fs;
1223 char buf[BUFFER_SIZE];
1225 unsigned long linenum = 0;
1229 * No need to reload if unchanged
1231 if (!check_file_changed(current_re_filterfile, csp->config->re_filterfile, &fs))
1235 csp->rlist = current_re_filterfile;
1241 goto load_re_filterfile_error;
1245 * Open the file or fail
1247 if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
1249 goto load_re_filterfile_error;
1255 while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL)
1258 * If this is the head of a new filter block, make it a
1259 * re_filterfile spec of its own and chain it to the list:
1261 if (strncmp(buf, "FILTER:", 7) == 0)
1263 new_bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1266 goto load_re_filterfile_error;
1269 new_bl->name = chomp(buf + 7);
1271 if (NULL != (new_bl->description = strchr(new_bl->name, ' ')))
1273 *new_bl->description++ = '\0';
1274 new_bl->description = strdup(chomp(new_bl->description));
1278 new_bl->description = strdup("No description available for this filter");
1281 new_bl->name = strdup(chomp(new_bl->name));
1284 * If this is the first filter block, chain it
1285 * to the file_list rather than its (nonexistant)
1298 log_error(LOG_LEVEL_RE_FILTER, "Reading in filter \"%s\" (\"%s\")", bl->name, bl->description);
1304 * Else, save the expression, make it a pcrs_job
1305 * and chain it into the current filter's joblist
1309 enlist(bl->patterns, buf);
1311 if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
1313 log_error(LOG_LEVEL_RE_FILTER,
1314 "Adding re_filter job %s to filter %s failed with error %d.", buf, bl->name, error);
1319 dummy->next = bl->joblist;
1320 bl->joblist = dummy;
1321 log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s to filter %s succeeded.", buf, bl->name);
1326 log_error(LOG_LEVEL_ERROR, "Ignoring job %s outside filter block in %s, line %d", buf, csp->config->re_filterfile, linenum);
1333 * Schedule the now-obsolete old data for unloading
1335 if ( NULL != current_re_filterfile )
1337 current_re_filterfile->unloader = unload_re_filterfile;
1341 * Chain this file into the global list of loaded files
1343 fs->next = files->next;
1345 current_re_filterfile = fs;
1354 load_re_filterfile_error:
1355 log_error(LOG_LEVEL_FATAL, "can't load re_filterfile '%s': %E",
1356 csp->config->re_filterfile);
1362 /*********************************************************************
1364 * Function : add_loader
1366 * Description : Called from `load_config'. Called once for each input
1367 * file found in config.
1370 * 1 : loader = pointer to a function that can parse and load
1371 * the appropriate config file.
1372 * 2 : config = The configuration_spec to add the loader to.
1376 *********************************************************************/
1377 void add_loader(int (*loader)(struct client_state *),
1378 struct configuration_spec * config)
1382 for (i=0; i < NLOADERS; i++)
1384 if (config->loaders[i] == NULL)
1386 config->loaders[i] = loader;
1394 /*********************************************************************
1396 * Function : run_loader
1398 * Description : Called from `load_config' and `listen_loop'. This
1399 * function keeps the "csp" current with any file mods
1400 * since the last loop. If a file is unchanged, the
1401 * loader functions do NOT reload the file.
1404 * 1 : csp = Current client state (buffers, headers, etc...)
1405 * Must be non-null. Reads: "csp->config"
1406 * Writes: various data members.
1408 * Returns : 0 => Ok, everything else is an error.
1410 *********************************************************************/
1411 int run_loader(struct client_state *csp)
1416 for (i=0; i < NLOADERS; i++)
1418 if (csp->config->loaders[i] == NULL)
1422 ret |= (csp->config->loaders[i])(csp);