1 const char loaders_rcs[] = "$Id: loaders.c,v 1.7 2001/05/26 00:28:36 jongfoster 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.7 2001/05/26 00:28:36 jongfoster
39 * Automatic reloading of config file.
40 * Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
41 * Most of the global variables have been moved to a new
42 * struct configuration_spec, accessed through csp->config->globalname
43 * Most of the globals remaining are used by the Win32 GUI.
45 * Revision 1.6 2001/05/23 12:27:33 oes
47 * Fixed ugly indentation of my last changes
49 * Revision 1.5 2001/05/23 10:39:05 oes
50 * - Added support for escaping the comment character
51 * in config files by a backslash
52 * - Added support for line continuation in config
54 * - Fixed a buffer overflow bug with long config lines
56 * Revision 1.4 2001/05/22 18:56:28 oes
59 * Revision 1.3 2001/05/20 01:21:20 jongfoster
60 * Version 2.9.4 checkin.
61 * - Merged popupfile and cookiefile, and added control over PCRS
62 * filtering, in new "permissionsfile".
63 * - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
64 * file error you now get a message box (in the Win32 GUI) rather
65 * than the program exiting with no explanation.
66 * - Made killpopup use the PCRS MIME-type checking and HTTP-header
68 * - Removed tabs from "config"
69 * - Moved duplicated url parsing code in "loaders.c" to a new funcition.
70 * - Bumped up version number.
72 * Revision 1.2 2001/05/17 23:01:01 oes
73 * - Cleaned CRLF's from the sources and related files
75 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
76 * Initial import of version 2.9.3 source tree
79 *********************************************************************/
86 #include <sys/types.h>
104 #include "miscutil.h"
108 #ifndef SPLIT_PROXY_ARGS
110 #include "showargs.h"
111 #endif /* ndef SPLIT_PROXY_ARGS */
113 const char loaders_h_rcs[] = LOADERS_H_VERSION;
115 /* Fix a problem with Solaris. There should be no effect on other
117 * Solaris's isspace() is a macro which uses it's argument directly
118 * as an array index. Therefore we need to make sure that high-bit
119 * characters generate +ve values, and ideally we also want to make
120 * the argument match the declared parameter type of "int".
122 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
126 * Currently active files.
127 * These are also entered in the main linked list of files.
129 static struct file_list *current_blockfile = NULL;
130 static struct file_list *current_permissions_file = NULL;
131 static struct file_list *current_forwardfile = NULL;
134 static struct file_list *current_aclfile = NULL;
135 #endif /* def ACL_FILES */
137 #ifdef USE_IMAGE_LIST
138 static struct file_list *current_imagefile = NULL;
139 #endif /* def USE_IMAGE_LIST */
142 static struct file_list *current_trustfile = NULL;
143 #endif /* def TRUST_FILES */
146 static struct file_list *current_re_filterfile = NULL;
147 #endif /* def PCRS */
150 static int create_url_spec(struct url_spec * url, char * buf);
153 /*********************************************************************
157 * Description : Basically a mark and sweep garbage collector, it is run
158 * (by the parent thread) every once in a while to reclaim memory.
160 * It uses a mark and sweep strategy:
161 * 1) mark all files as inactive
163 * 2) check with each client:
164 * if it is active, mark its files as active
165 * if it is inactive, free its resources
167 * 3) free the resources of all of the files that
168 * are still marked as inactive (and are obsolete).
170 * N.B. files that are not obsolete don't have an unloader defined.
176 *********************************************************************/
179 struct file_list *fl, *nfl;
180 struct client_state *csp, *ncsp;
182 /* clear all of the file's active flags */
183 for ( fl = files->next; NULL != fl; fl = fl->next )
188 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
192 /* mark this client's files as active */
195 * Always have a configuration file.
196 * (Also note the slightly non-standard extra
199 ncsp->config->config_file_list->active = 1;
201 if (ncsp->blist) /* block files */
203 ncsp->blist->active = 1;
206 if (ncsp->permissions_list) /* permissions files */
208 ncsp->permissions_list->active = 1;
211 if (ncsp->flist) /* forward files */
213 ncsp->flist->active = 1;
217 if (ncsp->alist) /* acl files */
219 ncsp->alist->active = 1;
221 #endif /* def ACL_FILES */
223 #ifdef USE_IMAGE_LIST
224 if (ncsp->ilist) /* image files */
226 ncsp->ilist->active = 1;
228 #endif /* def USE_IMAGE_LIST */
231 if (ncsp->rlist) /* perl re files */
233 ncsp->rlist->active = 1;
235 #endif /* def PCRS */
238 if (ncsp->tlist) /* trust files */
240 ncsp->tlist->active = 1;
242 #endif /* def TRUST_FILES */
247 /* this client one is not active, release its resources */
248 csp->next = ncsp->next;
250 freez(ncsp->ip_addr_str);
251 freez(ncsp->referrer);
252 freez(ncsp->x_forwarded);
253 freez(ncsp->ip_addr_str);
254 freez(ncsp->iob->buf);
256 free_http_request(ncsp->http);
258 destroy_list(ncsp->headers);
259 destroy_list(ncsp->cookie_list);
267 #endif /* def STATISTICS */
273 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
275 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
277 fl->next = nfl->next;
279 (nfl->unloader)(nfl->f);
281 #ifndef SPLIT_PROXY_ARGS
282 freez(nfl->proxy_args);
283 #endif /* ndef SPLIT_PROXY_ARGS */
285 freez(nfl->filename);
294 /*********************************************************************
296 * Function : create_url_spec
298 * Description : Creates a "url_spec" structure from a string.
299 * When finished, free with unload_url().
302 * 1 : url = Target url_spec to be filled in. Must be
303 * zeroed out before the call (e.g. using zalloc).
304 * 2 : buf = Source pattern, null terminated. NOTE: The
305 * contents of this buffer are destroyed by this
306 * function. If this function succeeds, the
307 * buffer is copied to url->spec. If this
308 * function fails, the contents of the buffer
311 * Returns : 0 => Ok, everything else is an error.
313 *********************************************************************/
314 static int create_url_spec(struct url_spec * url, char * buf)
317 struct url_spec tmp_url[1];
319 /* paranoia - should never happen. */
320 if ((url == NULL) || (buf == NULL))
325 /* save a copy of the orignal specification */
326 if ((url->spec = strdup(buf)) == NULL)
331 if ((p = strchr(buf, '/')))
333 if (NULL == (url->path = strdup(p)))
338 url->pathlen = strlen(url->path);
352 if (NULL == (url->preg = zalloc(sizeof(*url->preg))))
359 sprintf(rebuf, "^(%s)", url->path);
361 errcode = regcomp(url->preg, rebuf,
362 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
367 url->preg, buf, sizeof(buf));
371 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
382 if ((p = strchr(buf, ':')) == NULL)
392 if ((url->domain = strdup(buf)) == NULL)
398 #endif /* def REGEX */
402 /* split domain into components */
404 *tmp_url = dsplit(url->domain);
405 url->dbuf = tmp_url->dbuf;
406 url->dcnt = tmp_url->dcnt;
407 url->dvec = tmp_url->dvec;
413 /*********************************************************************
415 * Function : unload_url
417 * Description : Called from the "unloaders". Freez the url
418 * structure elements.
421 * 1 : url = pointer to a url_spec structure.
425 *********************************************************************/
426 static void unload_url(struct url_spec *url)
428 if (url == NULL) return;
447 /*********************************************************************
449 * Function : unload_aclfile
451 * Description : Unloads an aclfile.
454 * 1 : f = the data structure associated with the aclfile.
458 *********************************************************************/
459 static void unload_aclfile(void *f)
461 struct access_control_list *b = (struct access_control_list *)f;
462 if (b == NULL) return;
464 unload_aclfile(b->next);
469 #endif /* def ACL_FILES */
471 /*********************************************************************
473 * Function : unload_blockfile
475 * Description : Unloads a blockfile.
478 * 1 : f = the data structure associated with the blockfile.
482 *********************************************************************/
483 static void unload_blockfile(void *f)
485 struct block_spec *b = (struct block_spec *)f;
486 if (b == NULL) return;
488 unload_blockfile(b->next);
497 #ifdef USE_IMAGE_LIST
498 /*********************************************************************
500 * Function : unload_imagefile
502 * Description : Unloads an imagefile.
505 * 1 : f = the data structure associated with the imagefile.
509 *********************************************************************/
510 static void unload_imagefile(void *f)
512 struct block_spec *b = (struct block_spec *)f;
513 if (b == NULL) return;
515 unload_imagefile(b->next);
522 #endif /* def USE_IMAGE_LIST */
525 /*********************************************************************
527 * Function : unload_permissions_file
529 * Description : Unloads a permissions file.
532 * 1 : file_data = the data structure associated with the
537 *********************************************************************/
538 static void unload_permissions_file(void *file_data)
540 struct permissions_spec * next;
541 struct permissions_spec * cur = (struct permissions_spec *)file_data;
545 unload_url(cur->url);
554 /*********************************************************************
556 * Function : unload_trustfile
558 * Description : Unloads a trustfile.
561 * 1 : f = the data structure associated with the trustfile.
565 *********************************************************************/
566 static void unload_trustfile(void *f)
568 struct block_spec *b = (struct block_spec *)f;
569 if (b == NULL) return;
571 unload_trustfile(b->next);
578 #endif /* def TRUST_FILES */
581 /*********************************************************************
583 * Function : unload_forwardfile
585 * Description : Unloads a forwardfile.
588 * 1 : f = the data structure associated with the forwardfile.
592 *********************************************************************/
593 static void unload_forwardfile(void *f)
595 struct forward_spec *b = (struct forward_spec *)f;
596 if (b == NULL) return;
598 unload_forwardfile(b->next);
602 freez(b->gw->gateway_host);
603 freez(b->gw->forward_host);
611 /*********************************************************************
613 * Function : unload_re_filterfile
615 * Description : Unload the re_filter list.
618 * 1 : f = the data structure associated with the filterfile.
622 *********************************************************************/
623 static void unload_re_filterfile(void *f)
626 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
628 if (b == NULL) return;
630 destroy_list(b->patterns);
632 joblist = b->joblist;
633 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
638 #endif /* def PCRS */
641 /*********************************************************************
643 * Function : check_file_changed
645 * Description : Helper function to check if a file needs reloading.
646 * If "current" is still current, return it. Otherwise
647 * allocates a new (zeroed) "struct file_list", fills
648 * in the disk file name and timestamp, and returns it.
651 * 1 : current = The file_list currently being used - will
652 * be checked to see if it is out of date.
653 * May be NULL (which is treated as out of
655 * 2 : filename = Name of file to check.
656 * 3 : newfl = New file list. [Output only]
657 * This will be set to NULL, OR a struct
658 * file_list newly allocated on the
659 * heap, with the filename and lastmodified
660 * fields filled, standard header giving file
661 * name in proxy_args, and all others zeroed.
662 * (proxy_args is only filled in if !defined
663 * SPLIT_PROXY_ARGS and !suppress_blocklists).
665 * Returns : If file unchanged: 0 (and sets newfl == NULL)
666 * If file changed: 1 and sets newfl != NULL
667 * On error: 1 and sets newfl == NULL
669 *********************************************************************/
670 int check_file_changed(const struct file_list * current,
671 const char * filename,
672 struct file_list ** newfl)
674 struct file_list *fs;
675 struct stat statbuf[1];
679 if (stat(filename, statbuf) < 0)
681 /* Error, probably file not found. */
686 && (current->lastmodified == statbuf->st_mtime)
687 && (0 == strcmp(current->filename, filename)))
692 fs = (struct file_list *)zalloc(sizeof(struct file_list));
696 /* Out of memory error */
700 fs->filename = strdup(filename);
701 fs->lastmodified = statbuf->st_mtime;
703 if (fs->filename == NULL)
705 /* Out of memory error */
710 #ifndef SPLIT_PROXY_ARGS
711 if (!suppress_blocklists)
713 char * p = html_encode(filename);
716 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
717 fs->proxy_args = strsav(fs->proxy_args, p);
718 fs->proxy_args = strsav(fs->proxy_args,
719 "' contains the following patterns</h2>\n");
722 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
724 #endif /* ndef SPLIT_PROXY_ARGS */
731 /*********************************************************************
733 * Function : read_config_line
735 * Description : Read a single non-empty line from a file and return
736 * it. Trims comments, leading and trailing whitespace
737 * and respects escaping of newline and comment char.
738 * Also writes the file to fs->proxy_args.
741 * 1 : buf = Buffer to use.
742 * 2 : buflen = Size of buffer in bytes.
743 * 3 : fp = File to read from
744 * 4 : fs = File will be written to fs->proxy_args. May
745 * be NULL to disable this feature.
747 * Returns : NULL on EOF or error
748 * Otherwise, returns buf.
750 *********************************************************************/
751 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
754 char linebuf[BUFSIZ];
759 while (fgets(linebuf, sizeof(linebuf), fp))
761 #ifndef SPLIT_PROXY_ARGS
762 if (fs && !suppress_blocklists)
764 char *html_line = html_encode(linebuf);
765 if (html_line != NULL)
767 fs->proxy_args = strsav(fs->proxy_args, html_line);
770 fs->proxy_args = strsav(fs->proxy_args, "<br>");
772 #endif /* ndef SPLIT_PROXY_ARGS */
774 /* Trim off newline */
775 if ((p = strpbrk(linebuf, "\r\n")) != NULL)
780 /* Line continuation? Trim escape and set flag. */
781 if ((p != linebuf) && (*--p == '\\'))
787 /* If there's a comment char.. */
788 if ((p = strpbrk(linebuf, "#")) != NULL)
790 /* ..and it's escaped, left-shift the line over the escape. */
791 if ((p != linebuf) && (*(p-1) == '\\'))
794 while ((*q++ = *p++) != '\0') /* nop */;
796 /* Else, chop off the rest of the line */
803 /* Trim leading whitespace */
805 while (*p && ijb_isspace(*p))
812 /* There is something other than whitespace on the line. */
814 /* Move the data to the start of buf */
817 /* strcpy that can cope with overlap. */
819 while ((*q++ = *p++) != '\0')
825 /* Trim trailing whitespace */
826 p = linebuf + strlen(linebuf) - 1;
829 * Note: the (p >= linebuf) below is paranoia, it's not really needed.
830 * When p == linebuf then ijb_isspace(*p) will be false and we'll drop
833 while ((p >= linebuf) && ijb_isspace(*p))
839 /* More paranoia. This if statement is always true. */
842 strncat(buf, linebuf, buflen - strlen(buf));
862 /*********************************************************************
864 * Function : load_aclfile
866 * Description : Read and parse an aclfile and add to files list.
869 * 1 : csp = Current client state (buffers, headers, etc...)
871 * Returns : 0 => Ok, everything else is an error.
873 *********************************************************************/
874 int load_aclfile(struct client_state *csp)
877 char buf[BUFSIZ], *v[3], *p;
879 struct access_control_list *a, *bl;
880 struct file_list *fs;
882 if (!check_file_changed(current_aclfile, csp->config->aclfile, &fs))
884 /* No need to load */
887 csp->alist = current_aclfile;
893 goto load_aclfile_error;
896 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
901 goto load_aclfile_error;
904 fp = fopen(csp->config->aclfile, "r");
908 goto load_aclfile_error;
911 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
913 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
915 /* allocate a new node */
916 a = (struct access_control_list *) zalloc(sizeof(*a));
924 goto load_aclfile_error;
927 /* add it to the list */
934 if (acl_addr(v[2], a->dst) < 0)
936 goto load_aclfile_error;
941 if (acl_addr(v[1], a->src) < 0)
943 goto load_aclfile_error;
947 if (strcmpic(p, "permit") == 0)
949 a->action = ACL_PERMIT;
953 if (strcmpic(p, "deny") == 0)
955 a->action = ACL_DENY;
961 goto load_aclfile_error;
967 #ifndef SPLIT_PROXY_ARGS
968 if (!suppress_blocklists)
970 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
972 #endif /* ndef SPLIT_PROXY_ARGS */
976 current_aclfile->unloader = unload_aclfile;
979 fs->next = files->next;
981 current_aclfile = fs;
991 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E",
992 csp->config->aclfile);
996 #endif /* def ACL_FILES */
999 /*********************************************************************
1001 * Function : load_blockfile
1003 * Description : Read and parse a blockfile and add to files list.
1006 * 1 : csp = Current client state (buffers, headers, etc...)
1008 * Returns : 0 => Ok, everything else is an error.
1010 *********************************************************************/
1011 int load_blockfile(struct client_state *csp)
1015 struct block_spec *b, *bl;
1016 char buf[BUFSIZ], *p, *q;
1018 struct file_list *fs;
1020 if (!check_file_changed(current_blockfile, csp->config->blockfile, &fs))
1022 /* No need to load */
1025 csp->blist = current_blockfile;
1031 goto load_blockfile_error;
1034 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
1037 goto load_blockfile_error;
1040 if ((fp = fopen(csp->config->blockfile, "r")) == NULL)
1042 goto load_blockfile_error;
1045 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1054 while ((*p++ = *q++))
1060 /* skip lines containing only ~ */
1066 /* allocate a new node */
1067 if ((b = zalloc(sizeof(*b))) == NULL)
1070 goto load_blockfile_error;
1073 /* add it to the list */
1079 /* Save the URL pattern */
1080 if (create_url_spec(b->url, buf))
1083 goto load_blockfile_error;
1089 #ifndef SPLIT_PROXY_ARGS
1090 if (!suppress_blocklists)
1092 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1094 #endif /* ndef SPLIT_PROXY_ARGS */
1096 /* the old one is now obsolete */
1097 if (current_blockfile)
1099 current_blockfile->unloader = unload_blockfile;
1102 fs->next = files->next;
1104 current_blockfile = fs;
1113 load_blockfile_error:
1114 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", csp->config->blockfile);
1120 #ifdef USE_IMAGE_LIST
1121 /*********************************************************************
1123 * Function : load_imagefile
1125 * Description : Read and parse an imagefile and add to files list.
1128 * 1 : csp = Current client state (buffers, headers, etc...)
1130 * Returns : 0 => Ok, everything else is an error.
1132 *********************************************************************/
1133 int load_imagefile(struct client_state *csp)
1137 struct block_spec *b, *bl;
1138 char buf[BUFSIZ], *p, *q;
1140 struct file_list *fs;
1142 if (!check_file_changed(current_imagefile, csp->config->imagefile, &fs))
1144 /* No need to load */
1147 csp->ilist = current_imagefile;
1153 goto load_imagefile_error;
1156 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1159 goto load_imagefile_error;
1162 if ((fp = fopen(csp->config->imagefile, "r")) == NULL)
1164 goto load_imagefile_error;
1167 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1176 while ((*p++ = *q++))
1182 /* skip lines containing only ~ */
1188 /* allocate a new node */
1189 if ((b = zalloc(sizeof(*b))) == NULL)
1192 goto load_imagefile_error;
1195 /* add it to the list */
1201 /* Save the URL pattern */
1202 if (create_url_spec(b->url, buf))
1205 goto load_imagefile_error;
1211 #ifndef SPLIT_PROXY_ARGS
1212 if (!suppress_blocklists)
1214 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1216 #endif /* ndef SPLIT_PROXY_ARGS */
1218 /* the old one is now obsolete */
1219 if (current_imagefile)
1221 current_imagefile->unloader = unload_imagefile;
1224 fs->next = files->next;
1226 current_imagefile = fs;
1235 load_imagefile_error:
1236 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", csp->config->imagefile);
1240 #endif /* def USE_IMAGE_LIST */
1243 /*********************************************************************
1245 * Function : load_permissions_file
1247 * Description : Read and parse a permissions file and add to files
1251 * 1 : csp = Current client state (buffers, headers, etc...)
1253 * Returns : 0 => Ok, everything else is an error.
1255 *********************************************************************/
1256 int load_permissions_file(struct client_state *csp)
1260 struct permissions_spec *b, *bl;
1261 char buf[BUFSIZ], *p, *q;
1263 struct file_list *fs;
1266 if (!check_file_changed(current_permissions_file, csp->config->permissions_file, &fs))
1268 /* No need to load */
1271 csp->permissions_list = current_permissions_file;
1277 goto load_permissions_error;
1280 fs->f = bl = (struct permissions_spec *)zalloc(sizeof(*bl));
1283 goto load_permissions_error;
1286 if ((fp = fopen(csp->config->permissions_file, "r")) == NULL)
1288 goto load_permissions_error;
1293 * default_permissions is set in this file.
1295 * Reset it to default first.
1297 csp->config->default_permissions = PERMIT_RE_FILTER;
1299 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1303 permissions = PERMIT_COOKIE_SET | PERMIT_COOKIE_READ | PERMIT_POPUPS;
1306 * FIXME: for() loop is a kludge. Want to loop around until we
1307 * find a non-control character. Assume there will be at most 4
1310 for (i = 0; i < 4; i++)
1316 * Allow cookies to be read by the server, but do
1317 * not allow them to be set.
1319 permissions = (permissions & ~PERMIT_COOKIE_SET);
1325 * Allow server to set cookies but do not let the
1328 permissions = (permissions & ~PERMIT_COOKIE_READ);
1336 permissions = (permissions & ~PERMIT_POPUPS);
1342 * Permit filtering using PCRS
1344 permissions = (permissions | PERMIT_RE_FILTER);
1350 * All of the above (maximum filtering).
1352 permissions = PERMIT_RE_FILTER;
1358 * FIXME: Should break out of the loop here.
1365 * Elide any of the "special" chars from the
1366 * front of the pattern
1371 while ((*q++ = *p++) != '\0')
1377 /* a lines containing only "special" chars sets default */
1380 csp->config->default_permissions = permissions;
1384 /* allocate a new node */
1385 if (((b = zalloc(sizeof(*b))) == NULL)
1389 goto load_permissions_error;
1392 /* add it to the list */
1397 b->permissions = permissions;
1399 /* Save the URL pattern */
1400 if (create_url_spec(b->url, buf))
1403 goto load_permissions_error;
1409 #ifndef SPLIT_PROXY_ARGS
1410 if (!suppress_blocklists)
1412 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1414 #endif /* ndef SPLIT_PROXY_ARGS */
1416 /* the old one is now obsolete */
1417 if (current_permissions_file)
1419 current_permissions_file->unloader = unload_permissions_file;
1422 fs->next = files->next;
1424 current_permissions_file = fs;
1428 csp->permissions_list = fs;
1433 load_permissions_error:
1434 log_error(LOG_LEVEL_ERROR, "can't load permissions file '%s': %E",
1435 csp->config->permissions_file);
1442 /*********************************************************************
1444 * Function : load_trustfile
1446 * Description : Read and parse a trustfile and add to files list.
1449 * 1 : csp = Current client state (buffers, headers, etc...)
1451 * Returns : 0 => Ok, everything else is an error.
1453 *********************************************************************/
1454 int load_trustfile(struct client_state *csp)
1458 struct block_spec *b, *bl;
1459 struct url_spec **tl;
1461 char buf[BUFSIZ], *p, *q;
1462 int reject, trusted;
1463 struct file_list *fs;
1465 if (!check_file_changed(current_trustfile, csp->config->trustfile, &fs))
1467 /* No need to load */
1470 csp->tlist = current_trustfile;
1476 goto load_trustfile_error;
1479 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1482 goto load_trustfile_error;
1485 if ((fp = fopen(csp->config->trustfile, "r")) == NULL)
1487 goto load_trustfile_error;
1490 tl = csp->config->trust_list;
1492 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1508 while ((*p++ = *q++))
1514 /* skip blank lines */
1520 /* allocate a new node */
1521 if ((b = zalloc(sizeof(*b))) == NULL)
1524 goto load_trustfile_error;
1527 /* add it to the list */
1533 /* Save the URL pattern */
1534 if (create_url_spec(b->url, buf))
1537 goto load_trustfile_error;
1541 * save a pointer to URL's spec in the list of trusted URL's, too
1553 #ifndef SPLIT_PROXY_ARGS
1554 if (!suppress_blocklists)
1556 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1558 #endif /* ndef SPLIT_PROXY_ARGS */
1560 /* the old one is now obsolete */
1561 if (current_trustfile)
1563 current_trustfile->unloader = unload_trustfile;
1566 fs->next = files->next;
1568 current_trustfile = fs;
1577 load_trustfile_error:
1578 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E",
1579 csp->config->trustfile);
1583 #endif /* def TRUST_FILES */
1586 /*********************************************************************
1588 * Function : load_forwardfile
1590 * Description : Read and parse a forwardfile and add to files list.
1593 * 1 : csp = Current client state (buffers, headers, etc...)
1595 * Returns : 0 => Ok, everything else is an error.
1597 *********************************************************************/
1598 int load_forwardfile(struct client_state *csp)
1602 struct forward_spec *b, *bl;
1603 char buf[BUFSIZ], *p, *q, *tmp;
1606 struct file_list *fs;
1607 const struct gateway *gw;
1609 if (!check_file_changed(current_forwardfile, csp->config->forwardfile, &fs))
1611 /* No need to load */
1614 csp->flist = current_forwardfile;
1620 goto load_forwardfile_error;
1623 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1625 if ((fs == NULL) || (bl == NULL))
1627 goto load_forwardfile_error;
1630 if ((fp = fopen(csp->config->forwardfile, "r")) == NULL)
1632 goto load_forwardfile_error;
1637 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1643 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1647 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1651 strcpy(buf, vec[0]);
1660 while ((*p++ = *q++))
1666 /* skip lines containing only ~ */
1672 /* allocate a new node */
1673 if (((b = zalloc(sizeof(*b))) == NULL)
1677 goto load_forwardfile_error;
1680 /* add it to the list */
1684 b->reject = reject;
\r
1686 /* Save the URL pattern */
\r
1687 if (create_url_spec(b->url, buf))
\r
1690 goto load_forwardfile_error;
\r
1693 /* now parse the gateway specs */
1697 for (gw = gateways; gw->name; gw++)
1699 if (strcmp(gw->name, p) == 0)
1705 if (gw->name == NULL)
1707 goto load_forwardfile_error;
1710 /* save this as the gateway type */
1713 /* now parse the gateway host[:port] spec */
1716 if (strcmp(p, ".") != 0)
1718 b->gw->gateway_host = strdup(p);
1720 if ((p = strchr(b->gw->gateway_host, ':')))
1723 b->gw->gateway_port = atoi(p);
1726 if (b->gw->gateway_port <= 0)
1728 goto load_forwardfile_error;
1732 /* now parse the forwarding spec */
1735 if (strcmp(p, ".") != 0)
1737 b->gw->forward_host = strdup(p);
1739 if ((p = strchr(b->gw->forward_host, ':')))
1742 b->gw->forward_port = atoi(p);
1745 if (b->gw->forward_port <= 0)
1747 b->gw->forward_port = 8000;
1756 #ifndef SPLIT_PROXY_ARGS
1757 if (!suppress_blocklists)
1759 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1761 #endif /* ndef SPLIT_PROXY_ARGS */
1763 /* the old one is now obsolete */
1764 if (current_forwardfile)
1766 current_forwardfile->unloader = unload_forwardfile;
1769 fs->next = files->next;
1771 current_forwardfile = fs;
1780 load_forwardfile_error:
1781 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E",
1782 csp->config->forwardfile);
1789 /*********************************************************************
1791 * Function : load_re_filterfile
1793 * Description : Load the re_filterfile. Each non-comment, non-empty
1794 * line is instantly added to the joblist, which is
1795 * a chained list of pcrs_job structs.
1798 * 1 : csp = Current client state (buffers, headers, etc...)
1800 * Returns : 0 => Ok, everything else is an error.
1802 *********************************************************************/
1803 int load_re_filterfile(struct client_state *csp)
1807 struct re_filterfile_spec *bl;
1808 struct file_list *fs;
1814 if (!check_file_changed(current_re_filterfile, csp->config->re_filterfile, &fs))
1816 /* No need to load */
1819 csp->rlist = current_re_filterfile;
1825 goto load_re_filterfile_error;
1828 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1831 goto load_re_filterfile_error;
1834 /* Open the file or fail */
1835 if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
1837 goto load_re_filterfile_error;
1840 /* Read line by line */
1841 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1843 enlist( bl->patterns, buf );
1845 /* We have a meaningful line -> make it a job */
1846 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
1848 log_error(LOG_LEVEL_RE_FILTER,
1849 "Adding re_filter job %s failed with error %d.", buf, error);
1854 dummy->next = bl->joblist;
1855 bl->joblist = dummy;
1856 log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s succeeded.", buf);
1862 #ifndef SPLIT_PROXY_ARGS
1863 if (!suppress_blocklists)
1865 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1867 #endif /* ndef SPLIT_PROXY_ARGS */
1869 /* the old one is now obsolete */
1870 if ( NULL != current_re_filterfile )
1872 current_re_filterfile->unloader = unload_re_filterfile;
1875 fs->next = files->next;
1877 current_re_filterfile = fs;
1886 load_re_filterfile_error:
1887 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E",
1888 csp->config->re_filterfile);
1892 #endif /* def PCRS */
1895 /*********************************************************************
1897 * Function : add_loader
1899 * Description : Called from `load_config'. Called once for each input
1900 * file found in config.
1903 * 1 : loader = pointer to a function that can parse and load
1904 * the appropriate config file.
1905 * 2 : config = The configuration_spec to add the loader to.
1909 *********************************************************************/
1910 void add_loader(int (*loader)(struct client_state *),
1911 struct configuration_spec * config)
1915 for (i=0; i < NLOADERS; i++)
1917 if (config->loaders[i] == NULL)
1919 config->loaders[i] = loader;
1927 /*********************************************************************
1929 * Function : run_loader
1931 * Description : Called from `load_config' and `listen_loop'. This
1932 * function keeps the "csp" current with any file mods
1933 * since the last loop. If a file is unchanged, the
1934 * loader functions do NOT reload the file.
1937 * 1 : csp = Current client state (buffers, headers, etc...)
1938 * Must be non-null. Reads: "csp->config"
1939 * Writes: various data members.
1941 * Returns : 0 => Ok, everything else is an error.
1943 *********************************************************************/
1944 int run_loader(struct client_state *csp)
1949 for (i=0; i < NLOADERS; i++)
1951 if (csp->config->loaders[i] == NULL)
1955 ret |= (csp->config->loaders[i])(csp);