1 const char loaders_rcs[] = "$Id: loaders.c,v 1.2 2001/05/17 23:01:01 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.2 2001/05/17 23:01:01 oes
39 * - Cleaned CRLF's from the sources and related files
41 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
42 * Initial import of version 2.9.3 source tree
45 *********************************************************************/
52 #include <sys/types.h>
74 #ifndef SPLIT_PROXY_ARGS
77 #endif /* ndef SPLIT_PROXY_ARGS */
79 const char loaders_h_rcs[] = LOADERS_H_VERSION;
81 /* Fix a problem with Solaris. There should be no effect on other
83 * Solaris's isspace() is a macro which uses it's argument directly
84 * as an array index. Therefore we need to make sure that high-bit
85 * characters generate +ve values, and ideally we also want to make
86 * the argument match the declared parameter type of "int".
88 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
92 static int (*loaders[NLOADERS])(struct client_state *);
96 * Currently active files.
97 * These are also entered in the main linked list of files.
99 static struct file_list *current_blockfile = NULL;
100 static struct file_list *current_permissions_file = NULL;
101 static struct file_list *current_forwardfile = NULL;
104 static struct file_list *current_aclfile = NULL;
105 #endif /* def ACL_FILES */
107 #ifdef USE_IMAGE_LIST
108 static struct file_list *current_imagefile = NULL;
109 #endif /* def USE_IMAGE_LIST */
112 static struct file_list *current_trustfile = NULL;
113 #endif /* def TRUST_FILES */
116 static struct file_list *current_re_filterfile = NULL;
117 #endif /* def PCRS */
120 static int create_url_spec(struct url_spec * url, char * buf);
\r
123 /*********************************************************************
127 * Description : Basically a mark and sweep garbage collector, it is run
128 * (by the parent thread) every once in a while to reclaim memory.
130 * It uses a mark and sweep strategy:
131 * 1) mark all files as inactive
133 * 2) check with each client:
134 * if it is active, mark its files as active
135 * if it is inactive, free its resources
137 * 3) free the resources of all of the files that
138 * are still marked as inactive (and are obsolete).
140 * N.B. files that are not obsolete don't have an unloader defined.
146 *********************************************************************/
149 struct file_list *fl, *nfl;
150 struct client_state *csp, *ncsp;
152 /* clear all of the file's active flags */
153 for ( fl = files->next; NULL != fl; fl = fl->next )
158 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
162 /* mark this client's files as active */
164 if (ncsp->blist) /* block files */
166 ncsp->blist->active = 1;
169 if (ncsp->permissions_list) /* permissions files */
171 ncsp->permissions_list->active = 1;
174 if (ncsp->flist) /* forward files */
176 ncsp->flist->active = 1;
180 if (ncsp->alist) /* acl files */
182 ncsp->alist->active = 1;
184 #endif /* def ACL_FILES */
186 #ifdef USE_IMAGE_LIST
187 if (ncsp->ilist) /* image files */
189 ncsp->ilist->active = 1;
191 #endif /* def USE_IMAGE_LIST */
194 if (ncsp->rlist) /* perl re files */
196 ncsp->rlist->active = 1;
198 #endif /* def PCRS */
201 if (ncsp->tlist) /* trust files */
203 ncsp->tlist->active = 1;
205 #endif /* def TRUST_FILES */
210 /* this client one is not active, release its resources */
211 csp->next = ncsp->next;
213 freez(ncsp->ip_addr_str);
214 freez(ncsp->referrer);
215 freez(ncsp->x_forwarded);
216 freez(ncsp->ip_addr_str);
217 freez(ncsp->iob->buf);
219 free_http_request(ncsp->http);
221 destroy_list(ncsp->headers);
222 destroy_list(ncsp->cookie_list);
230 #endif /* def STATISTICS */
236 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
238 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
240 fl->next = nfl->next;
242 (nfl->unloader)(nfl->f);
244 #ifndef SPLIT_PROXY_ARGS
245 freez(nfl->proxy_args);
246 #endif /* ndef SPLIT_PROXY_ARGS */
248 freez(nfl->filename);
257 /*********************************************************************
\r
259 * Function : create_url_spec
\r
261 * Description : Creates a "url_spec" structure from a string.
\r
262 * When finished, free with unload_url().
\r
265 * 1 : url = Target url_spec to be filled in. Must be
\r
266 * zeroed out before the call (e.g. using zalloc).
\r
267 * 2 : buf = Source pattern, null terminated. NOTE: The
\r
268 * contents of this buffer are destroyed by this
\r
269 * function. If this function succeeds, the
\r
270 * buffer is copied to url->spec. If this
\r
271 * function fails, the contents of the buffer
\r
272 * are lost forever.
\r
274 * Returns : 0 => Ok, everything else is an error.
\r
276 *********************************************************************/
\r
277 static int create_url_spec(struct url_spec * url, char * buf)
\r
280 struct url_spec tmp_url[1];
\r
282 /* paranoia - should never happen. */
\r
283 if ((url == NULL) || (buf == NULL))
\r
288 /* save a copy of the orignal specification */
\r
289 if ((url->spec = strdup(buf)) == NULL)
\r
294 if ((p = strchr(buf, '/')))
\r
296 if (NULL == (url->path = strdup(p)))
\r
301 url->pathlen = strlen(url->path);
\r
313 char rebuf[BUFSIZ];
\r
315 if (NULL == (url->preg = zalloc(sizeof(*url->preg))))
\r
322 sprintf(rebuf, "^(%s)", url->path);
\r
324 errcode = regcomp(url->preg, rebuf,
\r
325 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
\r
330 url->preg, buf, sizeof(buf));
\r
332 buf[errlen] = '\0';
\r
334 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
\r
345 if ((p = strchr(buf, ':')) == NULL)
\r
352 url->port = atoi(p);
\r
355 if ((url->domain = strdup(buf)) == NULL)
\r
361 #endif /* def REGEX */
\r
365 /* split domain into components */
\r
367 *tmp_url = dsplit(url->domain);
\r
368 url->dbuf = tmp_url->dbuf;
\r
369 url->dcnt = tmp_url->dcnt;
\r
370 url->dvec = tmp_url->dvec;
\r
376 /*********************************************************************
378 * Function : unload_url
380 * Description : Called from the "unloaders". Freez the url
381 * structure elements.
384 * 1 : url = pointer to a url_spec structure.
388 *********************************************************************/
389 static void unload_url(struct url_spec *url)
391 if (url == NULL) return;
410 /*********************************************************************
412 * Function : unload_aclfile
414 * Description : Unloads an aclfile.
417 * 1 : f = the data structure associated with the aclfile.
421 *********************************************************************/
422 static void unload_aclfile(void *f)
424 struct access_control_list *b = (struct access_control_list *)f;
425 if (b == NULL) return;
427 unload_aclfile(b->next);
432 #endif /* def ACL_FILES */
434 /*********************************************************************
436 * Function : unload_blockfile
438 * Description : Unloads a blockfile.
441 * 1 : f = the data structure associated with the blockfile.
445 *********************************************************************/
446 static void unload_blockfile(void *f)
448 struct block_spec *b = (struct block_spec *)f;
449 if (b == NULL) return;
451 unload_blockfile(b->next);
460 #ifdef USE_IMAGE_LIST
461 /*********************************************************************
463 * Function : unload_imagefile
465 * Description : Unloads an imagefile.
468 * 1 : f = the data structure associated with the imagefile.
472 *********************************************************************/
473 static void unload_imagefile(void *f)
475 struct block_spec *b = (struct block_spec *)f;
476 if (b == NULL) return;
478 unload_imagefile(b->next);
485 #endif /* def USE_IMAGE_LIST */
488 /*********************************************************************
490 * Function : unload_permissions_file
492 * Description : Unloads a permissions file.
495 * 1 : file_data = the data structure associated with the
\r
500 *********************************************************************/
501 static void unload_permissions_file(void *file_data)
503 struct permissions_spec * next;
504 struct permissions_spec * cur = (struct permissions_spec *)file_data;
505 while (cur != NULL)
\r
508 unload_url(cur->url);
517 /*********************************************************************
519 * Function : unload_trustfile
521 * Description : Unloads a trustfile.
524 * 1 : f = the data structure associated with the trustfile.
528 *********************************************************************/
529 static void unload_trustfile(void *f)
531 struct block_spec *b = (struct block_spec *)f;
532 if (b == NULL) return;
534 unload_trustfile(b->next);
541 #endif /* def TRUST_FILES */
544 /*********************************************************************
546 * Function : unload_forwardfile
548 * Description : Unloads a forwardfile.
551 * 1 : f = the data structure associated with the forwardfile.
555 *********************************************************************/
556 static void unload_forwardfile(void *f)
558 struct forward_spec *b = (struct forward_spec *)f;
559 if (b == NULL) return;
561 unload_forwardfile(b->next);
565 freez(b->gw->gateway_host);
566 freez(b->gw->forward_host);
574 /*********************************************************************
576 * Function : unload_re_filterfile
578 * Description : Unload the re_filter list.
581 * 1 : f = the data structure associated with the filterfile.
585 *********************************************************************/
586 static void unload_re_filterfile(void *f)
589 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
591 if (b == NULL) return;
593 destroy_list(b->patterns);
595 joblist = b->joblist;
596 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
601 #endif /* def PCRS */
604 /*********************************************************************
606 * Function : check_file_changed
608 * Description : Helper function to check if a file needs reloading.
609 * If "current" is still current, return it. Otherwise
610 * allocates a new (zeroed) "struct file_list", fills
611 * in the disk file name and timestamp, and returns it.
614 * 1 : current = The file_list currently being used - will
615 * be checked to see if it is out of date.
616 * May be NULL (which is treated as out of
618 * 2 : filename = Name of file to check.
619 * 3 : newfl = New file list. [Output only]
620 * This will be set to NULL, OR a struct
621 * file_list newly allocated on the
622 * heap, with the filename and lastmodified
623 * fields filled, standard header giving file
624 * name in proxy_args, and all others zeroed.
625 * (proxy_args is only filled in if !defined
626 * SPLIT_PROXY_ARGS and !suppress_blocklists).
628 * Returns : If file unchanged: 0 (and sets newfl == NULL)
629 * If file changed: 1 and sets newfl != NULL
630 * On error: 1 and sets newfl == NULL
632 *********************************************************************/
633 static int check_file_changed(const struct file_list * current,
634 const char * filename,
635 struct file_list ** newfl)
637 struct file_list *fs;
638 struct stat statbuf[1];
642 if (stat(filename, statbuf) < 0)
644 /* Error, probably file not found. */
649 && (current->lastmodified == statbuf->st_mtime)
650 && (0 == strcmp(current->filename, filename)))
655 fs = (struct file_list *)zalloc(sizeof(struct file_list));
659 /* Out of memory error */
663 fs->filename = strdup(filename);
664 fs->lastmodified = statbuf->st_mtime;
666 if (fs->filename == NULL)
668 /* Out of memory error */
673 #ifndef SPLIT_PROXY_ARGS
674 if (!suppress_blocklists)
676 char * p = html_encode(filename);
679 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
680 fs->proxy_args = strsav(fs->proxy_args, p);
681 fs->proxy_args = strsav(fs->proxy_args,
682 "' contains the following patterns</h2>\n");
685 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
687 #endif /* ndef SPLIT_PROXY_ARGS */
694 /*********************************************************************
696 * Function : read_config_line
698 * Description : Read a single non-empty line from a file and return
699 * it. Trims comments, leading and trailing whitespace.
700 * Also wites the file to fs->proxy_args.
703 * 1 : buf = Buffer to use.
704 * 2 : buflen = Size of buffer in bytes.
705 * 3 : fp = File to read from
706 * 4 : fs = File will be written to fs->proxy_args. May
707 * be NULL to disable this feature.
709 * Returns : NULL on EOF or error
710 * Otherwise, returns buf.
712 *********************************************************************/
713 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
716 char linebuf[BUFSIZ];
718 while (fgets(linebuf, sizeof(linebuf), fp))
720 #ifndef SPLIT_PROXY_ARGS
721 if (fs && !suppress_blocklists)
723 char *html_line = html_encode(linebuf);
724 if (html_line != NULL)
726 fs->proxy_args = strsav(fs->proxy_args, html_line);
729 fs->proxy_args = strsav(fs->proxy_args, "<br>");
731 #endif /* ndef SPLIT_PROXY_ARGS */
733 /* Trim off newline and any comment */
734 if ((p = strpbrk(linebuf, "\r\n#")) != NULL)
739 /* Trim leading whitespace */
741 while (*p && ijb_isspace(*p))
748 /* There is something other than whitespace on the line. */
750 /* Move the data to the start of buf */
753 /* strcpy that can cope with overlap. */
755 while ((*q++ = *p++) != '\0')
761 /* Trim trailing whitespace */
762 p = linebuf + strlen(linebuf) - 1;
765 * Note: the (p >= linebuf) below is paranoia, it's not really needed.
766 * When p == linebuf then ijb_isspace(*p) will be false and we'll drop
769 while ((p >= linebuf) && ijb_isspace(*p))
775 /* More paranoia. This if statement is always true. */
778 strcpy(buf, linebuf);
790 /*********************************************************************
792 * Function : load_aclfile
794 * Description : Read and parse an aclfile and add to files list.
797 * 1 : csp = Current client state (buffers, headers, etc...)
799 * Returns : 0 => Ok, everything else is an error.
801 *********************************************************************/
802 int load_aclfile(struct client_state *csp)
805 char buf[BUFSIZ], *v[3], *p;
807 struct access_control_list *a, *bl;
808 struct file_list *fs;
810 if (!check_file_changed(current_aclfile, aclfile, &fs))
812 /* No need to load */
815 csp->alist = current_aclfile;
821 goto load_aclfile_error;
824 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
829 goto load_aclfile_error;
832 fp = fopen(aclfile, "r");
836 goto load_aclfile_error;
839 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
841 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
843 /* allocate a new node */
844 a = (struct access_control_list *) zalloc(sizeof(*a));
852 goto load_aclfile_error;
855 /* add it to the list */
862 if (acl_addr(v[2], a->dst) < 0)
864 goto load_aclfile_error;
869 if (acl_addr(v[1], a->src) < 0)
871 goto load_aclfile_error;
875 if (strcmpic(p, "permit") == 0)
877 a->action = ACL_PERMIT;
881 if (strcmpic(p, "deny") == 0)
883 a->action = ACL_DENY;
889 goto load_aclfile_error;
895 #ifndef SPLIT_PROXY_ARGS
896 if (!suppress_blocklists)
898 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
900 #endif /* ndef SPLIT_PROXY_ARGS */
904 current_aclfile->unloader = unload_aclfile;
907 fs->next = files->next;
909 current_aclfile = fs;
919 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
923 #endif /* def ACL_FILES */
926 /*********************************************************************
928 * Function : load_blockfile
930 * Description : Read and parse a blockfile and add to files list.
933 * 1 : csp = Current client state (buffers, headers, etc...)
935 * Returns : 0 => Ok, everything else is an error.
937 *********************************************************************/
938 int load_blockfile(struct client_state *csp)
942 struct block_spec *b, *bl;
943 char buf[BUFSIZ], *p, *q;
945 struct file_list *fs;
947 if (!check_file_changed(current_blockfile, blockfile, &fs))
949 /* No need to load */
952 csp->blist = current_blockfile;
958 goto load_blockfile_error;
961 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
964 goto load_blockfile_error;
967 if ((fp = fopen(blockfile, "r")) == NULL)
969 goto load_blockfile_error;
972 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
981 while ((*p++ = *q++))
987 /* skip lines containing only ~ */
993 /* allocate a new node */
994 if ((b = zalloc(sizeof(*b))) == NULL)
997 goto load_blockfile_error;
1000 /* add it to the list */
1006 /* Save the URL pattern */
\r
1007 if (create_url_spec(b->url, buf))
\r
1010 goto load_blockfile_error;
\r
1016 #ifndef SPLIT_PROXY_ARGS
1017 if (!suppress_blocklists)
1019 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1021 #endif /* ndef SPLIT_PROXY_ARGS */
1023 /* the old one is now obsolete */
1024 if (current_blockfile)
1026 current_blockfile->unloader = unload_blockfile;
1029 fs->next = files->next;
1031 current_blockfile = fs;
1040 load_blockfile_error:
1041 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
1047 #ifdef USE_IMAGE_LIST
1048 /*********************************************************************
1050 * Function : load_imagefile
1052 * Description : Read and parse an imagefile and add to files list.
1055 * 1 : csp = Current client state (buffers, headers, etc...)
1057 * Returns : 0 => Ok, everything else is an error.
1059 *********************************************************************/
1060 int load_imagefile(struct client_state *csp)
1064 struct block_spec *b, *bl;
1065 char buf[BUFSIZ], *p, *q;
1067 struct file_list *fs;
1069 if (!check_file_changed(current_imagefile, imagefile, &fs))
1071 /* No need to load */
1074 csp->ilist = current_imagefile;
1080 goto load_imagefile_error;
1083 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1086 goto load_imagefile_error;
1089 if ((fp = fopen(imagefile, "r")) == NULL)
1091 goto load_imagefile_error;
1094 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1103 while ((*p++ = *q++))
1109 /* skip lines containing only ~ */
1115 /* allocate a new node */
1116 if ((b = zalloc(sizeof(*b))) == NULL)
1119 goto load_imagefile_error;
1122 /* add it to the list */
1126 b->reject = reject;
\r
1128 /* Save the URL pattern */
\r
1129 if (create_url_spec(b->url, buf))
\r
1132 goto load_imagefile_error;
1138 #ifndef SPLIT_PROXY_ARGS
1139 if (!suppress_blocklists)
1141 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1143 #endif /* ndef SPLIT_PROXY_ARGS */
1145 /* the old one is now obsolete */
1146 if (current_imagefile)
1148 current_imagefile->unloader = unload_imagefile;
1151 fs->next = files->next;
1153 current_imagefile = fs;
1162 load_imagefile_error:
1163 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
1167 #endif /* def USE_IMAGE_LIST */
1170 /*********************************************************************
1172 * Function : load_permissions_file
1174 * Description : Read and parse a permissions file and add to files
\r
1178 * 1 : csp = Current client state (buffers, headers, etc...)
1180 * Returns : 0 => Ok, everything else is an error.
1182 *********************************************************************/
1183 int load_permissions_file(struct client_state *csp)
1187 struct permissions_spec *b, *bl;
1188 char buf[BUFSIZ], *p, *q;
1190 struct file_list *fs;
\r
1193 if (!check_file_changed(current_permissions_file, permissions_file, &fs))
1195 /* No need to load */
1198 csp->permissions_list = current_permissions_file;
1204 goto load_permissions_error;
1207 fs->f = bl = (struct permissions_spec *)zalloc(sizeof(*bl));
1210 goto load_permissions_error;
1213 if ((fp = fopen(permissions_file, "r")) == NULL)
1215 goto load_permissions_error;
1220 * default_permissions is set in this file.
\r
1222 * Reset it to default first.
\r
1224 default_permissions = PERMIT_RE_FILTER;
\r
1226 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1230 permissions = PERMIT_COOKIE_SET | PERMIT_COOKIE_READ | PERMIT_POPUPS;
\r
1233 * FIXME: for() loop is a kludge. Want to loop around until we
\r
1234 * find a non-control character. Assume there will be at most 4
\r
1237 for (i = 0; i < 4; i++)
\r
1243 * Allow cookies to be read by the server, but do
\r
1244 * not allow them to be set.
\r
1246 permissions = (permissions & ~PERMIT_COOKIE_SET);
1252 * Allow server to set cookies but do not let the
\r
1253 * server read them.
\r
1255 permissions = (permissions & ~PERMIT_COOKIE_READ);
\r
1263 permissions = (permissions & ~PERMIT_POPUPS);
\r
1269 * Permit filtering using PCRS
\r
1271 permissions = (permissions | PERMIT_RE_FILTER);
\r
1277 * All of the above (maximum filtering).
\r
1279 permissions = PERMIT_RE_FILTER;
\r
1285 * FIXME: Should break out of the loop here.
\r
1292 * Elide any of the "special" chars from the
1293 * front of the pattern
1298 while ((*q++ = *p++) != '\0')
1304 /* a lines containing only "special" chars sets default */
1307 default_permissions = permissions;
1311 /* allocate a new node */
1312 if (((b = zalloc(sizeof(*b))) == NULL)
1316 goto load_permissions_error;
1319 /* add it to the list */
1324 b->permissions = permissions;
\r
1326 /* Save the URL pattern */
\r
1327 if (create_url_spec(b->url, buf))
\r
1330 goto load_permissions_error;
1336 #ifndef SPLIT_PROXY_ARGS
1337 if (!suppress_blocklists)
1339 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1341 #endif /* ndef SPLIT_PROXY_ARGS */
1343 /* the old one is now obsolete */
1344 if (current_permissions_file)
1346 current_permissions_file->unloader = unload_permissions_file;
1349 fs->next = files->next;
1351 current_permissions_file = fs;
1355 csp->permissions_list = fs;
1360 load_permissions_error:
1361 log_error(LOG_LEVEL_ERROR, "can't load permissions file '%s': %E", permissions_file);
1368 /*********************************************************************
1370 * Function : load_trustfile
1372 * Description : Read and parse a trustfile and add to files list.
1375 * 1 : csp = Current client state (buffers, headers, etc...)
1377 * Returns : 0 => Ok, everything else is an error.
1379 *********************************************************************/
1380 int load_trustfile(struct client_state *csp)
1384 struct block_spec *b, *bl;
1385 struct url_spec **tl;
1387 char buf[BUFSIZ], *p, *q;
1388 int reject, trusted;
1389 struct file_list *fs;
1391 if (!check_file_changed(current_trustfile, trustfile, &fs))
1393 /* No need to load */
1396 csp->tlist = current_trustfile;
1402 goto load_trustfile_error;
1405 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1408 goto load_trustfile_error;
1411 if ((fp = fopen(trustfile, "r")) == NULL)
1413 goto load_trustfile_error;
1418 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1434 while ((*p++ = *q++))
1440 /* skip blank lines */
1446 /* allocate a new node */
1447 if ((b = zalloc(sizeof(*b))) == NULL)
1450 goto load_trustfile_error;
1453 /* add it to the list */
1459 /* Save the URL pattern */
\r
1460 if (create_url_spec(b->url, buf))
\r
1463 goto load_trustfile_error;
1467 * save a pointer to URL's spec in the list of trusted URL's, too
1479 #ifndef SPLIT_PROXY_ARGS
1480 if (!suppress_blocklists)
1482 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1484 #endif /* ndef SPLIT_PROXY_ARGS */
1486 /* the old one is now obsolete */
1487 if (current_trustfile)
1489 current_trustfile->unloader = unload_trustfile;
1492 fs->next = files->next;
1494 current_trustfile = fs;
1503 load_trustfile_error:
1504 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
1508 #endif /* def TRUST_FILES */
1511 /*********************************************************************
1513 * Function : load_forwardfile
1515 * Description : Read and parse a forwardfile and add to files list.
1518 * 1 : csp = Current client state (buffers, headers, etc...)
1520 * Returns : 0 => Ok, everything else is an error.
1522 *********************************************************************/
1523 int load_forwardfile(struct client_state *csp)
1527 struct forward_spec *b, *bl;
1528 char buf[BUFSIZ], *p, *q, *tmp;
1530 int port, n, reject;
1531 struct file_list *fs;
1532 const struct gateway *gw;
1533 struct url_spec url[1];
1535 if (!check_file_changed(current_forwardfile, forwardfile, &fs))
1537 /* No need to load */
1540 csp->flist = current_forwardfile;
1546 goto load_forwardfile_error;
1549 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1551 if ((fs == NULL) || (bl == NULL))
1553 goto load_forwardfile_error;
1556 if ((fp = fopen(forwardfile, "r")) == NULL)
1558 goto load_forwardfile_error;
1563 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1569 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1573 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1577 strcpy(buf, vec[0]);
1586 while ((*p++ = *q++))
1592 /* skip lines containing only ~ */
1598 /* allocate a new node */
1599 if (((b = zalloc(sizeof(*b))) == NULL)
1601 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1606 goto load_forwardfile_error;
1609 /* add it to the list */
1613 /* save a copy of the orignal specification */
1614 if ((b->url->spec = strdup(buf)) == NULL)
1617 goto load_forwardfile_error;
1622 if ((p = strchr(buf, '/')))
1624 b->url->path = strdup(p);
1625 b->url->pathlen = strlen(b->url->path);
1630 b->url->path = NULL;
1631 b->url->pathlen = 0;
1639 sprintf(rebuf, "^(%s)", b->url->path);
1641 errcode = regcomp(b->url->preg, rebuf,
1642 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1646 size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
1650 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1653 goto load_forwardfile_error;
1658 freez(b->url->preg);
1661 if ((p = strchr(buf, ':')) == NULL)
1671 b->url->port = port;
1673 if ((b->url->domain = strdup(buf)) == NULL)
1676 goto load_forwardfile_error;
1679 /* split domain into components */
1680 *url = dsplit(b->url->domain);
1681 b->url->dbuf = url->dbuf;
1682 b->url->dcnt = url->dcnt;
1683 b->url->dvec = url->dvec;
1685 /* now parse the gateway specs */
1689 for (gw = gateways; gw->name; gw++)
1691 if (strcmp(gw->name, p) == 0)
1697 if (gw->name == NULL)
1699 goto load_forwardfile_error;
1702 /* save this as the gateway type */
1705 /* now parse the gateway host[:port] spec */
1708 if (strcmp(p, ".") != 0)
1710 b->gw->gateway_host = strdup(p);
1712 if ((p = strchr(b->gw->gateway_host, ':')))
1715 b->gw->gateway_port = atoi(p);
1718 if (b->gw->gateway_port <= 0)
1720 goto load_forwardfile_error;
1724 /* now parse the forwarding spec */
1727 if (strcmp(p, ".") != 0)
1729 b->gw->forward_host = strdup(p);
1731 if ((p = strchr(b->gw->forward_host, ':')))
1734 b->gw->forward_port = atoi(p);
1737 if (b->gw->forward_port <= 0)
1739 b->gw->forward_port = 8000;
1748 #ifndef SPLIT_PROXY_ARGS
1749 if (!suppress_blocklists)
1751 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1753 #endif /* ndef SPLIT_PROXY_ARGS */
1755 /* the old one is now obsolete */
1756 if (current_forwardfile)
1758 current_forwardfile->unloader = unload_forwardfile;
1761 fs->next = files->next;
1763 current_forwardfile = fs;
1772 load_forwardfile_error:
1773 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
1780 /*********************************************************************
1782 * Function : load_re_filterfile
1784 * Description : Load the re_filterfile. Each non-comment, non-empty
1785 * line is instantly added to the joblist, which is
1786 * a chained list of pcrs_job structs.
1789 * 1 : csp = Current client state (buffers, headers, etc...)
1791 * Returns : 0 => Ok, everything else is an error.
1793 *********************************************************************/
1794 int load_re_filterfile(struct client_state *csp)
1798 struct re_filterfile_spec *bl;
1799 struct file_list *fs;
1805 if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
1807 /* No need to load */
1810 csp->rlist = current_re_filterfile;
1816 goto load_re_filterfile_error;
1819 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1822 goto load_re_filterfile_error;
1825 /* Open the file or fail */
1826 if ((fp = fopen(re_filterfile, "r")) == NULL)
1828 goto load_re_filterfile_error;
1831 /* Read line by line */
1832 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1834 enlist( bl->patterns, buf );
1836 /* We have a meaningful line -> make it a job */
1837 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
1839 log_error(LOG_LEVEL_RE_FILTER,
1840 "Adding re_filter job %s failed with error %d.", buf, error);
1845 dummy->next = bl->joblist;
1846 bl->joblist = dummy;
1847 log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s succeeded.", buf);
1853 #ifndef SPLIT_PROXY_ARGS
1854 if (!suppress_blocklists)
1856 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1858 #endif /* ndef SPLIT_PROXY_ARGS */
1860 /* the old one is now obsolete */
1861 if ( NULL != current_re_filterfile )
1863 current_re_filterfile->unloader = unload_re_filterfile;
1866 fs->next = files->next;
1868 current_re_filterfile = fs;
1877 load_re_filterfile_error:
1878 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
1882 #endif /* def PCRS */
1885 /*********************************************************************
1887 * Function : add_loader
1889 * Description : Called from `load_config'. Called once for each input
1890 * file found in config.
1893 * 1 : loader = pointer to a function that can parse and load
1894 * the appropriate config file.
1898 *********************************************************************/
1899 void add_loader(int (*loader)(struct client_state *))
1903 for (i=0; i < NLOADERS; i++)
1905 if (loaders[i] == NULL)
1907 loaders[i] = loader;
1915 /*********************************************************************
1917 * Function : run_loader
1919 * Description : Called from `load_config' and `listen_loop'. This
1920 * function keeps the "csp" current with any file mods
1921 * since the last loop. If a file is unchanged, the
1922 * loader functions do NOT reload the file.
1925 * 1 : csp = Current client state (buffers, headers, etc...)
1927 * Returns : 0 => Ok, everything else is an error.
1929 *********************************************************************/
1930 int run_loader(struct client_state *csp)
1935 for (i=0; i < NLOADERS; i++)
1937 if (loaders[i] == NULL)
1941 ret |= (loaders[i])(csp);
1948 /*********************************************************************
1950 * Function : remove_all_loaders
1952 * Description : Remove all loaders from the list.
1958 *********************************************************************/
1959 void remove_all_loaders(void)
1961 memset( loaders, 0, sizeof( loaders ) );