1 const char loaders_rcs[] = "$Id: loaders.c,v 1.5 2001/05/23 10:39:05 oes 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 * IJBSWA team. http://ijbswa.sourceforge.net
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.5 2001/05/23 10:39:05 oes
39 * - Added support for escaping the comment character
40 * in config files by a backslash
41 * - Added support for line continuation in config
43 * - Fixed a buffer overflow bug with long config lines
45 * Revision 1.4 2001/05/22 18:56:28 oes
48 * Revision 1.3 2001/05/20 01:21:20 jongfoster
49 * Version 2.9.4 checkin.
50 * - Merged popupfile and cookiefile, and added control over PCRS
51 * filtering, in new "permissionsfile".
52 * - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
53 * file error you now get a message box (in the Win32 GUI) rather
54 * than the program exiting with no explanation.
55 * - Made killpopup use the PCRS MIME-type checking and HTTP-header
57 * - Removed tabs from "config"
58 * - Moved duplicated url parsing code in "loaders.c" to a new funcition.
59 * - Bumped up version number.
61 * Revision 1.2 2001/05/17 23:01:01 oes
62 * - Cleaned CRLF's from the sources and related files
64 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
65 * Initial import of version 2.9.3 source tree
68 *********************************************************************/
75 #include <sys/types.h>
97 #ifndef SPLIT_PROXY_ARGS
100 #endif /* ndef SPLIT_PROXY_ARGS */
102 const char loaders_h_rcs[] = LOADERS_H_VERSION;
104 /* Fix a problem with Solaris. There should be no effect on other
106 * Solaris's isspace() is a macro which uses it's argument directly
107 * as an array index. Therefore we need to make sure that high-bit
108 * characters generate +ve values, and ideally we also want to make
109 * the argument match the declared parameter type of "int".
111 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
115 static int (*loaders[NLOADERS])(struct client_state *);
119 * Currently active files.
120 * These are also entered in the main linked list of files.
122 static struct file_list *current_blockfile = NULL;
123 static struct file_list *current_permissions_file = NULL;
124 static struct file_list *current_forwardfile = NULL;
127 static struct file_list *current_aclfile = NULL;
128 #endif /* def ACL_FILES */
130 #ifdef USE_IMAGE_LIST
131 static struct file_list *current_imagefile = NULL;
132 #endif /* def USE_IMAGE_LIST */
135 static struct file_list *current_trustfile = NULL;
136 #endif /* def TRUST_FILES */
139 static struct file_list *current_re_filterfile = NULL;
140 #endif /* def PCRS */
143 static int create_url_spec(struct url_spec * url, char * buf);
146 /*********************************************************************
150 * Description : Basically a mark and sweep garbage collector, it is run
151 * (by the parent thread) every once in a while to reclaim memory.
153 * It uses a mark and sweep strategy:
154 * 1) mark all files as inactive
156 * 2) check with each client:
157 * if it is active, mark its files as active
158 * if it is inactive, free its resources
160 * 3) free the resources of all of the files that
161 * are still marked as inactive (and are obsolete).
163 * N.B. files that are not obsolete don't have an unloader defined.
169 *********************************************************************/
172 struct file_list *fl, *nfl;
173 struct client_state *csp, *ncsp;
175 /* clear all of the file's active flags */
176 for ( fl = files->next; NULL != fl; fl = fl->next )
181 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
185 /* mark this client's files as active */
187 if (ncsp->blist) /* block files */
189 ncsp->blist->active = 1;
192 if (ncsp->permissions_list) /* permissions files */
194 ncsp->permissions_list->active = 1;
197 if (ncsp->flist) /* forward files */
199 ncsp->flist->active = 1;
203 if (ncsp->alist) /* acl files */
205 ncsp->alist->active = 1;
207 #endif /* def ACL_FILES */
209 #ifdef USE_IMAGE_LIST
210 if (ncsp->ilist) /* image files */
212 ncsp->ilist->active = 1;
214 #endif /* def USE_IMAGE_LIST */
217 if (ncsp->rlist) /* perl re files */
219 ncsp->rlist->active = 1;
221 #endif /* def PCRS */
224 if (ncsp->tlist) /* trust files */
226 ncsp->tlist->active = 1;
228 #endif /* def TRUST_FILES */
233 /* this client one is not active, release its resources */
234 csp->next = ncsp->next;
236 freez(ncsp->ip_addr_str);
237 freez(ncsp->referrer);
238 freez(ncsp->x_forwarded);
239 freez(ncsp->ip_addr_str);
240 freez(ncsp->iob->buf);
242 free_http_request(ncsp->http);
244 destroy_list(ncsp->headers);
245 destroy_list(ncsp->cookie_list);
253 #endif /* def STATISTICS */
259 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
261 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
263 fl->next = nfl->next;
265 (nfl->unloader)(nfl->f);
267 #ifndef SPLIT_PROXY_ARGS
268 freez(nfl->proxy_args);
269 #endif /* ndef SPLIT_PROXY_ARGS */
271 freez(nfl->filename);
280 /*********************************************************************
282 * Function : create_url_spec
284 * Description : Creates a "url_spec" structure from a string.
285 * When finished, free with unload_url().
288 * 1 : url = Target url_spec to be filled in. Must be
289 * zeroed out before the call (e.g. using zalloc).
290 * 2 : buf = Source pattern, null terminated. NOTE: The
291 * contents of this buffer are destroyed by this
292 * function. If this function succeeds, the
293 * buffer is copied to url->spec. If this
294 * function fails, the contents of the buffer
297 * Returns : 0 => Ok, everything else is an error.
299 *********************************************************************/
300 static int create_url_spec(struct url_spec * url, char * buf)
303 struct url_spec tmp_url[1];
305 /* paranoia - should never happen. */
306 if ((url == NULL) || (buf == NULL))
311 /* save a copy of the orignal specification */
312 if ((url->spec = strdup(buf)) == NULL)
317 if ((p = strchr(buf, '/')))
319 if (NULL == (url->path = strdup(p)))
324 url->pathlen = strlen(url->path);
338 if (NULL == (url->preg = zalloc(sizeof(*url->preg))))
345 sprintf(rebuf, "^(%s)", url->path);
347 errcode = regcomp(url->preg, rebuf,
348 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
353 url->preg, buf, sizeof(buf));
357 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
368 if ((p = strchr(buf, ':')) == NULL)
378 if ((url->domain = strdup(buf)) == NULL)
384 #endif /* def REGEX */
388 /* split domain into components */
390 *tmp_url = dsplit(url->domain);
391 url->dbuf = tmp_url->dbuf;
392 url->dcnt = tmp_url->dcnt;
393 url->dvec = tmp_url->dvec;
399 /*********************************************************************
401 * Function : unload_url
403 * Description : Called from the "unloaders". Freez the url
404 * structure elements.
407 * 1 : url = pointer to a url_spec structure.
411 *********************************************************************/
412 static void unload_url(struct url_spec *url)
414 if (url == NULL) return;
433 /*********************************************************************
435 * Function : unload_aclfile
437 * Description : Unloads an aclfile.
440 * 1 : f = the data structure associated with the aclfile.
444 *********************************************************************/
445 static void unload_aclfile(void *f)
447 struct access_control_list *b = (struct access_control_list *)f;
448 if (b == NULL) return;
450 unload_aclfile(b->next);
455 #endif /* def ACL_FILES */
457 /*********************************************************************
459 * Function : unload_blockfile
461 * Description : Unloads a blockfile.
464 * 1 : f = the data structure associated with the blockfile.
468 *********************************************************************/
469 static void unload_blockfile(void *f)
471 struct block_spec *b = (struct block_spec *)f;
472 if (b == NULL) return;
474 unload_blockfile(b->next);
483 #ifdef USE_IMAGE_LIST
484 /*********************************************************************
486 * Function : unload_imagefile
488 * Description : Unloads an imagefile.
491 * 1 : f = the data structure associated with the imagefile.
495 *********************************************************************/
496 static void unload_imagefile(void *f)
498 struct block_spec *b = (struct block_spec *)f;
499 if (b == NULL) return;
501 unload_imagefile(b->next);
508 #endif /* def USE_IMAGE_LIST */
511 /*********************************************************************
513 * Function : unload_permissions_file
515 * Description : Unloads a permissions file.
518 * 1 : file_data = the data structure associated with the
523 *********************************************************************/
524 static void unload_permissions_file(void *file_data)
526 struct permissions_spec * next;
527 struct permissions_spec * cur = (struct permissions_spec *)file_data;
531 unload_url(cur->url);
540 /*********************************************************************
542 * Function : unload_trustfile
544 * Description : Unloads a trustfile.
547 * 1 : f = the data structure associated with the trustfile.
551 *********************************************************************/
552 static void unload_trustfile(void *f)
554 struct block_spec *b = (struct block_spec *)f;
555 if (b == NULL) return;
557 unload_trustfile(b->next);
564 #endif /* def TRUST_FILES */
567 /*********************************************************************
569 * Function : unload_forwardfile
571 * Description : Unloads a forwardfile.
574 * 1 : f = the data structure associated with the forwardfile.
578 *********************************************************************/
579 static void unload_forwardfile(void *f)
581 struct forward_spec *b = (struct forward_spec *)f;
582 if (b == NULL) return;
584 unload_forwardfile(b->next);
588 freez(b->gw->gateway_host);
589 freez(b->gw->forward_host);
597 /*********************************************************************
599 * Function : unload_re_filterfile
601 * Description : Unload the re_filter list.
604 * 1 : f = the data structure associated with the filterfile.
608 *********************************************************************/
609 static void unload_re_filterfile(void *f)
612 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
614 if (b == NULL) return;
616 destroy_list(b->patterns);
618 joblist = b->joblist;
619 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
624 #endif /* def PCRS */
627 /*********************************************************************
629 * Function : check_file_changed
631 * Description : Helper function to check if a file needs reloading.
632 * If "current" is still current, return it. Otherwise
633 * allocates a new (zeroed) "struct file_list", fills
634 * in the disk file name and timestamp, and returns it.
637 * 1 : current = The file_list currently being used - will
638 * be checked to see if it is out of date.
639 * May be NULL (which is treated as out of
641 * 2 : filename = Name of file to check.
642 * 3 : newfl = New file list. [Output only]
643 * This will be set to NULL, OR a struct
644 * file_list newly allocated on the
645 * heap, with the filename and lastmodified
646 * fields filled, standard header giving file
647 * name in proxy_args, and all others zeroed.
648 * (proxy_args is only filled in if !defined
649 * SPLIT_PROXY_ARGS and !suppress_blocklists).
651 * Returns : If file unchanged: 0 (and sets newfl == NULL)
652 * If file changed: 1 and sets newfl != NULL
653 * On error: 1 and sets newfl == NULL
655 *********************************************************************/
656 static int check_file_changed(const struct file_list * current,
657 const char * filename,
658 struct file_list ** newfl)
660 struct file_list *fs;
661 struct stat statbuf[1];
665 if (stat(filename, statbuf) < 0)
667 /* Error, probably file not found. */
672 && (current->lastmodified == statbuf->st_mtime)
673 && (0 == strcmp(current->filename, filename)))
678 fs = (struct file_list *)zalloc(sizeof(struct file_list));
682 /* Out of memory error */
686 fs->filename = strdup(filename);
687 fs->lastmodified = statbuf->st_mtime;
689 if (fs->filename == NULL)
691 /* Out of memory error */
696 #ifndef SPLIT_PROXY_ARGS
697 if (!suppress_blocklists)
699 char * p = html_encode(filename);
702 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
703 fs->proxy_args = strsav(fs->proxy_args, p);
704 fs->proxy_args = strsav(fs->proxy_args,
705 "' contains the following patterns</h2>\n");
708 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
710 #endif /* ndef SPLIT_PROXY_ARGS */
717 /*********************************************************************
719 * Function : read_config_line
721 * Description : Read a single non-empty line from a file and return
722 * it. Trims comments, leading and trailing whitespace
723 * and respects escaping of newline and comment char.
724 * Also writes the file to fs->proxy_args.
727 * 1 : buf = Buffer to use.
728 * 2 : buflen = Size of buffer in bytes.
729 * 3 : fp = File to read from
730 * 4 : fs = File will be written to fs->proxy_args. May
731 * be NULL to disable this feature.
733 * Returns : NULL on EOF or error
734 * Otherwise, returns buf.
736 *********************************************************************/
737 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
740 char linebuf[BUFSIZ];
745 while (fgets(linebuf, sizeof(linebuf), fp))
747 #ifndef SPLIT_PROXY_ARGS
748 if (fs && !suppress_blocklists)
750 char *html_line = html_encode(linebuf);
751 if (html_line != NULL)
753 fs->proxy_args = strsav(fs->proxy_args, html_line);
756 fs->proxy_args = strsav(fs->proxy_args, "<br>");
758 #endif /* ndef SPLIT_PROXY_ARGS */
760 /* Trim off newline */
761 if ((p = strpbrk(linebuf, "\r\n")) != NULL)
766 /* Line continuation? Trim escape and set flag. */
767 if ((p != linebuf) && (*--p == '\\'))
773 /* If there's a comment char.. */
774 if ((p = strpbrk(linebuf, "#")) != NULL)
776 /* ..and it's escaped, left-shift the line over the escape. */
777 if ((p != linebuf) && (*(p-1) == '\\'))
780 while ((*q++ = *p++) != '\0') /* nop */;
782 /* Else, chop off the rest of the line */
789 /* Trim leading whitespace */
791 while (*p && ijb_isspace(*p))
798 /* There is something other than whitespace on the line. */
800 /* Move the data to the start of buf */
803 /* strcpy that can cope with overlap. */
805 while ((*q++ = *p++) != '\0')
811 /* Trim trailing whitespace */
812 p = linebuf + strlen(linebuf) - 1;
815 * Note: the (p >= linebuf) below is paranoia, it's not really needed.
816 * When p == linebuf then ijb_isspace(*p) will be false and we'll drop
819 while ((p >= linebuf) && ijb_isspace(*p))
825 /* More paranoia. This if statement is always true. */
828 strncat(buf, linebuf, buflen - strlen(buf));
848 /*********************************************************************
850 * Function : load_aclfile
852 * Description : Read and parse an aclfile and add to files list.
855 * 1 : csp = Current client state (buffers, headers, etc...)
857 * Returns : 0 => Ok, everything else is an error.
859 *********************************************************************/
860 int load_aclfile(struct client_state *csp)
863 char buf[BUFSIZ], *v[3], *p;
865 struct access_control_list *a, *bl;
866 struct file_list *fs;
868 if (!check_file_changed(current_aclfile, aclfile, &fs))
870 /* No need to load */
873 csp->alist = current_aclfile;
879 goto load_aclfile_error;
882 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
887 goto load_aclfile_error;
890 fp = fopen(aclfile, "r");
894 goto load_aclfile_error;
897 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
899 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
901 /* allocate a new node */
902 a = (struct access_control_list *) zalloc(sizeof(*a));
910 goto load_aclfile_error;
913 /* add it to the list */
920 if (acl_addr(v[2], a->dst) < 0)
922 goto load_aclfile_error;
927 if (acl_addr(v[1], a->src) < 0)
929 goto load_aclfile_error;
933 if (strcmpic(p, "permit") == 0)
935 a->action = ACL_PERMIT;
939 if (strcmpic(p, "deny") == 0)
941 a->action = ACL_DENY;
947 goto load_aclfile_error;
953 #ifndef SPLIT_PROXY_ARGS
954 if (!suppress_blocklists)
956 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
958 #endif /* ndef SPLIT_PROXY_ARGS */
962 current_aclfile->unloader = unload_aclfile;
965 fs->next = files->next;
967 current_aclfile = fs;
977 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
981 #endif /* def ACL_FILES */
984 /*********************************************************************
986 * Function : load_blockfile
988 * Description : Read and parse a blockfile and add to files list.
991 * 1 : csp = Current client state (buffers, headers, etc...)
993 * Returns : 0 => Ok, everything else is an error.
995 *********************************************************************/
996 int load_blockfile(struct client_state *csp)
1000 struct block_spec *b, *bl;
1001 char buf[BUFSIZ], *p, *q;
1003 struct file_list *fs;
1005 if (!check_file_changed(current_blockfile, blockfile, &fs))
1007 /* No need to load */
1010 csp->blist = current_blockfile;
1016 goto load_blockfile_error;
1019 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
1022 goto load_blockfile_error;
1025 if ((fp = fopen(blockfile, "r")) == NULL)
1027 goto load_blockfile_error;
1030 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1039 while ((*p++ = *q++))
1045 /* skip lines containing only ~ */
1051 /* allocate a new node */
1052 if ((b = zalloc(sizeof(*b))) == NULL)
1055 goto load_blockfile_error;
1058 /* add it to the list */
1064 /* Save the URL pattern */
1065 if (create_url_spec(b->url, buf))
1068 goto load_blockfile_error;
1074 #ifndef SPLIT_PROXY_ARGS
1075 if (!suppress_blocklists)
1077 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1079 #endif /* ndef SPLIT_PROXY_ARGS */
1081 /* the old one is now obsolete */
1082 if (current_blockfile)
1084 current_blockfile->unloader = unload_blockfile;
1087 fs->next = files->next;
1089 current_blockfile = fs;
1098 load_blockfile_error:
1099 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
1105 #ifdef USE_IMAGE_LIST
1106 /*********************************************************************
1108 * Function : load_imagefile
1110 * Description : Read and parse an imagefile and add to files list.
1113 * 1 : csp = Current client state (buffers, headers, etc...)
1115 * Returns : 0 => Ok, everything else is an error.
1117 *********************************************************************/
1118 int load_imagefile(struct client_state *csp)
1122 struct block_spec *b, *bl;
1123 char buf[BUFSIZ], *p, *q;
1125 struct file_list *fs;
1127 if (!check_file_changed(current_imagefile, imagefile, &fs))
1129 /* No need to load */
1132 csp->ilist = current_imagefile;
1138 goto load_imagefile_error;
1141 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1144 goto load_imagefile_error;
1147 if ((fp = fopen(imagefile, "r")) == NULL)
1149 goto load_imagefile_error;
1152 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1161 while ((*p++ = *q++))
1167 /* skip lines containing only ~ */
1173 /* allocate a new node */
1174 if ((b = zalloc(sizeof(*b))) == NULL)
1177 goto load_imagefile_error;
1180 /* add it to the list */
1186 /* Save the URL pattern */
1187 if (create_url_spec(b->url, buf))
1190 goto load_imagefile_error;
1196 #ifndef SPLIT_PROXY_ARGS
1197 if (!suppress_blocklists)
1199 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1201 #endif /* ndef SPLIT_PROXY_ARGS */
1203 /* the old one is now obsolete */
1204 if (current_imagefile)
1206 current_imagefile->unloader = unload_imagefile;
1209 fs->next = files->next;
1211 current_imagefile = fs;
1220 load_imagefile_error:
1221 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
1225 #endif /* def USE_IMAGE_LIST */
1228 /*********************************************************************
1230 * Function : load_permissions_file
1232 * Description : Read and parse a permissions file and add to files
1236 * 1 : csp = Current client state (buffers, headers, etc...)
1238 * Returns : 0 => Ok, everything else is an error.
1240 *********************************************************************/
1241 int load_permissions_file(struct client_state *csp)
1245 struct permissions_spec *b, *bl;
1246 char buf[BUFSIZ], *p, *q;
1248 struct file_list *fs;
1251 if (!check_file_changed(current_permissions_file, permissions_file, &fs))
1253 /* No need to load */
1256 csp->permissions_list = current_permissions_file;
1262 goto load_permissions_error;
1265 fs->f = bl = (struct permissions_spec *)zalloc(sizeof(*bl));
1268 goto load_permissions_error;
1271 if ((fp = fopen(permissions_file, "r")) == NULL)
1273 goto load_permissions_error;
1278 * default_permissions is set in this file.
1280 * Reset it to default first.
1282 default_permissions = PERMIT_RE_FILTER;
1284 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1288 permissions = PERMIT_COOKIE_SET | PERMIT_COOKIE_READ | PERMIT_POPUPS;
1291 * FIXME: for() loop is a kludge. Want to loop around until we
1292 * find a non-control character. Assume there will be at most 4
1295 for (i = 0; i < 4; i++)
1301 * Allow cookies to be read by the server, but do
1302 * not allow them to be set.
1304 permissions = (permissions & ~PERMIT_COOKIE_SET);
1310 * Allow server to set cookies but do not let the
1313 permissions = (permissions & ~PERMIT_COOKIE_READ);
1321 permissions = (permissions & ~PERMIT_POPUPS);
1327 * Permit filtering using PCRS
1329 permissions = (permissions | PERMIT_RE_FILTER);
1335 * All of the above (maximum filtering).
1337 permissions = PERMIT_RE_FILTER;
1343 * FIXME: Should break out of the loop here.
1350 * Elide any of the "special" chars from the
1351 * front of the pattern
1356 while ((*q++ = *p++) != '\0')
1362 /* a lines containing only "special" chars sets default */
1365 default_permissions = permissions;
1369 /* allocate a new node */
1370 if (((b = zalloc(sizeof(*b))) == NULL)
1374 goto load_permissions_error;
1377 /* add it to the list */
1382 b->permissions = permissions;
1384 /* Save the URL pattern */
1385 if (create_url_spec(b->url, buf))
1388 goto load_permissions_error;
1394 #ifndef SPLIT_PROXY_ARGS
1395 if (!suppress_blocklists)
1397 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1399 #endif /* ndef SPLIT_PROXY_ARGS */
1401 /* the old one is now obsolete */
1402 if (current_permissions_file)
1404 current_permissions_file->unloader = unload_permissions_file;
1407 fs->next = files->next;
1409 current_permissions_file = fs;
1413 csp->permissions_list = fs;
1418 load_permissions_error:
1419 log_error(LOG_LEVEL_ERROR, "can't load permissions file '%s': %E", permissions_file);
1426 /*********************************************************************
1428 * Function : load_trustfile
1430 * Description : Read and parse a trustfile and add to files list.
1433 * 1 : csp = Current client state (buffers, headers, etc...)
1435 * Returns : 0 => Ok, everything else is an error.
1437 *********************************************************************/
1438 int load_trustfile(struct client_state *csp)
1442 struct block_spec *b, *bl;
1443 struct url_spec **tl;
1445 char buf[BUFSIZ], *p, *q;
1446 int reject, trusted;
1447 struct file_list *fs;
1449 if (!check_file_changed(current_trustfile, trustfile, &fs))
1451 /* No need to load */
1454 csp->tlist = current_trustfile;
1460 goto load_trustfile_error;
1463 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1466 goto load_trustfile_error;
1469 if ((fp = fopen(trustfile, "r")) == NULL)
1471 goto load_trustfile_error;
1476 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1492 while ((*p++ = *q++))
1498 /* skip blank lines */
1504 /* allocate a new node */
1505 if ((b = zalloc(sizeof(*b))) == NULL)
1508 goto load_trustfile_error;
1511 /* add it to the list */
1517 /* Save the URL pattern */
1518 if (create_url_spec(b->url, buf))
1521 goto load_trustfile_error;
1525 * save a pointer to URL's spec in the list of trusted URL's, too
1537 #ifndef SPLIT_PROXY_ARGS
1538 if (!suppress_blocklists)
1540 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1542 #endif /* ndef SPLIT_PROXY_ARGS */
1544 /* the old one is now obsolete */
1545 if (current_trustfile)
1547 current_trustfile->unloader = unload_trustfile;
1550 fs->next = files->next;
1552 current_trustfile = fs;
1561 load_trustfile_error:
1562 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
1566 #endif /* def TRUST_FILES */
1569 /*********************************************************************
1571 * Function : load_forwardfile
1573 * Description : Read and parse a forwardfile and add to files list.
1576 * 1 : csp = Current client state (buffers, headers, etc...)
1578 * Returns : 0 => Ok, everything else is an error.
1580 *********************************************************************/
1581 int load_forwardfile(struct client_state *csp)
1585 struct forward_spec *b, *bl;
1586 char buf[BUFSIZ], *p, *q, *tmp;
1588 int port, n, reject;
1589 struct file_list *fs;
1590 const struct gateway *gw;
1591 struct url_spec url[1];
1593 if (!check_file_changed(current_forwardfile, forwardfile, &fs))
1595 /* No need to load */
1598 csp->flist = current_forwardfile;
1604 goto load_forwardfile_error;
1607 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1609 if ((fs == NULL) || (bl == NULL))
1611 goto load_forwardfile_error;
1614 if ((fp = fopen(forwardfile, "r")) == NULL)
1616 goto load_forwardfile_error;
1621 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1627 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1631 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1635 strcpy(buf, vec[0]);
1644 while ((*p++ = *q++))
1650 /* skip lines containing only ~ */
1656 /* allocate a new node */
1657 if (((b = zalloc(sizeof(*b))) == NULL)
1659 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1664 goto load_forwardfile_error;
1667 /* add it to the list */
1671 /* save a copy of the orignal specification */
1672 if ((b->url->spec = strdup(buf)) == NULL)
1675 goto load_forwardfile_error;
1680 if ((p = strchr(buf, '/')))
1682 b->url->path = strdup(p);
1683 b->url->pathlen = strlen(b->url->path);
1688 b->url->path = NULL;
1689 b->url->pathlen = 0;
1697 sprintf(rebuf, "^(%s)", b->url->path);
1699 errcode = regcomp(b->url->preg, rebuf,
1700 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1704 size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
1708 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1711 goto load_forwardfile_error;
1716 freez(b->url->preg);
1719 if ((p = strchr(buf, ':')) == NULL)
1729 b->url->port = port;
1731 if ((b->url->domain = strdup(buf)) == NULL)
1734 goto load_forwardfile_error;
1737 /* split domain into components */
1738 *url = dsplit(b->url->domain);
1739 b->url->dbuf = url->dbuf;
1740 b->url->dcnt = url->dcnt;
1741 b->url->dvec = url->dvec;
1743 /* now parse the gateway specs */
1747 for (gw = gateways; gw->name; gw++)
1749 if (strcmp(gw->name, p) == 0)
1755 if (gw->name == NULL)
1757 goto load_forwardfile_error;
1760 /* save this as the gateway type */
1763 /* now parse the gateway host[:port] spec */
1766 if (strcmp(p, ".") != 0)
1768 b->gw->gateway_host = strdup(p);
1770 if ((p = strchr(b->gw->gateway_host, ':')))
1773 b->gw->gateway_port = atoi(p);
1776 if (b->gw->gateway_port <= 0)
1778 goto load_forwardfile_error;
1782 /* now parse the forwarding spec */
1785 if (strcmp(p, ".") != 0)
1787 b->gw->forward_host = strdup(p);
1789 if ((p = strchr(b->gw->forward_host, ':')))
1792 b->gw->forward_port = atoi(p);
1795 if (b->gw->forward_port <= 0)
1797 b->gw->forward_port = 8000;
1806 #ifndef SPLIT_PROXY_ARGS
1807 if (!suppress_blocklists)
1809 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1811 #endif /* ndef SPLIT_PROXY_ARGS */
1813 /* the old one is now obsolete */
1814 if (current_forwardfile)
1816 current_forwardfile->unloader = unload_forwardfile;
1819 fs->next = files->next;
1821 current_forwardfile = fs;
1830 load_forwardfile_error:
1831 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
1838 /*********************************************************************
1840 * Function : load_re_filterfile
1842 * Description : Load the re_filterfile. Each non-comment, non-empty
1843 * line is instantly added to the joblist, which is
1844 * a chained list of pcrs_job structs.
1847 * 1 : csp = Current client state (buffers, headers, etc...)
1849 * Returns : 0 => Ok, everything else is an error.
1851 *********************************************************************/
1852 int load_re_filterfile(struct client_state *csp)
1856 struct re_filterfile_spec *bl;
1857 struct file_list *fs;
1863 if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
1865 /* No need to load */
1868 csp->rlist = current_re_filterfile;
1874 goto load_re_filterfile_error;
1877 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1880 goto load_re_filterfile_error;
1883 /* Open the file or fail */
1884 if ((fp = fopen(re_filterfile, "r")) == NULL)
1886 goto load_re_filterfile_error;
1889 /* Read line by line */
1890 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1892 enlist( bl->patterns, buf );
1894 /* We have a meaningful line -> make it a job */
1895 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
1897 log_error(LOG_LEVEL_RE_FILTER,
1898 "Adding re_filter job %s failed with error %d.", buf, error);
1903 dummy->next = bl->joblist;
1904 bl->joblist = dummy;
1905 log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s succeeded.", buf);
1911 #ifndef SPLIT_PROXY_ARGS
1912 if (!suppress_blocklists)
1914 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1916 #endif /* ndef SPLIT_PROXY_ARGS */
1918 /* the old one is now obsolete */
1919 if ( NULL != current_re_filterfile )
1921 current_re_filterfile->unloader = unload_re_filterfile;
1924 fs->next = files->next;
1926 current_re_filterfile = fs;
1935 load_re_filterfile_error:
1936 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
1940 #endif /* def PCRS */
1943 /*********************************************************************
1945 * Function : add_loader
1947 * Description : Called from `load_config'. Called once for each input
1948 * file found in config.
1951 * 1 : loader = pointer to a function that can parse and load
1952 * the appropriate config file.
1956 *********************************************************************/
1957 void add_loader(int (*loader)(struct client_state *))
1961 for (i=0; i < NLOADERS; i++)
1963 if (loaders[i] == NULL)
1965 loaders[i] = loader;
1973 /*********************************************************************
1975 * Function : run_loader
1977 * Description : Called from `load_config' and `listen_loop'. This
1978 * function keeps the "csp" current with any file mods
1979 * since the last loop. If a file is unchanged, the
1980 * loader functions do NOT reload the file.
1983 * 1 : csp = Current client state (buffers, headers, etc...)
1985 * Returns : 0 => Ok, everything else is an error.
1987 *********************************************************************/
1988 int run_loader(struct client_state *csp)
1993 for (i=0; i < NLOADERS; i++)
1995 if (loaders[i] == NULL)
1999 ret |= (loaders[i])(csp);
2006 /*********************************************************************
2008 * Function : remove_all_loaders
2010 * Description : Remove all loaders from the list.
2016 *********************************************************************/
2017 void remove_all_loaders(void)
2019 memset( loaders, 0, sizeof( loaders ) );