Now compiles in cgi.[ch]
[privoxy.git] / loadcfg.c
1 const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.10 2001/06/03 19:11:54 oes Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
5  *
6  * Purpose     :  Loads settings from the configuration file into
7  *                global variables.  This file contains both the 
8  *                routine to load the configuration and the global
9  *                variables it writes to.
10  *
11  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
12  *                IJBSWA team.  http://ijbswa.sourceforge.net
13  *
14  *                Based on the Internet Junkbuster originally written
15  *                by and Copyright (C) 1997 Anonymous Coders and 
16  *                Junkbusters Corporation.  http://www.junkbusters.com
17  *
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.
23  *
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.
29  *
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.
35  *
36  * Revisions   :
37  *    $Log: loadcfg.c,v $
38  *    Revision 1.10  2001/06/03 19:11:54  oes
39  *    introduced confdir option
40  *
41  *    Revision 1.10  2001/06/03 11:03:48  oes
42  *    Makefile/in
43  *
44  *    introduced cgi.c
45  *
46  *    actions.c:
47  *
48  *    adapted to new enlist_unique arg format
49  *
50  *    conf loadcfg.c
51  *
52  *    introduced confdir option
53  *
54  *    filters.c filtrers.h
55  *
56  *     extracted-CGI relevant stuff
57  *
58  *    jbsockets.c
59  *
60  *     filled comment
61  *
62  *    jcc.c
63  *
64  *     support for new cgi mechansim
65  *
66  *    list.c list.h
67  *
68  *    functions for new list type: "map"
69  *    extended enlist_unique
70  *
71  *    miscutil.c .h
72  *    introduced bindup()
73  *
74  *    parsers.c parsers.h
75  *
76  *    deleted const struct interceptors
77  *
78  *    pcrs.c
79  *    added FIXME
80  *
81  *    project.h
82  *
83  *    added struct map
84  *    added struct http_response
85  *    changes struct interceptors to struct cgi_dispatcher
86  *    moved HTML stuff to cgi.h
87  *
88  *    re_filterfile:
89  *
90  *    changed
91  *
92  *    showargs.c
93  *    NO TIME LEFT
94  *
95  *    Revision 1.9  2001/06/01 20:06:24  jongfoster
96  *    Removed support for "tinygif" option - moved to actions file.
97  *
98  *    Revision 1.8  2001/05/31 21:27:13  jongfoster
99  *    Removed many options from the config file and into the
100  *    "actions" file: add_forwarded, suppress_vanilla_wafer,
101  *    wafer, add_header, user_agent, referer, from
102  *    Also globally replaced "permission" with "action".
103  *
104  *    Revision 1.7  2001/05/29 09:50:24  jongfoster
105  *    Unified blocklist/imagelist/permissionslist.
106  *    File format is still under discussion, but the internal changes
107  *    are (mostly) done.
108  *
109  *    Also modified interceptor behaviour:
110  *    - We now intercept all URLs beginning with one of the following
111  *      prefixes (and *only* these prefixes):
112  *        * http://i.j.b/
113  *        * http://ijbswa.sf.net/config/
114  *        * http://ijbswa.sourceforge.net/config/
115  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
116  *    - Internal changes so that intercepted and fast redirect pages
117  *      are not replaced with an image.
118  *    - Interceptors now have the option to send a binary page direct
119  *      to the client. (i.e. ijb-send-banner uses this)
120  *    - Implemented show-url-info interceptor.  (Which is why I needed
121  *      the above interceptors changes - a typical URL is
122  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
123  *      The previous mechanism would not have intercepted that, and
124  *      if it had been intercepted then it then it would have replaced
125  *      it with an image.)
126  *
127  *    Revision 1.6  2001/05/26 00:28:36  jongfoster
128  *    Automatic reloading of config file.
129  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
130  *    Most of the global variables have been moved to a new
131  *    struct configuration_spec, accessed through csp->config->globalname
132  *    Most of the globals remaining are used by the Win32 GUI.
133  *
134  *    Revision 1.5  2001/05/25 22:34:30  jongfoster
135  *    Hard tabs->Spaces
136  *
137  *    Revision 1.4  2001/05/22 18:46:04  oes
138  *
139  *    - Enabled filtering banners by size rather than URL
140  *      by adding patterns that replace all standard banner
141  *      sizes with the "Junkbuster" gif to the re_filterfile
142  *
143  *    - Enabled filtering WebBugs by providing a pattern
144  *      which kills all 1x1 images
145  *
146  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
147  *      which is selected by the (nonstandard and therefore
148  *      capital) letter 'U' in the option string.
149  *      It causes the quantifiers to be ungreedy by default.
150  *      Appending a ? turns back to greedy (!).
151  *
152  *    - Added a new interceptor ijb-send-banner, which
153  *      sends back the "Junkbuster" gif. Without imagelist or
154  *      MSIE detection support, or if tinygif = 1, or the
155  *      URL isn't recognized as an imageurl, a lame HTML
156  *      explanation is sent instead.
157  *
158  *    - Added new feature, which permits blocking remote
159  *      script redirects and firing back a local redirect
160  *      to the browser.
161  *      The feature is conditionally compiled, i.e. it
162  *      can be disabled with --disable-fast-redirects,
163  *      plus it must be activated by a "fast-redirects"
164  *      line in the config file, has its own log level
165  *      and of course wants to be displayed by show-proxy-args
166  *      Note: Boy, all the #ifdefs in 1001 locations and
167  *      all the fumbling with configure.in and acconfig.h
168  *      were *way* more work than the feature itself :-(
169  *
170  *    - Because a generic redirect template was needed for
171  *      this, tinygif = 3 now uses the same.
172  *
173  *    - Moved GIFs, and other static HTTP response templates
174  *      to project.h
175  *
176  *    - Some minor fixes
177  *
178  *    - Removed some >400 CRs again (Jon, you really worked
179  *      a lot! ;-)
180  *
181  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
182  *    Version 2.9.4 checkin.
183  *    - Merged popupfile and cookiefile, and added control over PCRS
184  *      filtering, in new "permissionsfile".
185  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
186  *      file error you now get a message box (in the Win32 GUI) rather
187  *      than the program exiting with no explanation.
188  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
189  *      skipping.
190  *    - Removed tabs from "config"
191  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
192  *    - Bumped up version number.
193  *
194  *    Revision 1.2  2001/05/17 23:01:01  oes
195  *     - Cleaned CRLF's from the sources and related files
196  *
197  *    Revision 1.1.1.1  2001/05/15 13:58:58  oes
198  *    Initial import of version 2.9.3 source tree
199  *
200  *
201  *********************************************************************/
202 \f
203
204 #include "config.h"
205
206 #include <stdio.h>
207 #include <sys/types.h>
208 #include <stdlib.h>
209 #include <string.h>
210 #include <signal.h>
211 #include <fcntl.h>
212 #include <errno.h>
213 #include <ctype.h>
214
215 #ifdef _WIN32
216
217 # include <sys/timeb.h>
218 # include <windows.h>
219 # include <io.h>
220 # include <process.h>
221 # ifdef TOGGLE
222 #  include <time.h>
223 # endif /* def TOGGLE */
224
225 # include "win32.h"
226 # ifndef _WIN_CONSOLE
227 #  include "w32log.h"
228 # endif /* ndef _WIN_CONSOLE */
229
230 #else /* ifndef _WIN32 */
231
232 # include <unistd.h>
233 # include <sys/time.h>
234 # include <sys/wait.h>
235 # include <sys/stat.h>
236 # include <signal.h>
237
238 #endif
239
240 #include "loadcfg.h"
241 #include "list.h"
242 #include "jcc.h"
243 #include "filters.h"
244 #include "loaders.h"
245 #include "showargs.h"
246 #include "parsers.h"
247 #include "killpopup.h"
248 #include "miscutil.h"
249 #include "errlog.h"
250 #include "jbsockets.h"
251 #include "gateway.h"
252
253 const char loadcfg_h_rcs[] = LOADCFG_H_VERSION;
254
255 /*
256  * Fix a problem with Solaris.  There should be no effect on other
257  * platforms.
258  * Solaris's isspace() is a macro which uses it's argument directly
259  * as an array index.  Therefore we need to make sure that high-bit
260  * characters generate +ve values, and ideally we also want to make
261  * the argument match the declared parameter type of "int".
262  */
263 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
264 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
265
266 #ifdef TOGGLE
267 /* by haroon - indicates if ijb is enabled */
268 int g_bToggleIJB        = 1;   /* JunkBusters is enabled by default. */
269 #endif
270
271 /* The filename of the configfile */
272 const char *configfile  = NULL;
273
274 /*
275  * The load_config function is now going to call `init_proxy_args',
276  * so it will need argc and argv.  So we need to have these
277  * globally available.
278  */
279 int Argc = 0;
280 const char **Argv = NULL;
281
282 static struct file_list *current_configfile = NULL;
283
284
285 /*
286  * This takes the "cryptic" hash of each keyword and aliases them to
287  * something a little more readable.  This also makes changing the
288  * hash values easier if they should change or the hash algorthm changes.
289  * Use the included "hash" program to find out what the hash will be
290  * for any string supplied on the command line.  (Or just put it in the
291  * config file and read the number from the error message in the log).
292  */
293
294
295 #define hash_aclfile                      1908516ul
296 #define hash_actions_file              3825730796ul /* FIXME "permissionsfile" */
297 #define hash_debug                          78263ul
298 #define hash_confdir                      1978389lu
299 #define hash_logdir                        422889lu
300 #define hash_forwardfile               1268669141ul
301 #define hash_jarfile                      2046641ul
302 #define hash_listen_address            1255650842ul
303 #define hash_logfile                      2114766ul
304 #define hash_re_filterfile             3877522444ul
305 #define hash_single_threaded           4250084780ul
306 #define hash_suppress_blocklists       1948693308ul
307 #define hash_toggle                        447966ul
308 #define hash_trust_info_url             449869467ul
309 #define hash_trustfile                   56494766ul
310
311 #define hash_hide_console              2048809870ul
312
313 #define hash_activity_animation        1817904738ul
314 #define hash_close_button_minimizes    3651284693ul
315 #define hash_log_buffer_size           2918070425ul
316 #define hash_log_font_name             2866730124ul
317 #define hash_log_font_size             2866731014ul
318 #define hash_log_highlight_messages    4032101240ul
319 #define hash_log_max_lines             2868344173ul
320 #define hash_log_messages              2291744899ul
321 #define hash_show_on_task_bar           215410365ul
322
323
324
325 /*********************************************************************
326  *
327  * Function    :  unload_configfile
328  *
329  * Description :  Free the config structure and all components.
330  *
331  * Parameters  :
332  *          1  :  data: struct configuration_spec to unload
333  *
334  * Returns     :  N/A
335  *
336  *********************************************************************/
337 void unload_configfile (void * data)
338 {
339    struct configuration_spec * config = (struct configuration_spec *)data;
340
341 #ifdef JAR_FILES
342    if ( NULL != config->jar )
343    {
344       fclose( config->jar );
345       config->jar = NULL;
346    }
347 #endif /* def JAR_FILES */
348
349    freez((char *)config->haddr);
350    freez((char *)config->logfile);
351
352    freez((char *)config->actions_file);
353    freez((char *)config->forwardfile);
354
355 #ifdef ACL_FILES
356    freez((char *)config->aclfile);
357 #endif /* def ACL_FILES */
358
359 #ifdef JAR_FILES
360    freez((char *)config->jarfile);
361 #endif /* def JAR_FILES */
362
363 #ifndef SPLIT_PROXY_ARGS
364    freez((char *)config->suppress_message);
365 #endif /* ndef SPLIT_PROXY_ARGS */
366
367 #ifdef PCRS
368    freez((char *)config->re_filterfile);
369 #endif /* def PCRS */
370
371 }
372
373
374 /*********************************************************************
375  *
376  * Function    :  load_config
377  *
378  * Description :  Load the config file and all parameters.
379  *
380  * Parameters  :
381  *          1  :  csp = Client state (the config member will be 
382  *                filled in by this function).
383  *
384  * Returns     :  0 => Ok, everything else is an error.
385  *
386  *********************************************************************/
387 struct configuration_spec * load_config(void)
388 {
389    char buf[BUFSIZ];
390    char *p, *q;
391    FILE *configfp = NULL;
392    struct configuration_spec * config = NULL;
393    struct client_state * fake_csp;
394
395    struct file_list *fs;
396
397    if (!check_file_changed(current_configfile, configfile, &fs))
398    {
399       /* No need to load */
400       return ((struct configuration_spec *)current_configfile->f);
401    }
402    if (!fs)
403    {
404       log_error(LOG_LEVEL_FATAL, "can't check configuration file '%s':  %E",
405                 configfile);
406    }
407
408    log_error(LOG_LEVEL_INFO, "loading configuration file '%s':", configfile);
409
410 #ifdef TOGGLE
411    g_bToggleIJB      = 1;
412 #endif
413
414    fs->f = config = (struct configuration_spec *)zalloc(sizeof(*config));
415
416    if (config==NULL)
417    {
418       freez(fs->filename);
419       freez(fs);
420       log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
421       /* Never get here - LOG_LEVEL_FATAL causes program exit */
422    }
423
424    /*
425     * This is backwards from how it's usually done.
426     * Following the usual pattern, "fs" would be stored in a member 
427     * variable in "csp", and then we'd access "config" from "fs->f",
428     * using a cast.  However, "config" is used so often that a 
429     * cast each time would be very ugly, and the extra indirection
430     * would waste CPU cycles.  Therefore we store "config" in
431     * "csp->config", and "fs" in "csp->config->config_file_list".
432     */
433    config->config_file_list = fs;
434
435    init_proxy_args(Argc, Argv, config);
436
437    /*
438     * Set to defaults
439     */
440
441    config->multi_threaded    = 1;
442    config->hport             = HADDR_PORT;
443
444    if ((configfp = fopen(configfile, "r")) == NULL)
445    {
446       log_error(LOG_LEVEL_FATAL, "can't open configuration file '%s':  %E",
447               configfile);
448       /* Never get here - LOG_LEVEL_FATAL causes program exit */
449    }
450
451    while (read_config_line(buf, sizeof(buf), configfp, fs) != NULL)
452    {
453       char cmd[BUFSIZ];
454       char arg[BUFSIZ];
455       char tmp[BUFSIZ];
456
457       char arg2[BUFSIZ];
458
459       strcpy(tmp, buf);
460
461       /* Copy command (i.e. up to space or tab) into cmd */
462       p = buf;
463       q = cmd;
464       while (*p && (*p != ' ') && (*p != '\t'))
465       {
466          *q++ = *p++;
467       }
468       *q = '\0';
469
470       /* Skip over the whitespace in buf */
471       while (*p && ((*p == ' ') || (*p == '\t')))
472       {
473          p++;
474       }
475
476       /* Copy the argument into arg */
477       strcpy(arg, p);
478
479       /* Should never happen, but check this anyway */
480       if (*cmd == '\0')
481       {
482          continue;
483       }
484
485       /* Make sure the command field is lower case */
486       for (p=cmd; *p; p++)
487       {
488          if (ijb_isupper(*p))
489          {
490             *p = ijb_tolower(*p);
491          }
492       }
493
494       /* Save the argument for show-proxy-args */
495       savearg(cmd, arg, config);
496
497
498       switch( hash_string( cmd ) )
499       {
500 #ifdef TRUST_FILES
501          case hash_trustfile :
502             freez((char *)config->trustfile);
503                                 snprintf(arg2, BUFSIZ, "%s/%s", config->confdir, arg);
504             config->trustfile = strdup(arg2);
505             continue;
506
507          case hash_trust_info_url :
508             enlist(config->trust_info, arg);
509             continue;
510 #endif /* def TRUST_FILES */
511
512          case hash_debug :
513             config->debug |= atoi(arg);
514             continue;
515
516          case hash_confdir :
517             config->confdir = strdup(arg);
518             continue;            
519
520          case hash_logdir :
521             config->logdir = strdup(arg);
522             continue;            
523
524          case hash_single_threaded :
525             config->multi_threaded = 0;
526             continue;
527
528          case hash_actions_file :
529             freez((char *)config->actions_file);
530                                 snprintf(arg2, BUFSIZ, "%s/%s", config->confdir, arg);
531             config->actions_file = strdup(arg2);
532             continue;
533
534          case hash_logfile :
535             freez((char *)config->logfile);
536                                 snprintf(arg2, BUFSIZ, "%s/%s", config->logdir, arg);
537             config->logfile = strdup(arg2);
538             continue;
539
540 #ifdef JAR_FILES
541          case hash_jarfile :
542             freez((char *)config->jarfile);
543                                 snprintf(arg2, BUFSIZ, "%s/%s", config->logdir, arg);
544             config->jarfile = strdup(arg2);
545             continue;
546 #endif /* def JAR_FILES */
547
548          case hash_listen_address :
549             freez((char *)config->haddr);
550             config->haddr = strdup(arg);
551             continue;
552
553          case hash_forwardfile :
554             freez((char *)config->forwardfile);
555                                 snprintf(arg2, BUFSIZ, "%s/%s", config->confdir, arg);
556             config->forwardfile = strdup(arg2);
557             continue;
558
559 #ifdef ACL_FILES
560          case hash_aclfile :
561             freez((char *)config->aclfile);
562                                 snprintf(arg2, BUFSIZ, "%s/%s", config->confdir, arg);
563             config->aclfile = strdup(arg2);
564             continue;
565 #endif /* def ACL_FILES */
566
567 #ifdef PCRS
568          case hash_re_filterfile :
569             freez((char *)config->re_filterfile);
570             config->re_filterfile = strdup(arg);
571             continue;
572 #endif /* def PCRS */
573
574 #ifdef _WIN_CONSOLE
575          case hash_hide_console :
576             hideConsole = 1;
577             continue;
578 #endif /*def _WIN_CONSOLE*/
579
580 #ifndef SPLIT_PROXY_ARGS
581          case hash_suppress_blocklists :
582             if (arg[0] != '\0')
583             {
584                config->suppress_message = strdup(arg);
585             }
586             else
587             {
588                /* There will be NO reference in proxy-args. */
589                config->suppress_message = NULL;
590             }
591
592             config->suppress_blocklists = 1;
593             continue;
594 #endif /* ndef SPLIT_PROXY_ARGS */
595
596 #ifdef TOGGLE
597          case hash_toggle :
598             g_bToggleIJB = atoi(arg);
599             continue;
600 #endif /* def TOGGLE */
601
602 #if defined(_WIN32) && ! defined(_WIN_CONSOLE)
603          case hash_activity_animation :
604             g_bShowActivityAnimation = atoi(arg);
605             continue;
606
607          case hash_log_messages :
608             g_bLogMessages = atoi(arg);
609             continue;
610
611          case hash_log_highlight_messages :
612             g_bHighlightMessages = atoi(arg);
613             continue;
614
615          case hash_log_buffer_size :
616             g_bLimitBufferSize = atoi(arg);
617             continue;
618
619          case hash_log_max_lines :
620             g_nMaxBufferLines = atoi(arg);
621             continue;
622
623          case hash_log_font_name :
624             strcpy( g_szFontFaceName, arg );
625             continue;
626
627          case hash_log_font_size :
628             g_nFontSize = atoi(arg);
629             continue;
630
631          case hash_show_on_task_bar :
632             g_bShowOnTaskBar = atoi(arg);
633             continue;
634
635          case hash_close_button_minimizes :
636             g_bCloseHidesWindow = atoi(arg);
637             continue;
638 #endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
639
640          /* Warnings about unsupported features */
641
642 #ifndef PCRS
643          case hash_re_filterfile :
644 #endif /* ndef PCRS */
645 #ifndef TOGGLE
646          case hash_toggle :
647 #endif /* ndef TOGGLE */
648 #if defined(_WIN_CONSOLE) || ! defined(_WIN32)
649          case hash_activity_animation :
650          case hash_log_messages :
651          case hash_log_highlight_messages :
652          case hash_log_buffer_size :
653          case hash_log_max_lines :
654          case hash_log_font_name :
655          case hash_log_font_size :
656          case hash_show_on_task_bar :
657          case hash_close_button_minimizes :
658 #endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
659 #ifndef _WIN_CONSOLE
660          case hash_hide_console :
661 #endif /* ndef _WIN_CONSOLE */
662 #ifndef JAR_FILES
663          case hash_jarfile :
664 #endif /* ndef JAR_FILES */
665 #ifndef ACL_FILES
666          case hash_aclfile :
667 #endif /* ndef ACL_FILES */
668 #ifdef SPLIT_PROXY_ARGS
669          case hash_suppress_blocklists :
670 #endif /* def SPLIT_PROXY_ARGS */
671             log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd);
672             continue;
673
674          default :
675             /*
676              * I decided that I liked this better as a warning than an
677              * error.  To change back to an error, just change log level
678              * to LOG_LEVEL_FATAL.
679              */
680             log_error(LOG_LEVEL_ERROR, "Unrecognized directive (%lulu) in "
681                   "configuration file: \"%s\"", hash_string( cmd ), buf);
682             p = malloc( BUFSIZ );
683             if (p != NULL)
684             {
685                sprintf( p, "<br>\nWARNING: unrecognized directive : %s<br><br>\n", buf );
686                config->proxy_args_invocation = strsav( config->proxy_args_invocation, p );
687                freez( p );
688             }
689             continue;
690       } /* end switch( hash_string(cmd) ) */
691    } /* end while ( read_config_line(...) ) */
692
693    fclose(configfp);
694
695    init_error_log(Argv[0], config->logfile, config->debug);
696
697    if (config->actions_file)
698    {
699       add_loader(load_actions_file, config);
700    }
701
702    if (config->forwardfile)
703    {
704       add_loader(load_forwardfile, config);
705    }
706
707 #ifdef ACL_FILES
708    if (config->aclfile)
709    {
710       add_loader(load_aclfile, config);
711    }
712 #endif /* def ACL_FILES */
713
714 #ifdef PCRS
715    if (config->re_filterfile)
716    {
717       add_loader(load_re_filterfile, config);
718    }
719 #endif /* def PCRS */
720
721 #ifdef TRUST_FILES
722    if (config->trustfile)
723    {
724       add_loader(load_trustfile, config);
725    }
726 #endif
727
728 #ifdef JAR_FILES
729    if ( NULL != config->jarfile )
730    {
731       if ( NULL == (config->jar = fopen(config->jarfile, "a")) )
732       {
733          log_error(LOG_LEVEL_FATAL, "can't open jarfile '%s': %E", config->jarfile);
734          /* Never get here - LOG_LEVEL_FATAL causes program exit */
735       }
736       setbuf(config->jar, NULL);
737    }
738 #endif /* def JAR_FILES */
739
740    if ( NULL == config->haddr )
741    {
742       config->haddr = strdup( HADDR_DEFAULT );
743    }
744
745    if ( NULL != config->haddr )
746    {
747       if ((p = strchr(config->haddr, ':')))
748       {
749          *p++ = '\0';
750          if (*p)
751          {
752             config->hport = atoi(p);
753          }
754       }
755
756       if (config->hport <= 0)
757       {
758          *--p = ':';
759          log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
760          /* Never get here - LOG_LEVEL_FATAL causes program exit */
761       }
762       if (*config->haddr == '\0')
763       {
764          config->haddr = NULL;
765       }
766    }
767
768    /*
769     * Want to run all the loaders once now.
770     *
771     * Need to set up a fake csp, so they can get to the config.
772     */
773    fake_csp = (struct client_state *) zalloc (sizeof(*fake_csp));
774    fake_csp->config = config;
775
776    if (run_loader(fake_csp))
777    {
778       freez(fake_csp);
779       log_error(LOG_LEVEL_FATAL, "A loader failed while loading config file. Exiting.");
780       /* Never get here - LOG_LEVEL_FATAL causes program exit */
781    }
782    freez(fake_csp);
783
784 #ifndef SPLIT_PROXY_ARGS
785    if (!suppress_blocklists)
786    {
787       fs->proxy_args = strsav(fs->proxy_args, "</pre>");
788    }
789 #endif /* ndef SPLIT_PROXY_ARGS */
790
791 /* FIXME: this is a kludge for win32 */
792 #if defined(_WIN32) && !defined (_WIN_CONSOLE)
793
794    g_actions_file     = config->actions_file;
795    g_forwardfile      = config->forwardfile;
796 #ifdef ACL_FILES
797    g_aclfile          = config->aclfile;
798 #endif /* def ACL_FILES */
799 #ifdef PCRS
800    g_re_filterfile    = config->re_filterfile;
801 #endif
802 #ifdef TRUST_FILES
803    g_trustfile        = config->trustfile;
804 #endif
805    
806
807 #endif /* defined(_WIN32) && !defined (_WIN_CONSOLE) */
808 /* FIXME: end kludge */
809
810
811    config->need_bind = 1;
812
813    if (current_configfile)
814    {
815       struct configuration_spec * oldcfg = (struct configuration_spec *)
816                                            current_configfile->f;
817       /*
818        * Check if config->haddr,hport == oldcfg->haddr,hport
819        *
820        * The following could be written more compactly as a single,
821        * (unreadably long) if statement.
822        */
823       config->need_bind = 0;
824       if (config->hport != oldcfg->hport)
825       {
826          config->need_bind = 1;
827       }
828       else if (config->haddr == NULL)
829       {
830          if (oldcfg->haddr != NULL)
831          {
832             config->need_bind = 1;
833          }
834       }
835       else if (oldcfg->haddr == NULL)
836       {
837          config->need_bind = 1;
838       }
839       else if (0 != strcmp(config->haddr, oldcfg->haddr))
840       {
841          config->need_bind = 1;
842       }
843
844       current_configfile->unloader = unload_configfile;
845    }
846
847    fs->next = files->next;
848    files->next = fs;
849
850    current_configfile = fs;
851
852    return (config);
853 }
854
855
856 /*
857   Local Variables:
858   tab-width: 3
859   end:
860 */